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 <rtl/math.hxx>
21
22 #include <iterator>
23
24 #include <InternalDataProvider.hxx>
25 #include <LabeledDataSequence.hxx>
26 #include <DataSource.hxx>
27 #include <XMLRangeHelper.hxx>
28 #include <CommonFunctors.hxx>
29 #include <UncachedDataSequence.hxx>
30 #include <DataSourceHelper.hxx>
31 #include <ChartModel.hxx>
32 #include <ChartModelHelper.hxx>
33 #include <DiagramHelper.hxx>
34 #include <ExplicitCategoriesProvider.hxx>
35
36 #include <com/sun/star/chart2/data/XDataSequence.hpp>
37 #include <com/sun/star/chart/ChartDataRowSource.hpp>
38 #include <cppuhelper/supportsservice.hxx>
39 #include <comphelper/sequenceashashmap.hxx>
40 #include <comphelper/property.hxx>
41 #include <tools/diagnose_ex.h>
42
43 #include <vector>
44 #include <algorithm>
45
46 namespace com::sun::star::chart2 { class XChartDocument; }
47
48 using namespace ::com::sun::star;
49 using namespace ::std;
50
51 using ::com::sun::star::uno::Reference;
52 using ::com::sun::star::uno::Sequence;
53
54 namespace chart
55 {
56
57 namespace
58 {
59
60 constexpr OUStringLiteral lcl_aCategoriesRangeName = u"categories";
61 const char lcl_aCategoriesLevelRangeNamePrefix[] = "categoriesL "; //L <-> level
62 const char lcl_aCategoriesPointRangeNamePrefix[] = "categoriesP "; //P <-> point
63 constexpr OUStringLiteral lcl_aCategoriesRoleName = u"categories";
64 const char lcl_aLabelRangePrefix[] = "label ";
65 constexpr OUStringLiteral lcl_aCompleteRange = u"all";
66
67 typedef std::multimap< OUString, uno::WeakReference< chart2::data::XDataSequence > >
68 lcl_tSequenceMap;
69
lcl_AnyToStringSequence(const std::vector<uno::Any> & aAnySeq)70 std::vector< OUString > lcl_AnyToStringSequence( const std::vector< uno::Any >& aAnySeq )
71 {
72 std::vector< OUString > aResult;
73 aResult.resize( aAnySeq.size() );
74 int i = 0;
75 for (const uno::Any& aAny : aAnySeq)
76 aResult[i++] = CommonFunctors::AnyToString()(aAny);
77 return aResult;
78 }
79
lcl_StringToAnyVector(const css::uno::Sequence<OUString> & aStringSeq)80 std::vector< uno::Any > lcl_StringToAnyVector( const css::uno::Sequence< OUString >& aStringSeq )
81 {
82 std::vector< uno::Any > aResult;
83 aResult.resize( aStringSeq.getLength() );
84 int i = 0;
85 for (const OUString& aStr : aStringSeq)
86 aResult[i++] = CommonFunctors::makeAny<OUString>()(aStr);
87 return aResult;
88 }
89
90 struct lcl_setModified
91 {
operator ()chart::__anon1db070c30111::lcl_setModified92 void operator() ( const lcl_tSequenceMap::value_type & rMapEntry )
93 {
94 // convert weak reference to reference
95 Reference< chart2::data::XDataSequence > xSeq( rMapEntry.second );
96 if( xSeq.is())
97 {
98 Reference< util::XModifiable > xMod( xSeq, uno::UNO_QUERY );
99 if( xMod.is())
100 xMod->setModified( true );
101 }
102 }
103 };
104
105 struct lcl_internalizeSeries
106 {
lcl_internalizeSerieschart::__anon1db070c30111::lcl_internalizeSeries107 lcl_internalizeSeries( InternalData & rInternalData,
108 InternalDataProvider & rProvider,
109 bool bConnectToModel, bool bDataInColumns ) :
110 m_rInternalData( rInternalData ),
111 m_rProvider( rProvider ),
112 m_bConnectToModel( bConnectToModel ),
113 m_bDataInColumns( bDataInColumns )
114 {}
operator ()chart::__anon1db070c30111::lcl_internalizeSeries115 void operator() ( const Reference< chart2::XDataSeries > & xSeries )
116 {
117 Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
118 Reference< chart2::data::XDataSink > xSink( xSeries, uno::UNO_QUERY );
119 if( !(xSource.is() && xSink.is()) )
120 return;
121
122 Sequence< Reference< chart2::data::XLabeledDataSequence > > aOldSeriesData = xSource->getDataSequences();
123 Sequence< Reference< chart2::data::XLabeledDataSequence > > aNewSeriesData( aOldSeriesData.getLength() );
124 for( sal_Int32 i=0; i<aOldSeriesData.getLength(); ++i )
125 {
126 sal_Int32 nNewIndex( m_bDataInColumns ? m_rInternalData.appendColumn() : m_rInternalData.appendRow() );
127 OUString aIdentifier( OUString::number( nNewIndex ));
128 //@todo: deal also with genericXDataSequence
129 Reference< chart2::data::XNumericalDataSequence > xValues( aOldSeriesData[i]->getValues(), uno::UNO_QUERY );
130 Reference< chart2::data::XTextualDataSequence > xLabel( aOldSeriesData[i]->getLabel(), uno::UNO_QUERY );
131 Reference< chart2::data::XDataSequence > xNewValues;
132
133 if( xValues.is() )
134 {
135 auto aValues( comphelper::sequenceToContainer<std::vector< double >>( xValues->getNumericalData()));
136 if( m_bDataInColumns )
137 m_rInternalData.setColumnValues( nNewIndex, aValues );
138 else
139 m_rInternalData.setRowValues( nNewIndex, aValues );
140 if( m_bConnectToModel )
141 {
142 xNewValues.set( m_rProvider.createDataSequenceByRangeRepresentation( aIdentifier ));
143 comphelper::copyProperties(
144 Reference< beans::XPropertySet >( xValues, uno::UNO_QUERY ),
145 Reference< beans::XPropertySet >( xNewValues, uno::UNO_QUERY ));
146 }
147 }
148
149 if( xLabel.is() )
150 {
151 if( m_bDataInColumns )
152 m_rInternalData.setComplexColumnLabel( nNewIndex, lcl_StringToAnyVector( xLabel->getTextualData() ) );
153 else
154 m_rInternalData.setComplexRowLabel( nNewIndex, lcl_StringToAnyVector( xLabel->getTextualData() ) );
155 if( m_bConnectToModel )
156 {
157 Reference< chart2::data::XDataSequence > xNewLabel(
158 m_rProvider.createDataSequenceByRangeRepresentation( lcl_aLabelRangePrefix + aIdentifier ));
159 comphelper::copyProperties(
160 Reference< beans::XPropertySet >( xLabel, uno::UNO_QUERY ),
161 Reference< beans::XPropertySet >( xNewLabel, uno::UNO_QUERY ));
162 aNewSeriesData[i].set( new LabeledDataSequence( xNewValues, xNewLabel ) );
163 }
164 }
165 else
166 {
167 if( m_bConnectToModel )
168 aNewSeriesData[i].set( new LabeledDataSequence( xNewValues ) );
169 }
170 }
171 if( m_bConnectToModel )
172 xSink->setData( aNewSeriesData );
173 }
174
175 private:
176 InternalData & m_rInternalData;
177 InternalDataProvider & m_rProvider;
178 bool m_bConnectToModel;
179 bool m_bDataInColumns;
180 };
181
182 struct lcl_copyFromLevel
183 {
184 public:
185
lcl_copyFromLevelchart::__anon1db070c30111::lcl_copyFromLevel186 explicit lcl_copyFromLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
187 {}
188
operator ()chart::__anon1db070c30111::lcl_copyFromLevel189 uno::Any operator() ( const vector< uno::Any >& rVector )
190 {
191 uno::Any aRet;
192 if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) )
193 aRet = rVector[m_nLevel];
194 return aRet;
195 }
196
197 private:
198 sal_Int32 m_nLevel;
199 };
200
201 struct lcl_getStringFromLevelVector
202 {
203 public:
204
lcl_getStringFromLevelVectorchart::__anon1db070c30111::lcl_getStringFromLevelVector205 explicit lcl_getStringFromLevelVector( sal_Int32 nLevel ) : m_nLevel( nLevel )
206 {}
207
operator ()chart::__anon1db070c30111::lcl_getStringFromLevelVector208 OUString operator() ( const vector< uno::Any >& rVector )
209 {
210 OUString aString;
211 if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) )
212 aString = CommonFunctors::AnyToString()(rVector[m_nLevel]);
213 return aString;
214 }
215
216 private:
217 sal_Int32 m_nLevel;
218 };
219
220 struct lcl_setAnyAtLevel
221 {
222 public:
223
lcl_setAnyAtLevelchart::__anon1db070c30111::lcl_setAnyAtLevel224 explicit lcl_setAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
225 {}
226
operator ()chart::__anon1db070c30111::lcl_setAnyAtLevel227 vector< uno::Any > operator() ( const vector< uno::Any >& rVector, const uno::Any& rNewValue )
228 {
229 vector< uno::Any > aRet( rVector );
230 if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) )
231 aRet.resize( m_nLevel+1 );
232 aRet[ m_nLevel ]=rNewValue;
233 return aRet;
234 }
235
236 private:
237 sal_Int32 m_nLevel;
238 };
239
240 struct lcl_setAnyAtLevelFromStringSequence
241 {
242 public:
243
lcl_setAnyAtLevelFromStringSequencechart::__anon1db070c30111::lcl_setAnyAtLevelFromStringSequence244 explicit lcl_setAnyAtLevelFromStringSequence( sal_Int32 nLevel ) : m_nLevel( nLevel )
245 {}
246
operator ()chart::__anon1db070c30111::lcl_setAnyAtLevelFromStringSequence247 vector< uno::Any > operator() ( const vector< uno::Any >& rVector, const OUString& rNewValue )
248 {
249 vector< uno::Any > aRet( rVector );
250 if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) )
251 aRet.resize( m_nLevel+1 );
252 aRet[ m_nLevel ] <<= rNewValue;
253 return aRet;
254 }
255
256 private:
257 sal_Int32 m_nLevel;
258 };
259
260 struct lcl_insertAnyAtLevel
261 {
262 public:
263
lcl_insertAnyAtLevelchart::__anon1db070c30111::lcl_insertAnyAtLevel264 explicit lcl_insertAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
265 {}
266
operator ()chart::__anon1db070c30111::lcl_insertAnyAtLevel267 void operator() ( vector< uno::Any >& rVector )
268 {
269 if( m_nLevel >= static_cast< sal_Int32 >(rVector.size()) )
270 {
271 rVector.resize( m_nLevel + 1 );
272 }
273 else
274 {
275 rVector.insert( rVector.begin() + m_nLevel, uno::Any() );
276 }
277 }
278
279 private:
280 sal_Int32 m_nLevel;
281 };
282
283 struct lcl_removeAnyAtLevel
284 {
285 public:
286
lcl_removeAnyAtLevelchart::__anon1db070c30111::lcl_removeAnyAtLevel287 explicit lcl_removeAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
288 {}
289
operator ()chart::__anon1db070c30111::lcl_removeAnyAtLevel290 void operator() ( vector< uno::Any >& rVector )
291 {
292 if( m_nLevel < static_cast<sal_Int32>(rVector.size()) )
293 {
294 rVector.erase(rVector.begin() + m_nLevel);
295 }
296 }
297
298 private:
299 sal_Int32 m_nLevel;
300 };
301
302 } // anonymous namespace
303
InternalDataProvider()304 InternalDataProvider::InternalDataProvider()
305 : m_bDataInColumns( true )
306 {}
307
InternalDataProvider(const Reference<chart2::XChartDocument> & xChartDoc,bool bConnectToModel,bool bDefaultDataInColumns)308 InternalDataProvider::InternalDataProvider(
309 const Reference< chart2::XChartDocument > & xChartDoc,
310 bool bConnectToModel,
311 bool bDefaultDataInColumns)
312 : m_bDataInColumns( bDefaultDataInColumns )
313 {
314 try
315 {
316 Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDoc ) );
317 if( xDiagram.is())
318 {
319 Reference< frame::XModel > xChartModel = xChartDoc;
320
321 //data in columns?
322 {
323 OUString aRangeString;
324 bool bFirstCellAsLabel = true;
325 bool bHasCategories = true;
326 uno::Sequence< sal_Int32 > aSequenceMapping;
327 const bool bSomethingDetected(
328 DataSourceHelper::detectRangeSegmentation(
329 xChartModel, aRangeString, aSequenceMapping, m_bDataInColumns, bFirstCellAsLabel, bHasCategories ));
330
331 // #i120559# if no data was available, restore default
332 if(!bSomethingDetected && m_bDataInColumns != bDefaultDataInColumns)
333 {
334 m_bDataInColumns = bDefaultDataInColumns;
335 }
336 }
337
338 // categories
339 {
340 vector< vector< uno::Any > > aNewCategories;//inner count is level
341 {
342 ChartModel& rModel = dynamic_cast<ChartModel&>(*xChartModel);
343 ExplicitCategoriesProvider aExplicitCategoriesProvider(ChartModelHelper::getFirstCoordinateSystem(xChartModel), rModel);
344
345 const Sequence< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() );
346 sal_Int32 nLevelCount = rSplitCategoriesList.getLength();
347 for( sal_Int32 nL = 0; nL<nLevelCount; nL++ )
348 {
349 Reference< chart2::data::XLabeledDataSequence > xLDS( rSplitCategoriesList[nL] );
350 if( !xLDS.is() )
351 continue;
352 Sequence< uno::Any > aDataSeq;
353 Reference< chart2::data::XDataSequence > xSeq( xLDS->getValues() );
354 if( xSeq.is() )
355 aDataSeq = xSeq->getData();
356 sal_Int32 nLength = aDataSeq.getLength();
357 sal_Int32 nCatLength = static_cast< sal_Int32 >(aNewCategories.size());
358 if( nCatLength < nLength )
359 aNewCategories.resize( nLength );
360 else if( nLength < nCatLength )
361 aDataSeq.realloc( nCatLength );
362 transform( aNewCategories.begin(), aNewCategories.end(), aDataSeq.getConstArray(),
363 aNewCategories.begin(), lcl_setAnyAtLevel(nL) );
364 }
365 if( !nLevelCount )
366 {
367 Sequence< OUString > aSimplecategories = aExplicitCategoriesProvider.getSimpleCategories();
368 sal_Int32 nLength = aSimplecategories.getLength();
369 aNewCategories.reserve( nLength );
370 for( sal_Int32 nN=0; nN<nLength; nN++)
371 {
372 aNewCategories.push_back( { uno::Any(aSimplecategories[nN]) } );
373 }
374 }
375 }
376
377 if( m_bDataInColumns )
378 m_aInternalData.setComplexRowLabels( aNewCategories );
379 else
380 m_aInternalData.setComplexColumnLabels( aNewCategories );
381 if( bConnectToModel )
382 DiagramHelper::setCategoriesToDiagram( new LabeledDataSequence(
383 createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName )), xDiagram );
384 }
385
386 // data series
387 std::vector< Reference< chart2::XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xChartDoc ));
388 lcl_internalizeSeries ftor( m_aInternalData, *this, bConnectToModel, m_bDataInColumns );
389 for( const auto& rxScreen : aSeriesVector )
390 ftor( rxScreen );
391 }
392 }
393 catch( const uno::Exception & )
394 {
395 DBG_UNHANDLED_EXCEPTION("chart2");
396 }
397 }
398
399 // copy-CTOR
InternalDataProvider(const InternalDataProvider & rOther)400 InternalDataProvider::InternalDataProvider( const InternalDataProvider & rOther ) :
401 impl::InternalDataProvider_Base(rOther),
402 m_aSequenceMap( rOther.m_aSequenceMap ),
403 m_aInternalData( rOther.m_aInternalData ),
404 m_bDataInColumns( rOther.m_bDataInColumns )
405 {}
406
~InternalDataProvider()407 InternalDataProvider::~InternalDataProvider()
408 {}
409
addDataSequenceToMap(const OUString & rRangeRepresentation,const Reference<chart2::data::XDataSequence> & xSequence)410 void InternalDataProvider::addDataSequenceToMap(
411 const OUString & rRangeRepresentation,
412 const Reference< chart2::data::XDataSequence > & xSequence )
413 {
414 m_aSequenceMap.emplace(
415 rRangeRepresentation,
416 uno::WeakReference< chart2::data::XDataSequence >( xSequence ));
417 }
418
deleteMapReferences(const OUString & rRangeRepresentation)419 void InternalDataProvider::deleteMapReferences( const OUString & rRangeRepresentation )
420 {
421 // set sequence to deleted by setting its range to an empty string
422 tSequenceMapRange aRange( m_aSequenceMap.equal_range( rRangeRepresentation ));
423 for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
424 {
425 Reference< chart2::data::XDataSequence > xSeq( aIt->second );
426 if( xSeq.is())
427 {
428 Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
429 if( xNamed.is())
430 xNamed->setName( OUString());
431 }
432 }
433 // remove from map
434 m_aSequenceMap.erase( aRange.first, aRange.second );
435 }
436
adaptMapReferences(const OUString & rOldRangeRepresentation,const OUString & rNewRangeRepresentation)437 void InternalDataProvider::adaptMapReferences(
438 const OUString & rOldRangeRepresentation,
439 const OUString & rNewRangeRepresentation )
440 {
441 tSequenceMapRange aRange( m_aSequenceMap.equal_range( rOldRangeRepresentation ));
442 tSequenceMap aNewElements;
443 for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
444 {
445 Reference< chart2::data::XDataSequence > xSeq( aIt->second );
446 if( xSeq.is())
447 {
448 Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
449 if( xNamed.is())
450 xNamed->setName( rNewRangeRepresentation );
451 }
452 aNewElements.emplace( rNewRangeRepresentation, aIt->second );
453 }
454 // erase map values for old index
455 m_aSequenceMap.erase( aRange.first, aRange.second );
456 // add new entries for values with new index
457 m_aSequenceMap.insert( aNewElements.begin(), aNewElements.end() );
458 }
459
increaseMapReferences(sal_Int32 nBegin,sal_Int32 nEnd)460 void InternalDataProvider::increaseMapReferences(
461 sal_Int32 nBegin, sal_Int32 nEnd )
462 {
463 for( sal_Int32 nIndex = nEnd - 1; nIndex >= nBegin; --nIndex )
464 {
465 adaptMapReferences( OUString::number( nIndex ),
466 OUString::number( nIndex + 1 ));
467 adaptMapReferences( lcl_aLabelRangePrefix + OUString::number( nIndex ),
468 lcl_aLabelRangePrefix + OUString::number( nIndex + 1 ));
469 }
470 }
471
decreaseMapReferences(sal_Int32 nBegin,sal_Int32 nEnd)472 void InternalDataProvider::decreaseMapReferences(
473 sal_Int32 nBegin, sal_Int32 nEnd )
474 {
475 for( sal_Int32 nIndex = nBegin; nIndex < nEnd; ++nIndex )
476 {
477 adaptMapReferences( OUString::number( nIndex ),
478 OUString::number( nIndex - 1 ));
479 adaptMapReferences( lcl_aLabelRangePrefix + OUString::number( nIndex ),
480 lcl_aLabelRangePrefix + OUString::number( nIndex - 1 ));
481 }
482 }
483
createDataSequenceAndAddToMap(const OUString & rRangeRepresentation)484 Reference< chart2::data::XDataSequence > InternalDataProvider::createDataSequenceAndAddToMap(
485 const OUString & rRangeRepresentation )
486 {
487 Reference<chart2::data::XDataSequence> xSeq = createDataSequenceFromArray(rRangeRepresentation, u"");
488 if (xSeq.is())
489 return xSeq;
490
491 xSeq.set(new UncachedDataSequence(this, rRangeRepresentation));
492 addDataSequenceToMap(rRangeRepresentation, xSeq);
493 return xSeq;
494 }
495
496 uno::Reference<chart2::data::XDataSequence>
createDataSequenceFromArray(const OUString & rArrayStr,std::u16string_view rRole)497 InternalDataProvider::createDataSequenceFromArray( const OUString& rArrayStr, std::u16string_view rRole )
498 {
499 if (rArrayStr.indexOf('{') != 0 || rArrayStr[rArrayStr.getLength()-1] != '}')
500 {
501 // Not an array string.
502 return uno::Reference<chart2::data::XDataSequence>();
503 }
504
505 bool bAllNumeric = true;
506 uno::Reference<chart2::data::XDataSequence> xSeq;
507
508 const sal_Unicode* p = rArrayStr.getStr();
509 const sal_Unicode* pEnd = p + rArrayStr.getLength();
510 const sal_Unicode* pElem = nullptr;
511 OUString aElem;
512
513 std::vector<OUString> aRawElems;
514 ++p; // Skip the first '{'.
515 --pEnd; // Skip the last '}'.
516 bool bInQuote = false;
517 for (; p != pEnd; ++p)
518 {
519 // Skip next "" within the title text: it's an escaped double quotation mark.
520 if (bInQuote && *p == '"' && *(p + 1) == '"')
521 {
522 if (!pElem)
523 pElem = p;
524 ++p;
525 }
526 else if (*p == '"')
527 {
528 bInQuote = !bInQuote;
529 if (bInQuote)
530 {
531 // Opening quote.
532 pElem = nullptr;
533 }
534 else
535 {
536 // Closing quote.
537 if (pElem)
538 aElem = OUString(pElem, p-pElem);
539 // Non empty string
540 if (!aElem.isEmpty())
541 bAllNumeric = false;
542 // Restore also escaped double quotation marks
543 aRawElems.push_back(aElem.replaceAll("\"\"", "\""));
544 pElem = nullptr;
545 aElem.clear();
546
547 ++p; // Skip '"'.
548 if (p == pEnd)
549 break;
550 }
551 }
552 else if (*p == ';' && !bInQuote)
553 {
554 // element separator.
555 if (pElem)
556 aElem = OUString(pElem, p-pElem);
557 aRawElems.push_back(aElem);
558 pElem = nullptr;
559 aElem.clear();
560 }
561 else if (!pElem)
562 pElem = p;
563 }
564
565 if (pElem)
566 {
567 aElem = OUString(pElem, p-pElem);
568 aRawElems.push_back(aElem);
569 }
570
571 if (rRole == u"values-y" || rRole == u"values-first" || rRole == u"values-last" ||
572 rRole == u"values-min" || rRole == u"values-max" || rRole == u"values-size")
573 {
574 // Column values. Append a new data column and populate it.
575
576 std::vector<double> aValues;
577 aValues.reserve(aRawElems.size());
578 for (const OUString & aRawElem : aRawElems)
579 {
580 if (aRawElem.isEmpty())
581 aValues.push_back(NAN);
582 else
583 aValues.push_back(aRawElem.toDouble());
584 }
585 sal_Int32 n = m_aInternalData.appendColumn();
586
587 m_aInternalData.setColumnValues(n, aValues);
588
589 OUString aRangeRep = OUString::number(n);
590 xSeq.set(new UncachedDataSequence(this, aRangeRep));
591 addDataSequenceToMap(aRangeRep, xSeq);
592 }
593 else if (rRole == u"values-x")
594 {
595 std::vector<double> aValues;
596 aValues.reserve(aRawElems.size());
597 if (bAllNumeric)
598 {
599 for (const OUString & aRawElem : aRawElems)
600 {
601 if (!aRawElem.isEmpty())
602 aValues.push_back(aRawElem.toDouble());
603 else
604 aValues.push_back(NAN);
605 }
606 }
607 else
608 {
609 for (size_t i = 0; i < aRawElems.size(); ++i)
610 aValues.push_back(i+1);
611 }
612
613 sal_Int32 n = m_aInternalData.appendColumn();
614 m_aInternalData.setColumnValues(n, aValues);
615
616 OUString aRangeRep = OUString::number(n);
617 xSeq.set(new UncachedDataSequence(this, aRangeRep));
618 addDataSequenceToMap(aRangeRep, xSeq);
619 }
620 else if (rRole == u"categories")
621 {
622 // Category labels.
623
624 for (size_t i = 0; i < aRawElems.size(); ++i)
625 {
626 std::vector<uno::Any> aLabels(1, uno::Any(aRawElems[i]));
627 m_aInternalData.setComplexRowLabel(i, aLabels);
628 }
629
630 xSeq.set(new UncachedDataSequence(this, lcl_aCategoriesRangeName));
631 addDataSequenceToMap(lcl_aCategoriesRangeName, xSeq);
632 }
633 else if (rRole == u"label")
634 {
635 // Data series label. There should be only one element. This always
636 // goes to the last data column.
637 sal_Int32 nColSize = m_aInternalData.getColumnCount();
638 if (!aRawElems.empty() && nColSize)
639 {
640 std::vector<uno::Any> aLabels(1, uno::Any(aRawElems[0]));
641 m_aInternalData.setComplexColumnLabel(nColSize-1, aLabels);
642
643 OUString aRangeRep = lcl_aLabelRangePrefix + OUString::number(nColSize-1);
644 xSeq.set(new UncachedDataSequence(this, aRangeRep));
645 addDataSequenceToMap(aRangeRep, xSeq);
646 }
647 }
648
649 return xSeq;
650 }
651
createDataSequenceAndAddToMap(const OUString & rRangeRepresentation,const OUString & rRole)652 Reference< chart2::data::XDataSequence > InternalDataProvider::createDataSequenceAndAddToMap(
653 const OUString & rRangeRepresentation,
654 const OUString & rRole )
655 {
656 Reference< chart2::data::XDataSequence > xSeq(
657 new UncachedDataSequence( this, rRangeRepresentation, rRole ));
658 addDataSequenceToMap( rRangeRepresentation, xSeq );
659 return xSeq;
660 }
661
662 // ____ XDataProvider ____
createDataSourcePossible(const Sequence<beans::PropertyValue> &)663 sal_Bool SAL_CALL InternalDataProvider::createDataSourcePossible( const Sequence< beans::PropertyValue >& /* aArguments */ )
664 {
665 return true;
666 }
667
668 namespace
669 {
670
lcl_getInnerLevelCount(const vector<vector<uno::Any>> & rLabels)671 sal_Int32 lcl_getInnerLevelCount( const vector< vector< uno::Any > >& rLabels )
672 {
673 sal_Int32 nCount = 1;//minimum is 1!
674 for (auto const& elemLabel : rLabels)
675 {
676 nCount = std::max<sal_Int32>( elemLabel.size(), nCount );
677 }
678 return nCount;
679 }
680
681 }//end anonymous namespace
682
createDataSource(const Sequence<beans::PropertyValue> & aArguments)683 Reference< chart2::data::XDataSource > SAL_CALL InternalDataProvider::createDataSource(
684 const Sequence< beans::PropertyValue >& aArguments )
685 {
686 OUString aRangeRepresentation;
687 bool bUseColumns = true;
688 bool bFirstCellAsLabel = true;
689 bool bHasCategories = true;
690 uno::Sequence< sal_Int32 > aSequenceMapping;
691 DataSourceHelper::readArguments( aArguments, aRangeRepresentation, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories );
692
693 if( aRangeRepresentation == lcl_aCategoriesRangeName )
694 {
695 //return split complex categories if we have any:
696 std::vector< Reference< chart2::data::XLabeledDataSequence > > aComplexCategories;
697 vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
698 if( bUseColumns==m_bDataInColumns )
699 {
700 sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories );
701 for( sal_Int32 nL=0; nL<nLevelCount; nL++ )
702 aComplexCategories.push_back( new LabeledDataSequence(
703 new UncachedDataSequence( this
704 , lcl_aCategoriesLevelRangeNamePrefix + OUString::number( nL )
705 , lcl_aCategoriesRoleName ) ) );
706 }
707 else
708 {
709 sal_Int32 nPointCount = m_bDataInColumns ? m_aInternalData.getRowCount() : m_aInternalData.getColumnCount();
710 for( sal_Int32 nP=0; nP<nPointCount; nP++ )
711 aComplexCategories.push_back( new LabeledDataSequence(
712 new UncachedDataSequence( this
713 , lcl_aCategoriesPointRangeNamePrefix + OUString::number( nP )
714 , lcl_aCategoriesRoleName ) ) );
715 }
716 //don't add the created sequences to the map as they are used temporarily only ...
717 return new DataSource( comphelper::containerToSequence(aComplexCategories) );
718 }
719
720 OSL_ASSERT( aRangeRepresentation == lcl_aCompleteRange );
721
722 std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultLSeqVec;
723
724 // categories
725 if( bHasCategories )
726 aResultLSeqVec.push_back(
727 new LabeledDataSequence( createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName ) ) );
728
729 // data with labels
730 std::vector< Reference< chart2::data::XLabeledDataSequence > > aDataVec;
731 const sal_Int32 nCount = (bUseColumns ? m_aInternalData.getColumnCount() : m_aInternalData.getRowCount());
732 aDataVec.reserve(nCount);
733 for (sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx)
734 {
735 aDataVec.push_back(
736 new LabeledDataSequence(
737 createDataSequenceAndAddToMap( OUString::number( nIdx )),
738 createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::number( nIdx ))));
739 }
740
741 // attention: this data provider has the limitation that it stores
742 // internally if data comes from columns or rows. It is intended for
743 // creating only one used data source.
744 // @todo: add this information in the range representation strings
745 m_bDataInColumns = bUseColumns;
746
747 //reorder labeled sequences according to aSequenceMapping; ignore categories
748 for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
749 {
750 std::vector< LabeledDataSequence* >::size_type nOldIndex = aSequenceMapping[nNewIndex];
751 if( nOldIndex < aDataVec.size() )
752 {
753 if( aDataVec[nOldIndex].is() )
754 {
755 aResultLSeqVec.push_back( aDataVec[nOldIndex] );
756 aDataVec[nOldIndex] = nullptr;
757 }
758 }
759 }
760
761 //add left over data sequences to result
762 for (auto const& elem : aDataVec)
763 {
764 if( elem.is() )
765 aResultLSeqVec.push_back(elem);
766 }
767
768 return new DataSource( comphelper::containerToSequence(aResultLSeqVec) );
769 }
770
detectArguments(const Reference<chart2::data::XDataSource> &)771 Sequence< beans::PropertyValue > SAL_CALL InternalDataProvider::detectArguments(
772 const Reference< chart2::data::XDataSource >& /* xDataSource */ )
773 {
774 Sequence< beans::PropertyValue > aArguments( 4 );
775 aArguments[0] = beans::PropertyValue(
776 "CellRangeRepresentation", -1, uno::Any( OUString(lcl_aCompleteRange) ),
777 beans::PropertyState_DIRECT_VALUE );
778 aArguments[1] = beans::PropertyValue(
779 "DataRowSource", -1, uno::Any(
780 m_bDataInColumns
781 ? css::chart::ChartDataRowSource_COLUMNS
782 : css::chart::ChartDataRowSource_ROWS ),
783 beans::PropertyState_DIRECT_VALUE );
784 // internal data always contains labels and categories
785 aArguments[2] = beans::PropertyValue(
786 "FirstCellAsLabel", -1, uno::Any( true ), beans::PropertyState_DIRECT_VALUE );
787 aArguments[3] = beans::PropertyValue(
788 "HasCategories", -1, uno::Any( true ), beans::PropertyState_DIRECT_VALUE );
789
790 // #i85913# Sequence Mapping is not needed for internal data, as it is
791 // applied to the data when the data source is created.
792
793 return aArguments;
794 }
795
createDataSequenceByRangeRepresentationPossible(const OUString &)796 sal_Bool SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentationPossible( const OUString& /* aRangeRepresentation */ )
797 {
798 return true;
799 }
800
createDataSequenceByRangeRepresentation(const OUString & aRangeRepresentation)801 Reference< chart2::data::XDataSequence > SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentation(
802 const OUString& aRangeRepresentation )
803 {
804 if( aRangeRepresentation.match( lcl_aCategoriesRangeName ))
805 {
806 OSL_ASSERT( aRangeRepresentation == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
807
808 // categories
809 return createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName );
810 }
811 else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
812 {
813 // label
814 sal_Int32 nIndex = aRangeRepresentation.copy( strlen(lcl_aLabelRangePrefix)).toInt32();
815 return createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::number( nIndex ));
816 }
817 else if ( aRangeRepresentation == "last" )
818 {
819 sal_Int32 nIndex = (m_bDataInColumns
820 ? m_aInternalData.getColumnCount()
821 : m_aInternalData.getRowCount()) - 1;
822 return createDataSequenceAndAddToMap( OUString::number( nIndex ));
823 }
824 else if( !aRangeRepresentation.isEmpty())
825 {
826 // data
827 return createDataSequenceAndAddToMap( aRangeRepresentation );
828 }
829
830 return Reference< chart2::data::XDataSequence >();
831 }
832
833 Reference<chart2::data::XDataSequence> SAL_CALL
createDataSequenceByValueArray(const OUString & aRole,const OUString & aRangeRepresentation)834 InternalDataProvider::createDataSequenceByValueArray(
835 const OUString& aRole, const OUString& aRangeRepresentation )
836 {
837 return createDataSequenceFromArray(aRangeRepresentation, aRole);
838 }
839
getRangeSelection()840 Reference< sheet::XRangeSelection > SAL_CALL InternalDataProvider::getRangeSelection()
841 {
842 // there is no range selection component
843 return Reference< sheet::XRangeSelection >();
844 }
845
846 // ____ XInternalDataProvider ____
hasDataByRangeRepresentation(const OUString & aRange)847 sal_Bool SAL_CALL InternalDataProvider::hasDataByRangeRepresentation( const OUString& aRange )
848 {
849 bool bResult = false;
850
851 if( aRange.match( lcl_aCategoriesRangeName ))
852 {
853 OSL_ASSERT( aRange == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
854 bResult = true;
855 }
856 else if( aRange.match( lcl_aLabelRangePrefix ))
857 {
858 sal_Int32 nIndex = aRange.copy( strlen(lcl_aLabelRangePrefix)).toInt32();
859 bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount()));
860 }
861 else
862 {
863 sal_Int32 nIndex = aRange.toInt32();
864 bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount()));
865 }
866
867 return bResult;
868 }
869
getDataByRangeRepresentation(const OUString & aRange)870 Sequence< uno::Any > SAL_CALL InternalDataProvider::getDataByRangeRepresentation( const OUString& aRange )
871 {
872 Sequence< uno::Any > aResult;
873
874 if( aRange.match( lcl_aLabelRangePrefix ) )
875 {
876 auto nIndex = aRange.copy( strlen(lcl_aLabelRangePrefix)).toUInt32();
877 vector< uno::Any > aComplexLabel = m_bDataInColumns
878 ? m_aInternalData.getComplexColumnLabel( nIndex )
879 : m_aInternalData.getComplexRowLabel( nIndex );
880 if( !aComplexLabel.empty() )
881 aResult = comphelper::containerToSequence(aComplexLabel);
882 }
883 else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
884 {
885 auto nPointIndex = aRange.copy( strlen(lcl_aCategoriesPointRangeNamePrefix) ).toUInt32();
886 vector< uno::Any > aComplexCategory = m_bDataInColumns
887 ? m_aInternalData.getComplexRowLabel( nPointIndex )
888 : m_aInternalData.getComplexColumnLabel( nPointIndex );
889 if( !aComplexCategory.empty() )
890 aResult = comphelper::containerToSequence(aComplexCategory);
891 }
892 else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
893 {
894 sal_Int32 nLevel = aRange.copy( strlen(lcl_aCategoriesLevelRangeNamePrefix) ).toInt32();
895 vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
896 if( nLevel < lcl_getInnerLevelCount( aCategories ) )
897 {
898 aResult.realloc( aCategories.size() );
899 transform( aCategories.begin(), aCategories.end(),
900 aResult.getArray(), lcl_copyFromLevel(nLevel) );
901 }
902 }
903 else if( aRange == lcl_aCategoriesRangeName )
904 {
905 vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
906 sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories );
907 if( nLevelCount == 1 )
908 {
909 aResult = getDataByRangeRepresentation( lcl_aCategoriesLevelRangeNamePrefix + OUString::number( 0 ) );
910 }
911 else
912 {
913 // Maybe this 'else' part and the functions is not necessary anymore.
914 Sequence< OUString > aLabels = m_bDataInColumns ? getRowDescriptions() : getColumnDescriptions();
915 aResult.realloc( aLabels.getLength() );
916 transform( aLabels.begin(), aLabels.end(),
917 aResult.getArray(), CommonFunctors::makeAny< OUString >() );
918 }
919 }
920 else
921 {
922 sal_Int32 nIndex = aRange.toInt32();
923 if( nIndex >= 0 )
924 {
925 Sequence< double > aData;
926 if( m_bDataInColumns )
927 aData = m_aInternalData.getColumnValues(nIndex);
928 else
929 aData = m_aInternalData.getRowValues(nIndex);
930 if( aData.hasElements() )
931 {
932 aResult.realloc( aData.getLength());
933 transform( aData.begin(), aData.end(),
934 aResult.getArray(), CommonFunctors::makeAny< double >());
935 }
936 }
937 }
938
939 return aResult;
940 }
941
setDataByRangeRepresentation(const OUString & aRange,const Sequence<uno::Any> & aNewData)942 void SAL_CALL InternalDataProvider::setDataByRangeRepresentation(
943 const OUString& aRange, const Sequence< uno::Any >& aNewData )
944 {
945 auto aNewVector( comphelper::sequenceToContainer<vector< uno::Any >>(aNewData) );
946 if( aRange.match( lcl_aLabelRangePrefix ) )
947 {
948 sal_uInt32 nIndex = aRange.copy( strlen(lcl_aLabelRangePrefix)).toInt32();
949 if( m_bDataInColumns )
950 m_aInternalData.setComplexColumnLabel( nIndex, aNewVector );
951 else
952 m_aInternalData.setComplexRowLabel( nIndex, aNewVector );
953 }
954 else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
955 {
956 sal_Int32 nPointIndex = aRange.copy( strlen(lcl_aCategoriesLevelRangeNamePrefix)).toInt32();
957 if( m_bDataInColumns )
958 m_aInternalData.setComplexRowLabel( nPointIndex, aNewVector );
959 else
960 m_aInternalData.setComplexColumnLabel( nPointIndex, aNewVector );
961 }
962 else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
963 {
964 sal_Int32 nLevel = aRange.copy( strlen(lcl_aCategoriesLevelRangeNamePrefix)).toInt32();
965 vector< vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
966
967 //ensure equal length
968 if( aNewVector.size() > aComplexCategories.size() )
969 aComplexCategories.resize( aNewVector.size() );
970 else if( aNewVector.size() < aComplexCategories.size() )
971 aNewVector.resize( aComplexCategories.size() );
972
973 transform( aComplexCategories.begin(), aComplexCategories.end(), aNewVector.begin(),
974 aComplexCategories.begin(), lcl_setAnyAtLevel(nLevel) );
975
976 if( m_bDataInColumns )
977 m_aInternalData.setComplexRowLabels( aComplexCategories );
978 else
979 m_aInternalData.setComplexColumnLabels( aComplexCategories );
980 }
981 else if( aRange == lcl_aCategoriesRangeName )
982 {
983 vector< vector< uno::Any > > aComplexCategories;
984 aComplexCategories.resize( aNewVector.size() );
985 transform( aComplexCategories.begin(), aComplexCategories.end(), aNewVector.begin(),
986 aComplexCategories.begin(), lcl_setAnyAtLevel(0) );
987 if( m_bDataInColumns )
988 m_aInternalData.setComplexRowLabels( aComplexCategories );
989 else
990 m_aInternalData.setComplexColumnLabels( aComplexCategories );
991 }
992 else
993 {
994 sal_Int32 nIndex = aRange.toInt32();
995 if( nIndex>=0 )
996 {
997 vector< double > aNewDataVec;
998 transform( aNewData.begin(), aNewData.end(),
999 back_inserter( aNewDataVec ), CommonFunctors::AnyToDouble());
1000 if( m_bDataInColumns )
1001 m_aInternalData.setColumnValues( nIndex, aNewDataVec );
1002 else
1003 m_aInternalData.setRowValues( nIndex, aNewDataVec );
1004 }
1005 }
1006 }
1007
insertSequence(::sal_Int32 nAfterIndex)1008 void SAL_CALL InternalDataProvider::insertSequence( ::sal_Int32 nAfterIndex )
1009 {
1010 if( m_bDataInColumns )
1011 {
1012 increaseMapReferences( nAfterIndex + 1, m_aInternalData.getColumnCount());
1013 m_aInternalData.insertColumn( nAfterIndex );
1014 }
1015 else
1016 {
1017 increaseMapReferences( nAfterIndex + 1, m_aInternalData.getRowCount());
1018 m_aInternalData.insertRow( nAfterIndex );
1019 }
1020 }
1021
deleteSequence(::sal_Int32 nAtIndex)1022 void SAL_CALL InternalDataProvider::deleteSequence( ::sal_Int32 nAtIndex )
1023 {
1024 deleteMapReferences( OUString::number( nAtIndex ));
1025 deleteMapReferences( lcl_aLabelRangePrefix + OUString::number( nAtIndex ));
1026 if( m_bDataInColumns )
1027 {
1028 decreaseMapReferences( nAtIndex + 1, m_aInternalData.getColumnCount());
1029 m_aInternalData.deleteColumn( nAtIndex );
1030 }
1031 else
1032 {
1033 decreaseMapReferences( nAtIndex + 1, m_aInternalData.getRowCount());
1034 m_aInternalData.deleteRow( nAtIndex );
1035 }
1036 }
1037
appendSequence()1038 void SAL_CALL InternalDataProvider::appendSequence()
1039 {
1040 if( m_bDataInColumns )
1041 m_aInternalData.appendColumn();
1042 else
1043 m_aInternalData.appendRow();
1044 }
1045
insertComplexCategoryLevel(sal_Int32 nLevel)1046 void SAL_CALL InternalDataProvider::insertComplexCategoryLevel( sal_Int32 nLevel )
1047 {
1048 OSL_ENSURE( nLevel> 0, "you can only insert category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
1049 if( nLevel>0 )
1050 {
1051 vector< vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
1052 std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_insertAnyAtLevel(nLevel) );
1053 if( m_bDataInColumns )
1054 m_aInternalData.setComplexRowLabels( aComplexCategories );
1055 else
1056 m_aInternalData.setComplexColumnLabels( aComplexCategories );
1057
1058 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1059 std::for_each( aRange.first, aRange.second, lcl_setModified());
1060 }
1061 }
deleteComplexCategoryLevel(sal_Int32 nLevel)1062 void SAL_CALL InternalDataProvider::deleteComplexCategoryLevel( sal_Int32 nLevel )
1063 {
1064 OSL_ENSURE( nLevel>0, "you can only delete category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
1065 if( nLevel>0 )
1066 {
1067 vector< vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
1068 std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_removeAnyAtLevel(nLevel) );
1069 if( m_bDataInColumns )
1070 m_aInternalData.setComplexRowLabels( aComplexCategories );
1071 else
1072 m_aInternalData.setComplexColumnLabels( aComplexCategories );
1073
1074 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1075 std::for_each( aRange.first, aRange.second, lcl_setModified());
1076 }
1077 }
1078
insertDataPointForAllSequences(::sal_Int32 nAfterIndex)1079 void SAL_CALL InternalDataProvider::insertDataPointForAllSequences( ::sal_Int32 nAfterIndex )
1080 {
1081 sal_Int32 nMaxRep = 0;
1082 if( m_bDataInColumns )
1083 {
1084 m_aInternalData.insertRow( nAfterIndex );
1085 nMaxRep = m_aInternalData.getColumnCount();
1086 }
1087 else
1088 {
1089 m_aInternalData.insertColumn( nAfterIndex );
1090 nMaxRep = m_aInternalData.getRowCount();
1091 }
1092
1093 // notify change to all affected ranges
1094 tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( "0"));
1095 tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
1096 std::for_each( aBegin, aEnd, lcl_setModified());
1097
1098 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1099 std::for_each( aRange.first, aRange.second, lcl_setModified());
1100 }
1101
deleteDataPointForAllSequences(::sal_Int32 nAtIndex)1102 void SAL_CALL InternalDataProvider::deleteDataPointForAllSequences( ::sal_Int32 nAtIndex )
1103 {
1104 sal_Int32 nMaxRep = 0;
1105 if( m_bDataInColumns )
1106 {
1107 m_aInternalData.deleteRow( nAtIndex );
1108 nMaxRep = m_aInternalData.getColumnCount();
1109 }
1110 else
1111 {
1112 m_aInternalData.deleteColumn( nAtIndex );
1113 nMaxRep = m_aInternalData.getRowCount();
1114 }
1115
1116 // notify change to all affected ranges
1117 tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( "0"));
1118 tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
1119 std::for_each( aBegin, aEnd, lcl_setModified());
1120
1121 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1122 std::for_each( aRange.first, aRange.second, lcl_setModified());
1123 }
1124
swapDataPointWithNextOneForAllSequences(::sal_Int32 nAtIndex)1125 void SAL_CALL InternalDataProvider::swapDataPointWithNextOneForAllSequences( ::sal_Int32 nAtIndex )
1126 {
1127 if( m_bDataInColumns )
1128 m_aInternalData.swapRowWithNext( nAtIndex );
1129 else
1130 m_aInternalData.swapColumnWithNext( nAtIndex );
1131 sal_Int32 nMaxRep = (m_bDataInColumns
1132 ? m_aInternalData.getColumnCount()
1133 : m_aInternalData.getRowCount());
1134
1135 // notify change to all affected ranges
1136 tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( "0"));
1137 tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
1138 std::for_each( aBegin, aEnd, lcl_setModified());
1139
1140 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1141 std::for_each( aRange.first, aRange.second, lcl_setModified());
1142 }
1143
registerDataSequenceForChanges(const Reference<chart2::data::XDataSequence> & xSeq)1144 void SAL_CALL InternalDataProvider::registerDataSequenceForChanges( const Reference< chart2::data::XDataSequence >& xSeq )
1145 {
1146 if( xSeq.is())
1147 addDataSequenceToMap( xSeq->getSourceRangeRepresentation(), xSeq );
1148 }
1149
1150 // ____ XRangeXMLConversion ____
convertRangeToXML(const OUString & aRangeRepresentation)1151 OUString SAL_CALL InternalDataProvider::convertRangeToXML( const OUString& aRangeRepresentation )
1152 {
1153 XMLRangeHelper::CellRange aRange;
1154 aRange.aTableName = "local-table";
1155
1156 // attention: this data provider has the limitation that it stores
1157 // internally if data comes from columns or rows. It is intended for
1158 // creating only one used data source.
1159 // @todo: add this information in the range representation strings
1160 if( aRangeRepresentation.match( lcl_aCategoriesRangeName ))
1161 {
1162 OSL_ASSERT( aRangeRepresentation == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
1163 aRange.aUpperLeft.bIsEmpty = false;
1164 if( m_bDataInColumns )
1165 {
1166 aRange.aUpperLeft.nColumn = 0;
1167 aRange.aUpperLeft.nRow = 1;
1168 aRange.aLowerRight = aRange.aUpperLeft;
1169 aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
1170 }
1171 else
1172 {
1173 aRange.aUpperLeft.nColumn = 1;
1174 aRange.aUpperLeft.nRow = 0;
1175 aRange.aLowerRight = aRange.aUpperLeft;
1176 aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
1177 }
1178 }
1179 else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
1180 {
1181 sal_Int32 nIndex = aRangeRepresentation.copy( strlen(lcl_aLabelRangePrefix)).toInt32();
1182 aRange.aUpperLeft.bIsEmpty = false;
1183 aRange.aLowerRight.bIsEmpty = true;
1184 if( m_bDataInColumns )
1185 {
1186 aRange.aUpperLeft.nColumn = nIndex + 1;
1187 aRange.aUpperLeft.nRow = 0;
1188 }
1189 else
1190 {
1191 aRange.aUpperLeft.nColumn = 0;
1192 aRange.aUpperLeft.nRow = nIndex + 1;
1193 }
1194 }
1195 else if( aRangeRepresentation == lcl_aCompleteRange )
1196 {
1197 aRange.aUpperLeft.bIsEmpty = false;
1198 aRange.aLowerRight.bIsEmpty = false;
1199 aRange.aUpperLeft.nColumn = 0;
1200 aRange.aUpperLeft.nRow = 0;
1201 aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
1202 aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
1203 }
1204 else
1205 {
1206 sal_Int32 nIndex = aRangeRepresentation.toInt32();
1207 aRange.aUpperLeft.bIsEmpty = false;
1208 if( m_bDataInColumns )
1209 {
1210 aRange.aUpperLeft.nColumn = nIndex + 1;
1211 aRange.aUpperLeft.nRow = 1;
1212 aRange.aLowerRight = aRange.aUpperLeft;
1213 aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
1214 }
1215 else
1216 {
1217 aRange.aUpperLeft.nColumn = 1;
1218 aRange.aUpperLeft.nRow = nIndex + 1;
1219 aRange.aLowerRight = aRange.aUpperLeft;
1220 aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
1221 }
1222 }
1223
1224 return XMLRangeHelper::getXMLStringFromCellRange( aRange );
1225 }
1226
convertRangeFromXML(const OUString & aXMLRange)1227 OUString SAL_CALL InternalDataProvider::convertRangeFromXML( const OUString& aXMLRange )
1228 {
1229 // Handle non-standards-conforming table:cell-range-address="PivotChart", see
1230 // <https://bugs.documentfoundation.org/show_bug.cgi?id=112783> "PIVOT CHARTS: Save produces
1231 // invalid file because of invalid cell address":
1232 if (aXMLRange == "PivotChart") {
1233 return "";
1234 }
1235
1236 static const OUStringLiteral aPivotTableID(u"PT@");
1237 if (aXMLRange.startsWith(aPivotTableID))
1238 return aXMLRange.copy(aPivotTableID.getLength());
1239
1240 XMLRangeHelper::CellRange aRange( XMLRangeHelper::getCellRangeFromXMLString( aXMLRange ));
1241 if( aRange.aUpperLeft.bIsEmpty )
1242 {
1243 OSL_ENSURE( aRange.aLowerRight.bIsEmpty, "Weird Range" );
1244 return OUString();
1245 }
1246
1247 // "all"
1248 if( !aRange.aLowerRight.bIsEmpty &&
1249 ( aRange.aUpperLeft.nColumn != aRange.aLowerRight.nColumn ) &&
1250 ( aRange.aUpperLeft.nRow != aRange.aLowerRight.nRow ) )
1251 return lcl_aCompleteRange;
1252
1253 // attention: this data provider has the limitation that it stores
1254 // internally if data comes from columns or rows. It is intended for
1255 // creating only one used data source.
1256 // @todo: add this information in the range representation strings
1257
1258 // data in columns
1259 if( m_bDataInColumns )
1260 {
1261 if( aRange.aUpperLeft.nColumn == 0 )
1262 return lcl_aCategoriesRangeName;
1263 if( aRange.aUpperLeft.nRow == 0 )
1264 return lcl_aLabelRangePrefix + OUString::number( aRange.aUpperLeft.nColumn - 1 );
1265
1266 return OUString::number( aRange.aUpperLeft.nColumn - 1 );
1267 }
1268
1269 // data in rows
1270 if( aRange.aUpperLeft.nRow == 0 )
1271 return lcl_aCategoriesRangeName;
1272 if( aRange.aUpperLeft.nColumn == 0 )
1273 return lcl_aLabelRangePrefix + OUString::number( aRange.aUpperLeft.nRow - 1 );
1274
1275 return OUString::number( aRange.aUpperLeft.nRow - 1 );
1276 }
1277
1278 namespace
1279 {
1280
1281 template< class Type >
lcl_convertVectorVectorToSequenceSequence(const vector<vector<Type>> & rIn)1282 Sequence< Sequence< Type > > lcl_convertVectorVectorToSequenceSequence( const vector< vector< Type > >& rIn )
1283 {
1284 Sequence< Sequence< Type > > aRet;
1285 sal_Int32 nOuterCount = rIn.size();
1286 if( nOuterCount )
1287 {
1288 aRet.realloc(nOuterCount);
1289 for( sal_Int32 nN=0; nN<nOuterCount; nN++)
1290 aRet[nN]= comphelper::containerToSequence( rIn[nN] );
1291 }
1292 return aRet;
1293 }
1294
1295 template< class Type >
lcl_convertSequenceSequenceToVectorVector(const Sequence<Sequence<Type>> & rIn)1296 vector< vector< Type > > lcl_convertSequenceSequenceToVectorVector( const Sequence< Sequence< Type > >& rIn )
1297 {
1298 vector< vector< Type > > aRet;
1299 sal_Int32 nOuterCount = rIn.getLength();
1300 if( nOuterCount )
1301 {
1302 aRet.resize(nOuterCount);
1303 for( sal_Int32 nN=0; nN<nOuterCount; nN++)
1304 aRet[nN]= comphelper::sequenceToContainer<vector< Type >>( rIn[nN] );
1305 }
1306 return aRet;
1307 }
1308
lcl_convertComplexAnyVectorToStringSequence(const vector<vector<uno::Any>> & rIn)1309 std::vector< Sequence< OUString > > lcl_convertComplexAnyVectorToStringSequence( const vector< vector< uno::Any > >& rIn )
1310 {
1311 std::vector< Sequence< OUString > > aRet;
1312 sal_Int32 nOuterCount = rIn.size();
1313 if( nOuterCount )
1314 {
1315 aRet.resize(nOuterCount);
1316 for( sal_Int32 nN=0; nN<nOuterCount; nN++)
1317 aRet[nN] = comphelper::containerToSequence(lcl_AnyToStringSequence( rIn[nN] ));
1318 }
1319 return aRet;
1320 }
1321
lcl_convertComplexStringSequenceToAnyVector(const Sequence<Sequence<OUString>> & rIn)1322 vector< vector< uno::Any > > lcl_convertComplexStringSequenceToAnyVector( const Sequence< Sequence< OUString > >& rIn )
1323 {
1324 vector< vector< uno::Any > > aRet;
1325 sal_Int32 nOuterCount = rIn.getLength();
1326 aRet.reserve(nOuterCount);
1327 for (sal_Int32 nN = 0; nN < nOuterCount; nN++)
1328 aRet.push_back( lcl_StringToAnyVector( rIn[nN] ) );
1329 return aRet;
1330 }
1331
1332 class SplitCategoriesProvider_ForComplexDescriptions : public SplitCategoriesProvider
1333 {
1334 public:
1335
SplitCategoriesProvider_ForComplexDescriptions(const std::vector<std::vector<uno::Any>> & rComplexDescriptions)1336 explicit SplitCategoriesProvider_ForComplexDescriptions( const std::vector< std::vector< uno::Any > >& rComplexDescriptions )
1337 : m_rComplexDescriptions( rComplexDescriptions )
1338 {}
1339
1340 virtual sal_Int32 getLevelCount() const override;
1341 virtual uno::Sequence< OUString > getStringsForLevel( sal_Int32 nIndex ) const override;
1342
1343 private:
1344 const std::vector< std::vector< uno::Any > >& m_rComplexDescriptions;
1345 };
1346
getLevelCount() const1347 sal_Int32 SplitCategoriesProvider_ForComplexDescriptions::getLevelCount() const
1348 {
1349 return lcl_getInnerLevelCount( m_rComplexDescriptions );
1350 }
getStringsForLevel(sal_Int32 nLevel) const1351 uno::Sequence< OUString > SplitCategoriesProvider_ForComplexDescriptions::getStringsForLevel( sal_Int32 nLevel ) const
1352 {
1353 uno::Sequence< OUString > aResult;
1354 if( nLevel < lcl_getInnerLevelCount( m_rComplexDescriptions ) )
1355 {
1356 aResult.realloc( m_rComplexDescriptions.size() );
1357 transform( m_rComplexDescriptions.begin(), m_rComplexDescriptions.end(),
1358 aResult.getArray(), lcl_getStringFromLevelVector(nLevel) );
1359 }
1360 return aResult;
1361 }
1362
1363 }//anonymous namespace
1364
1365 // ____ XDateCategories ____
getDateCategories()1366 Sequence< double > SAL_CALL InternalDataProvider::getDateCategories()
1367 {
1368 double fNan = InternalDataProvider::getNotANumber();
1369 double fValue = fNan;
1370 vector< vector< uno::Any > > aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
1371 sal_Int32 nCount = aCategories.size();
1372 Sequence< double > aDoubles( nCount );
1373 sal_Int32 nN=0;
1374 for (auto const& category : aCategories)
1375 {
1376 if( category.empty() || !(category[0]>>=fValue) )
1377 fValue = fNan;
1378 aDoubles[nN++]=fValue;
1379 }
1380 return aDoubles;
1381 }
1382
setDateCategories(const Sequence<double> & rDates)1383 void SAL_CALL InternalDataProvider::setDateCategories( const Sequence< double >& rDates )
1384 {
1385 sal_Int32 nCount = rDates.getLength();
1386 vector< vector< uno::Any > > aNewCategories;
1387 aNewCategories.reserve(nCount);
1388 vector< uno::Any > aSingleLabel(1);
1389
1390 for(sal_Int32 nN=0; nN<nCount; ++nN )
1391 {
1392 aSingleLabel[0] <<= rDates[nN];
1393 aNewCategories.push_back(aSingleLabel);
1394 }
1395
1396 if( m_bDataInColumns )
1397 m_aInternalData.setComplexRowLabels( aNewCategories );
1398 else
1399 m_aInternalData.setComplexColumnLabels( aNewCategories );
1400 }
1401
1402 // ____ XAnyDescriptionAccess ____
getAnyRowDescriptions()1403 Sequence< Sequence< uno::Any > > SAL_CALL InternalDataProvider::getAnyRowDescriptions()
1404 {
1405 return lcl_convertVectorVectorToSequenceSequence( m_aInternalData.getComplexRowLabels() );
1406 }
setAnyRowDescriptions(const Sequence<Sequence<uno::Any>> & aRowDescriptions)1407 void SAL_CALL InternalDataProvider::setAnyRowDescriptions( const Sequence< Sequence< uno::Any > >& aRowDescriptions )
1408 {
1409 m_aInternalData.setComplexRowLabels( lcl_convertSequenceSequenceToVectorVector( aRowDescriptions ) );
1410 }
getAnyColumnDescriptions()1411 Sequence< Sequence< uno::Any > > SAL_CALL InternalDataProvider::getAnyColumnDescriptions()
1412 {
1413 return lcl_convertVectorVectorToSequenceSequence( m_aInternalData.getComplexColumnLabels() );
1414 }
setAnyColumnDescriptions(const Sequence<Sequence<uno::Any>> & aColumnDescriptions)1415 void SAL_CALL InternalDataProvider::setAnyColumnDescriptions( const Sequence< Sequence< uno::Any > >& aColumnDescriptions )
1416 {
1417 m_aInternalData.setComplexColumnLabels( lcl_convertSequenceSequenceToVectorVector( aColumnDescriptions ) );
1418 }
1419
1420 // ____ XComplexDescriptionAccess ____
getComplexRowDescriptions()1421 Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexRowDescriptions()
1422 {
1423 return comphelper::containerToSequence(lcl_convertComplexAnyVectorToStringSequence( m_aInternalData.getComplexRowLabels() ));
1424 }
setComplexRowDescriptions(const Sequence<Sequence<OUString>> & aRowDescriptions)1425 void SAL_CALL InternalDataProvider::setComplexRowDescriptions( const Sequence< Sequence< OUString > >& aRowDescriptions )
1426 {
1427 m_aInternalData.setComplexRowLabels( lcl_convertComplexStringSequenceToAnyVector(aRowDescriptions) );
1428 }
getComplexColumnDescriptions()1429 Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexColumnDescriptions()
1430 {
1431 return comphelper::containerToSequence(lcl_convertComplexAnyVectorToStringSequence( m_aInternalData.getComplexColumnLabels() ));
1432 }
setComplexColumnDescriptions(const Sequence<Sequence<OUString>> & aColumnDescriptions)1433 void SAL_CALL InternalDataProvider::setComplexColumnDescriptions( const Sequence< Sequence< OUString > >& aColumnDescriptions )
1434 {
1435 m_aInternalData.setComplexColumnLabels( lcl_convertComplexStringSequenceToAnyVector(aColumnDescriptions) );
1436 }
1437
1438 // ____ XChartDataArray ____
getData()1439 Sequence< Sequence< double > > SAL_CALL InternalDataProvider::getData()
1440 {
1441 return m_aInternalData.getData();
1442 }
1443
setData(const Sequence<Sequence<double>> & rDataInRows)1444 void SAL_CALL InternalDataProvider::setData( const Sequence< Sequence< double > >& rDataInRows )
1445 {
1446 return m_aInternalData.setData( rDataInRows );
1447 }
1448
setRowDescriptions(const Sequence<OUString> & aRowDescriptions)1449 void SAL_CALL InternalDataProvider::setRowDescriptions( const Sequence< OUString >& aRowDescriptions )
1450 {
1451 vector< vector< uno::Any > > aComplexDescriptions( aRowDescriptions.getLength() );
1452 transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aRowDescriptions.getConstArray(),
1453 aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
1454 m_aInternalData.setComplexRowLabels( aComplexDescriptions );
1455 }
1456
setColumnDescriptions(const Sequence<OUString> & aColumnDescriptions)1457 void SAL_CALL InternalDataProvider::setColumnDescriptions( const Sequence< OUString >& aColumnDescriptions )
1458 {
1459 vector< vector< uno::Any > > aComplexDescriptions( aColumnDescriptions.getLength() );
1460 transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aColumnDescriptions.getConstArray(),
1461 aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
1462 m_aInternalData.setComplexColumnLabels( aComplexDescriptions );
1463 }
1464
getRowDescriptions()1465 Sequence< OUString > SAL_CALL InternalDataProvider::getRowDescriptions()
1466 {
1467 vector< vector< uno::Any > > aComplexLabels( m_aInternalData.getComplexRowLabels() );
1468 SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels );
1469 return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider );
1470 }
1471
getColumnDescriptions()1472 Sequence< OUString > SAL_CALL InternalDataProvider::getColumnDescriptions()
1473 {
1474 vector< vector< uno::Any > > aComplexLabels( m_aInternalData.getComplexColumnLabels() );
1475 SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels );
1476 return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider );
1477 }
1478
1479 // ____ XChartData (base of XChartDataArray) ____
addChartDataChangeEventListener(const Reference<css::chart::XChartDataChangeEventListener> &)1480 void SAL_CALL InternalDataProvider::addChartDataChangeEventListener(
1481 const Reference< css::chart::XChartDataChangeEventListener >& )
1482 {
1483 }
1484
removeChartDataChangeEventListener(const Reference<css::chart::XChartDataChangeEventListener> &)1485 void SAL_CALL InternalDataProvider::removeChartDataChangeEventListener(
1486 const Reference< css::chart::XChartDataChangeEventListener >& )
1487 {
1488 }
1489
getNotANumber()1490 double SAL_CALL InternalDataProvider::getNotANumber()
1491 {
1492 double fNan;
1493 ::rtl::math::setNan( & fNan );
1494 return fNan;
1495 }
1496
isNotANumber(double nNumber)1497 sal_Bool SAL_CALL InternalDataProvider::isNotANumber( double nNumber )
1498 {
1499 return std::isnan( nNumber )
1500 || std::isinf( nNumber );
1501 }
1502 // lang::XInitialization:
initialize(const uno::Sequence<uno::Any> & _aArguments)1503 void SAL_CALL InternalDataProvider::initialize(const uno::Sequence< uno::Any > & _aArguments)
1504 {
1505 comphelper::SequenceAsHashMap aArgs(_aArguments);
1506 if ( aArgs.getUnpackedValueOrDefault( "CreateDefaultData", false ) )
1507 m_aInternalData.createDefaultData();
1508 }
1509
1510 // ____ XCloneable ____
createClone()1511 Reference< util::XCloneable > SAL_CALL InternalDataProvider::createClone()
1512 {
1513 return Reference< util::XCloneable >( new InternalDataProvider( *this ));
1514 }
1515
getImplementationName()1516 OUString SAL_CALL InternalDataProvider::getImplementationName()
1517 {
1518 // note: in xmloff this name is used to indicate usage of own data
1519 return "com.sun.star.comp.chart.InternalDataProvider";
1520 }
1521
supportsService(const OUString & rServiceName)1522 sal_Bool SAL_CALL InternalDataProvider::supportsService( const OUString& rServiceName )
1523 {
1524 return cppu::supportsService(this, rServiceName);
1525 }
1526
getSupportedServiceNames()1527 css::uno::Sequence< OUString > SAL_CALL InternalDataProvider::getSupportedServiceNames()
1528 {
1529 return { "com.sun.star.chart2.data.DataProvider" };
1530 }
1531
1532 } // namespace chart
1533
1534 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_chart_InternalDataProvider_get_implementation(css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)1535 com_sun_star_comp_chart_InternalDataProvider_get_implementation(css::uno::XComponentContext *,
1536 css::uno::Sequence<css::uno::Any> const &)
1537 {
1538 return cppu::acquire(new ::chart::InternalDataProvider);
1539 }
1540
1541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1542