Get the style color and number just once
[LibreOffice.git] / chart2 / source / tools / InternalDataProvider.cxx
blob157c7cbca336f377a42f6f87d4041cf7deb6aec9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <cstddef>
21 #include <iterator>
23 #include <InternalDataProvider.hxx>
24 #include <LabeledDataSequence.hxx>
25 #include <DataSource.hxx>
26 #include <XMLRangeHelper.hxx>
27 #include <CommonFunctors.hxx>
28 #include <UncachedDataSequence.hxx>
29 #include <DataSourceHelper.hxx>
30 #include <ChartModel.hxx>
31 #include <ChartModelHelper.hxx>
32 #include <Diagram.hxx>
33 #include <ExplicitCategoriesProvider.hxx>
34 #include <BaseCoordinateSystem.hxx>
35 #include <DataBrowserModel.hxx>
36 #include <DataSeries.hxx>
38 #include <com/sun/star/chart2/data/XDataSequence.hpp>
39 #include <com/sun/star/chart/ChartDataRowSource.hpp>
40 #include <cppuhelper/supportsservice.hxx>
41 #include <comphelper/sequenceashashmap.hxx>
42 #include <comphelper/property.hxx>
43 #include <o3tl/string_view.hxx>
44 #include <comphelper/diagnose_ex.hxx>
46 #include <limits>
47 #include <vector>
48 #include <algorithm>
50 namespace com::sun::star::chart2 { class XChartDocument; }
52 using namespace ::com::sun::star;
54 using ::com::sun::star::uno::Reference;
55 using ::com::sun::star::uno::Sequence;
57 namespace chart
60 namespace
63 constexpr OUString lcl_aCategoriesRangeName = u"categories"_ustr;
64 const char lcl_aCategoriesLevelRangeNamePrefix[] = "categoriesL "; //L <-> level
65 const char lcl_aCategoriesPointRangeNamePrefix[] = "categoriesP "; //P <-> point
66 constexpr OUString lcl_aCategoriesRoleName = u"categories"_ustr;
67 const char lcl_aLabelRangePrefix[] = "label ";
68 constexpr OUString lcl_aCompleteRange = u"all"_ustr;
70 typedef std::multimap< OUString, uno::WeakReference< chart2::data::XDataSequence > >
71 lcl_tSequenceMap;
73 std::vector< uno::Any > lcl_StringToAnyVector( const css::uno::Sequence< OUString >& aStringSeq )
75 std::vector< uno::Any > aResult;
76 aResult.reserve(aStringSeq.getLength());
77 std::transform(aStringSeq.begin(), aStringSeq.end(), std::back_inserter(aResult), CommonFunctors::makeAny());
78 return aResult;
81 struct lcl_setModified
83 void operator() ( const lcl_tSequenceMap::value_type & rMapEntry )
85 // convert weak reference to reference
86 Reference< chart2::data::XDataSequence > xSeq( rMapEntry.second );
87 if( xSeq.is())
89 Reference< util::XModifiable > xMod( xSeq, uno::UNO_QUERY );
90 if( xMod.is())
91 xMod->setModified( true );
96 struct lcl_internalizeSeries
98 lcl_internalizeSeries( InternalData & rInternalData,
99 InternalDataProvider & rProvider,
100 bool bConnectToModel, bool bDataInColumns ) :
101 m_rInternalData( rInternalData ),
102 m_rProvider( rProvider ),
103 m_bConnectToModel( bConnectToModel ),
104 m_bDataInColumns( bDataInColumns )
106 void operator() ( const rtl::Reference< DataSeries > & xSeries )
108 const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aOldSeriesData = xSeries->getDataSequences2();
109 std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSeriesData( aOldSeriesData.size() );
110 for( std::size_t i=0; i<aOldSeriesData.size(); ++i )
112 sal_Int32 nNewIndex( m_bDataInColumns ? m_rInternalData.appendColumn() : m_rInternalData.appendRow() );
113 OUString aIdentifier( OUString::number( nNewIndex ));
114 //@todo: deal also with genericXDataSequence
115 Reference< chart2::data::XNumericalDataSequence > xValues( aOldSeriesData[i]->getValues(), uno::UNO_QUERY );
116 Reference< chart2::data::XTextualDataSequence > xLabel( aOldSeriesData[i]->getLabel(), uno::UNO_QUERY );
117 Reference< chart2::data::XDataSequence > xNewValues;
119 if( xValues.is() )
121 auto aValues( comphelper::sequenceToContainer<std::vector< double >>( xValues->getNumericalData()));
122 if( m_bDataInColumns )
123 m_rInternalData.setColumnValues( nNewIndex, aValues );
124 else
125 m_rInternalData.setRowValues( nNewIndex, aValues );
126 if( m_bConnectToModel )
128 xNewValues.set( m_rProvider.createDataSequenceByRangeRepresentation( aIdentifier ));
129 comphelper::copyProperties(
130 Reference< beans::XPropertySet >( xValues, uno::UNO_QUERY ),
131 Reference< beans::XPropertySet >( xNewValues, uno::UNO_QUERY ));
135 if( xLabel.is() )
137 if( m_bDataInColumns )
138 m_rInternalData.setComplexColumnLabel( nNewIndex, lcl_StringToAnyVector( xLabel->getTextualData() ) );
139 else
140 m_rInternalData.setComplexRowLabel( nNewIndex, lcl_StringToAnyVector( xLabel->getTextualData() ) );
141 if( m_bConnectToModel )
143 Reference< chart2::data::XDataSequence > xNewLabel(
144 m_rProvider.createDataSequenceByRangeRepresentation( lcl_aLabelRangePrefix + aIdentifier ));
145 comphelper::copyProperties(
146 Reference< beans::XPropertySet >( xLabel, uno::UNO_QUERY ),
147 Reference< beans::XPropertySet >( xNewLabel, uno::UNO_QUERY ));
148 aNewSeriesData[i].set( new LabeledDataSequence( xNewValues, xNewLabel ) );
151 else
153 if( m_bConnectToModel )
154 aNewSeriesData[i].set( new LabeledDataSequence( xNewValues ) );
157 if( m_bConnectToModel )
158 xSeries->setData( aNewSeriesData );
161 private:
162 InternalData & m_rInternalData;
163 InternalDataProvider & m_rProvider;
164 bool m_bConnectToModel;
165 bool m_bDataInColumns;
168 struct lcl_copyFromLevel
170 public:
172 explicit lcl_copyFromLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
175 uno::Any operator() ( const std::vector< uno::Any >& rVector )
177 uno::Any aRet;
178 if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) )
179 aRet = rVector[m_nLevel];
180 return aRet;
183 private:
184 sal_Int32 m_nLevel;
187 struct lcl_getStringFromLevelVector
189 public:
191 explicit lcl_getStringFromLevelVector( sal_Int32 nLevel ) : m_nLevel( nLevel )
194 OUString operator() ( const std::vector< uno::Any >& rVector )
196 OUString aString;
197 if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) )
198 aString = CommonFunctors::ToString()(rVector[m_nLevel]);
199 return aString;
202 private:
203 sal_Int32 m_nLevel;
206 struct lcl_setAnyAtLevel
208 public:
210 explicit lcl_setAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
213 std::vector< uno::Any > operator() ( const std::vector< uno::Any >& rVector, const uno::Any& rNewValue )
215 std::vector< uno::Any > aRet( rVector );
216 if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) )
217 aRet.resize( m_nLevel+1 );
218 aRet[ m_nLevel ]=rNewValue;
219 return aRet;
222 private:
223 sal_Int32 m_nLevel;
226 struct lcl_setAnyAtLevelFromStringSequence
228 public:
230 explicit lcl_setAnyAtLevelFromStringSequence( sal_Int32 nLevel ) : m_nLevel( nLevel )
233 std::vector< uno::Any > operator() ( const std::vector< uno::Any >& rVector, const OUString& rNewValue )
235 std::vector< uno::Any > aRet( rVector );
236 if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) )
237 aRet.resize( m_nLevel+1 );
238 aRet[ m_nLevel ] <<= rNewValue;
239 return aRet;
242 private:
243 sal_Int32 m_nLevel;
246 struct lcl_insertAnyAtLevel
248 public:
250 explicit lcl_insertAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
253 void operator() ( std::vector< uno::Any >& rVector )
255 if( m_nLevel >= static_cast< sal_Int32 >(rVector.size()) )
257 rVector.resize( m_nLevel + 1 );
259 else
261 rVector.insert( rVector.begin() + m_nLevel, uno::Any() );
265 private:
266 sal_Int32 m_nLevel;
269 struct lcl_removeAnyAtLevel
271 public:
273 explicit lcl_removeAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
276 void operator() ( std::vector< uno::Any >& rVector )
278 if( m_nLevel < static_cast<sal_Int32>(rVector.size()) )
280 rVector.erase(rVector.begin() + m_nLevel);
284 private:
285 sal_Int32 m_nLevel;
288 } // anonymous namespace
290 InternalDataProvider::InternalDataProvider()
291 : m_bDataInColumns( true )
294 InternalDataProvider::InternalDataProvider(
295 const rtl::Reference< ChartModel > & xModel,
296 bool bConnectToModel,
297 bool bDefaultDataInColumns)
298 : m_bDataInColumns( bDefaultDataInColumns )
300 if (!xModel.is())
301 return;
302 m_xChartModel = xModel.get();
305 rtl::Reference< Diagram > xDiagram( xModel->getFirstChartDiagram() );
306 if( xDiagram.is())
308 //data in columns?
310 OUString aRangeString;
311 bool bFirstCellAsLabel = true;
312 bool bHasCategories = true;
313 uno::Sequence< sal_Int32 > aSequenceMapping;
314 const bool bSomethingDetected(
315 DataSourceHelper::detectRangeSegmentation(
316 xModel, aRangeString, aSequenceMapping, m_bDataInColumns, bFirstCellAsLabel, bHasCategories ));
318 // #i120559# if no data was available, restore default
319 if(!bSomethingDetected && m_bDataInColumns != bDefaultDataInColumns)
321 m_bDataInColumns = bDefaultDataInColumns;
325 // categories
327 std::vector< std::vector< uno::Any > > aNewCategories;//inner count is level
329 ExplicitCategoriesProvider aExplicitCategoriesProvider(ChartModelHelper::getFirstCoordinateSystem(xModel), *xModel);
331 const std::vector< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() );
332 sal_Int32 nLevelCount = rSplitCategoriesList.size();
333 for( sal_Int32 nL = 0; nL<nLevelCount; nL++ )
335 const Reference< chart2::data::XLabeledDataSequence >& xLDS( rSplitCategoriesList[nL] );
336 if( !xLDS.is() )
337 continue;
338 Sequence< uno::Any > aDataSeq;
339 Reference< chart2::data::XDataSequence > xSeq( xLDS->getValues() );
340 if( xSeq.is() )
341 aDataSeq = xSeq->getData();
342 sal_Int32 nLength = aDataSeq.getLength();
343 sal_Int32 nCatLength = static_cast< sal_Int32 >(aNewCategories.size());
344 if( nCatLength < nLength )
345 aNewCategories.resize( nLength );
346 else if( nLength < nCatLength )
347 aDataSeq.realloc( nCatLength );
348 transform( aNewCategories.begin(), aNewCategories.end(), aDataSeq.begin(),
349 aNewCategories.begin(), lcl_setAnyAtLevel(nL) );
351 if( !nLevelCount )
353 Sequence< OUString > aSimplecategories = aExplicitCategoriesProvider.getSimpleCategories();
354 sal_Int32 nLength = aSimplecategories.getLength();
355 aNewCategories.reserve( nLength );
356 for( sal_Int32 nN=0; nN<nLength; nN++)
358 aNewCategories.push_back( { uno::Any(aSimplecategories[nN]) } );
363 if( m_bDataInColumns )
364 m_aInternalData.setComplexRowLabels( std::move(aNewCategories) );
365 else
366 m_aInternalData.setComplexColumnLabels( std::move(aNewCategories) );
367 if( bConnectToModel )
368 xDiagram->setCategories(
369 new LabeledDataSequence(
370 createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName ))
374 // data series
375 std::vector< rtl::Reference< DataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xModel ));
376 lcl_internalizeSeries ftor( m_aInternalData, *this, bConnectToModel, m_bDataInColumns );
377 for( const auto& rxScreen : aSeriesVector )
378 ftor( rxScreen );
381 catch( const uno::Exception & )
383 DBG_UNHANDLED_EXCEPTION("chart2");
387 // copy-CTOR
388 InternalDataProvider::InternalDataProvider( const InternalDataProvider & rOther ) :
389 impl::InternalDataProvider_Base(rOther),
390 m_aSequenceMap( rOther.m_aSequenceMap ),
391 m_aInternalData( rOther.m_aInternalData ),
392 m_bDataInColumns( rOther.m_bDataInColumns )
395 InternalDataProvider::~InternalDataProvider()
398 void InternalDataProvider::setChartModel(ChartModel* pChartModel)
400 m_xChartModel = pChartModel;
403 void InternalDataProvider::addDataSequenceToMap(
404 const OUString & rRangeRepresentation,
405 const Reference< chart2::data::XDataSequence > & xSequence )
407 m_aSequenceMap.emplace(
408 rRangeRepresentation,
409 uno::WeakReference< chart2::data::XDataSequence >( xSequence ));
412 void InternalDataProvider::deleteMapReferences( const OUString & rRangeRepresentation )
414 // set sequence to deleted by setting its range to an empty string
415 tSequenceMapRange aRange( m_aSequenceMap.equal_range( rRangeRepresentation ));
416 for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
418 Reference< chart2::data::XDataSequence > xSeq( aIt->second );
419 if( xSeq.is())
421 Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
422 if( xNamed.is())
423 xNamed->setName( OUString());
426 // remove from map
427 m_aSequenceMap.erase( aRange.first, aRange.second );
430 void InternalDataProvider::adaptMapReferences(
431 const OUString & rOldRangeRepresentation,
432 const OUString & rNewRangeRepresentation )
434 tSequenceMapRange aRange( m_aSequenceMap.equal_range( rOldRangeRepresentation ));
435 tSequenceMap aNewElements;
436 for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
438 Reference< chart2::data::XDataSequence > xSeq( aIt->second );
439 if( xSeq.is())
441 Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
442 if( xNamed.is())
443 xNamed->setName( rNewRangeRepresentation );
445 aNewElements.emplace( rNewRangeRepresentation, aIt->second );
447 // erase map values for old index
448 m_aSequenceMap.erase( aRange.first, aRange.second );
449 // add new entries for values with new index
450 m_aSequenceMap.insert( aNewElements.begin(), aNewElements.end() );
453 void InternalDataProvider::increaseMapReferences(
454 sal_Int32 nBegin, sal_Int32 nEnd )
456 for( sal_Int32 nIndex = nEnd - 1; nIndex >= nBegin; --nIndex )
458 adaptMapReferences( OUString::number( nIndex ),
459 OUString::number( nIndex + 1 ));
460 adaptMapReferences( lcl_aLabelRangePrefix + OUString::number( nIndex ),
461 lcl_aLabelRangePrefix + OUString::number( nIndex + 1 ));
465 void InternalDataProvider::decreaseMapReferences(
466 sal_Int32 nBegin, sal_Int32 nEnd )
468 for( sal_Int32 nIndex = nBegin; nIndex < nEnd; ++nIndex )
470 adaptMapReferences( OUString::number( nIndex ),
471 OUString::number( nIndex - 1 ));
472 adaptMapReferences( lcl_aLabelRangePrefix + OUString::number( nIndex ),
473 lcl_aLabelRangePrefix + OUString::number( nIndex - 1 ));
477 rtl::Reference< UncachedDataSequence > InternalDataProvider::createDataSequenceAndAddToMap(
478 const OUString & rRangeRepresentation )
480 rtl::Reference<UncachedDataSequence> xSeq = createDataSequenceFromArray(rRangeRepresentation, u"", u"");
481 if (xSeq.is())
482 return nullptr;
484 xSeq.set(new UncachedDataSequence(this, rRangeRepresentation));
485 addDataSequenceToMap(rRangeRepresentation, xSeq);
486 return xSeq;
489 rtl::Reference<UncachedDataSequence>
490 InternalDataProvider::createDataSequenceFromArray( const OUString& rArrayStr, std::u16string_view rRole, std::u16string_view rRoleQualifier )
492 if (rArrayStr.indexOf('{') != 0 || rArrayStr[rArrayStr.getLength()-1] != '}')
494 // Not an array string.
495 return nullptr;
498 bool bAllNumeric = true;
499 rtl::Reference<UncachedDataSequence> xSeq;
501 const sal_Unicode* p = rArrayStr.getStr();
502 const sal_Unicode* pEnd = p + rArrayStr.getLength();
503 const sal_Unicode* pElem = nullptr;
504 OUString aElem;
506 std::vector<OUString> aRawElems;
507 ++p; // Skip the first '{'.
508 --pEnd; // Skip the last '}'.
509 bool bInQuote = false;
510 for (; p != pEnd; ++p)
512 // Skip next "" within the title text: it's an escaped double quotation mark.
513 if (bInQuote && *p == '"' && *(p + 1) == '"')
515 if (!pElem)
516 pElem = p;
517 ++p;
519 else if (*p == '"')
521 bInQuote = !bInQuote;
522 if (bInQuote)
524 // Opening quote.
525 pElem = nullptr;
527 else
529 // Closing quote.
530 if (pElem)
531 aElem = OUString(pElem, p-pElem);
532 // Non empty string
533 if (!aElem.isEmpty())
534 bAllNumeric = false;
535 // Restore also escaped double quotation marks
536 aRawElems.push_back(aElem.replaceAll("\"\"", "\""));
537 pElem = nullptr;
538 aElem.clear();
540 ++p; // Skip '"'.
541 if (p == pEnd)
542 break;
545 else if (*p == ';' && !bInQuote)
547 // element separator.
548 if (pElem)
549 aElem = OUString(pElem, p-pElem);
550 aRawElems.push_back(aElem);
551 pElem = nullptr;
552 aElem.clear();
554 else if (!pElem)
555 pElem = p;
558 if (pElem)
560 aElem = OUString(pElem, p-pElem);
561 aRawElems.push_back(aElem);
564 if (rRole == u"values-y" || rRole == u"values-first" || rRole == u"values-last" ||
565 rRole == u"values-min" || rRole == u"values-max" || rRole == u"values-size" ||
566 rRole == u"error-bars-y-positive" || rRole == u"error-bars-y-negative")
568 // Column values. Append a new data column and populate it.
570 std::vector<double> aValues;
571 aValues.reserve(aRawElems.size());
572 for (const OUString & aRawElem : aRawElems)
574 if (aRawElem.isEmpty())
575 aValues.push_back(NAN);
576 else
577 aValues.push_back(aRawElem.toDouble());
579 sal_Int32 n = m_aInternalData.appendColumn();
581 m_aInternalData.setColumnValues(n, aValues);
583 OUString aRangeRep = OUString::number(n);
584 xSeq.set(new UncachedDataSequence(this, aRangeRep));
585 addDataSequenceToMap(aRangeRep, xSeq);
587 else if (rRole == u"values-x")
589 std::vector<double> aValues;
590 aValues.reserve(aRawElems.size());
591 if (bAllNumeric)
593 for (const OUString & aRawElem : aRawElems)
595 if (!aRawElem.isEmpty())
596 aValues.push_back(aRawElem.toDouble());
597 else
598 aValues.push_back(NAN);
601 else
603 for (size_t i = 0; i < aRawElems.size(); ++i)
604 aValues.push_back(i+1);
607 sal_Int32 n = m_aInternalData.appendColumn();
608 m_aInternalData.setColumnValues(n, aValues);
610 OUString aRangeRep = OUString::number(n);
611 xSeq.set(new UncachedDataSequence(this, aRangeRep));
612 addDataSequenceToMap(aRangeRep, xSeq);
614 else if (rRole == u"categories")
616 // Category labels.
618 // Store date categories as numbers.
619 bool bStoreNumeric = rRoleQualifier == u"date";
620 double fValue;
621 for (size_t i = 0; i < aRawElems.size(); ++i)
623 if (bStoreNumeric)
625 bool bGetDouble = bAllNumeric && !aRawElems[i].isEmpty();
626 fValue = bGetDouble ? aRawElems[i].toDouble() :
627 std::numeric_limits<double>::quiet_NaN();
629 std::vector<uno::Any> aLabels(1,
630 bStoreNumeric ? uno::Any(fValue) : uno::Any(aRawElems[i]));
631 m_aInternalData.setComplexRowLabel(i, std::move(aLabels));
634 xSeq.set(new UncachedDataSequence(this, lcl_aCategoriesRangeName));
635 addDataSequenceToMap(lcl_aCategoriesRangeName, xSeq);
637 else if (rRole == u"label")
639 // Data series label. There should be only one element. This always
640 // goes to the last data column.
641 sal_Int32 nColSize = m_aInternalData.getColumnCount();
642 if (!aRawElems.empty() && nColSize)
644 // Do not overwrite an existing label (attempted by series with no data values)
645 if (!m_aInternalData.getComplexColumnLabel(nColSize-1)[0].hasValue())
647 std::vector<uno::Any> aLabels(1, uno::Any(aRawElems[0]));
648 m_aInternalData.setComplexColumnLabel(nColSize-1, std::move(aLabels));
651 OUString aRangeRep = lcl_aLabelRangePrefix + OUString::number(nColSize-1);
652 xSeq.set(new UncachedDataSequence(this, aRangeRep));
653 addDataSequenceToMap(aRangeRep, xSeq);
657 return xSeq;
660 Reference< chart2::data::XDataSequence > InternalDataProvider::createDataSequenceAndAddToMap(
661 const OUString & rRangeRepresentation,
662 const OUString & rRole )
664 rtl::Reference< UncachedDataSequence > xSeq =
665 new UncachedDataSequence( this, rRangeRepresentation, rRole );
666 addDataSequenceToMap( rRangeRepresentation, xSeq );
667 return xSeq;
670 // ____ XDataProvider ____
671 sal_Bool SAL_CALL InternalDataProvider::createDataSourcePossible( const Sequence< beans::PropertyValue >& /* aArguments */ )
673 return true;
676 namespace
679 sal_Int32 lcl_getInnerLevelCount( const std::vector< std::vector< uno::Any > >& rLabels )
681 sal_Int32 nCount = 1;//minimum is 1!
682 for (auto const& elemLabel : rLabels)
684 nCount = std::max<sal_Int32>( elemLabel.size(), nCount );
686 return nCount;
689 }//end anonymous namespace
691 Reference< chart2::data::XDataSource > SAL_CALL InternalDataProvider::createDataSource(
692 const Sequence< beans::PropertyValue >& aArguments )
694 OUString aRangeRepresentation;
695 bool bUseColumns = true;
696 bool bFirstCellAsLabel = true;
697 bool bHasCategories = true;
698 uno::Sequence< sal_Int32 > aSequenceMapping;
699 DataSourceHelper::readArguments( aArguments, aRangeRepresentation, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories );
701 if( aRangeRepresentation == lcl_aCategoriesRangeName )
703 //return split complex categories if we have any:
704 std::vector< Reference< chart2::data::XLabeledDataSequence > > aComplexCategories;
705 const std::vector< std::vector< uno::Any > > & aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
706 if( bUseColumns==m_bDataInColumns )
708 sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories );
709 for( sal_Int32 nL=0; nL<nLevelCount; nL++ )
710 aComplexCategories.push_back( new LabeledDataSequence(
711 new UncachedDataSequence( this
712 , lcl_aCategoriesLevelRangeNamePrefix + OUString::number( nL )
713 , lcl_aCategoriesRoleName ) ) );
715 else
717 sal_Int32 nPointCount = m_bDataInColumns ? m_aInternalData.getRowCount() : m_aInternalData.getColumnCount();
718 for( sal_Int32 nP=0; nP<nPointCount; nP++ )
719 aComplexCategories.push_back( new LabeledDataSequence(
720 new UncachedDataSequence( this
721 , lcl_aCategoriesPointRangeNamePrefix + OUString::number( nP )
722 , lcl_aCategoriesRoleName ) ) );
724 //don't add the created sequences to the map as they are used temporarily only ...
725 return new DataSource( comphelper::containerToSequence(aComplexCategories) );
728 OSL_ASSERT( aRangeRepresentation == lcl_aCompleteRange );
730 std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultLSeqVec;
732 // categories
733 if( bHasCategories )
734 aResultLSeqVec.push_back(
735 new LabeledDataSequence( createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName ) ) );
737 // data with labels
738 std::vector< Reference< chart2::data::XLabeledDataSequence > > aDataVec;
739 const sal_Int32 nCount = (bUseColumns ? m_aInternalData.getColumnCount() : m_aInternalData.getRowCount());
740 aDataVec.reserve(nCount);
741 for (sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx)
743 aDataVec.push_back(
744 new LabeledDataSequence(
745 createDataSequenceAndAddToMap( OUString::number( nIdx )),
746 createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::number( nIdx ))));
749 // attention: this data provider has the limitation that it stores
750 // internally if data comes from columns or rows. It is intended for
751 // creating only one used data source.
752 // @todo: add this information in the range representation strings
753 m_bDataInColumns = bUseColumns;
755 //reorder labeled sequences according to aSequenceMapping; ignore categories
756 for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
758 std::vector< LabeledDataSequence* >::size_type nOldIndex = aSequenceMapping[nNewIndex];
759 if( nOldIndex < aDataVec.size() )
761 if( aDataVec[nOldIndex].is() )
763 aResultLSeqVec.push_back( aDataVec[nOldIndex] );
764 aDataVec[nOldIndex] = nullptr;
769 //add left over data sequences to result
770 for (auto const& elem : aDataVec)
772 if( elem.is() )
773 aResultLSeqVec.push_back(elem);
776 return new DataSource( comphelper::containerToSequence(aResultLSeqVec) );
779 Sequence< beans::PropertyValue > SAL_CALL InternalDataProvider::detectArguments(
780 const Reference< chart2::data::XDataSource >& /* xDataSource */ )
782 Sequence< beans::PropertyValue > aArguments{
783 beans::PropertyValue(
784 u"CellRangeRepresentation"_ustr, -1, uno::Any( lcl_aCompleteRange ),
785 beans::PropertyState_DIRECT_VALUE ),
786 beans::PropertyValue(
787 u"DataRowSource"_ustr, -1, uno::Any(
788 m_bDataInColumns
789 ? css::chart::ChartDataRowSource_COLUMNS
790 : css::chart::ChartDataRowSource_ROWS ),
791 beans::PropertyState_DIRECT_VALUE ),
792 // internal data always contains labels and categories
793 beans::PropertyValue(
794 u"FirstCellAsLabel"_ustr, -1, uno::Any( true ), beans::PropertyState_DIRECT_VALUE ),
795 beans::PropertyValue(
796 u"HasCategories"_ustr, -1, uno::Any( true ), beans::PropertyState_DIRECT_VALUE )
798 // #i85913# Sequence Mapping is not needed for internal data, as it is
799 // applied to the data when the data source is created.
801 return aArguments;
804 sal_Bool SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentationPossible( const OUString& /* aRangeRepresentation */ )
806 return true;
809 Reference< chart2::data::XDataSequence > SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentation(
810 const OUString& aRangeRepresentation )
812 if( aRangeRepresentation.match( lcl_aCategoriesRangeName ))
814 OSL_ASSERT( aRangeRepresentation == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
816 // categories
817 return createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName );
819 else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
821 // label
822 sal_Int32 nIndex = o3tl::toInt32(aRangeRepresentation.subView( strlen(lcl_aLabelRangePrefix)));
823 return createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::number( nIndex ));
825 else if ( aRangeRepresentation == "last" )
827 sal_Int32 nIndex = (m_bDataInColumns
828 ? m_aInternalData.getColumnCount()
829 : m_aInternalData.getRowCount()) - 1;
830 return createDataSequenceAndAddToMap( OUString::number( nIndex ));
832 else if( !aRangeRepresentation.isEmpty())
834 // data
835 return createDataSequenceAndAddToMap( aRangeRepresentation );
838 return Reference< chart2::data::XDataSequence >();
841 Reference<chart2::data::XDataSequence> SAL_CALL
842 InternalDataProvider::createDataSequenceByValueArray(
843 const OUString& aRole, const OUString& aRangeRepresentation, const OUString& aRoleQualifier )
845 return createDataSequenceFromArray(aRangeRepresentation, aRole, aRoleQualifier);
848 Reference< sheet::XRangeSelection > SAL_CALL InternalDataProvider::getRangeSelection()
850 // there is no range selection component
851 return Reference< sheet::XRangeSelection >();
854 // ____ XInternalDataProvider ____
855 sal_Bool SAL_CALL InternalDataProvider::hasDataByRangeRepresentation( const OUString& aRange )
857 bool bResult = false;
859 if( aRange.match( lcl_aCategoriesRangeName ))
861 OSL_ASSERT( aRange == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
862 bResult = true;
864 else if( aRange.match( lcl_aLabelRangePrefix ))
866 sal_Int32 nIndex = o3tl::toInt32(aRange.subView( strlen(lcl_aLabelRangePrefix)));
867 bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount()));
869 else
871 sal_Int32 nIndex = aRange.toInt32();
872 bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount()));
875 return bResult;
878 Sequence< uno::Any > SAL_CALL InternalDataProvider::getDataByRangeRepresentation( const OUString& aRange )
880 Sequence< uno::Any > aResult;
882 if( aRange.match( lcl_aLabelRangePrefix ) )
884 auto nIndex = o3tl::toUInt32(aRange.subView( strlen(lcl_aLabelRangePrefix)));
885 std::vector< uno::Any > aComplexLabel = m_bDataInColumns
886 ? m_aInternalData.getComplexColumnLabel( nIndex )
887 : m_aInternalData.getComplexRowLabel( nIndex );
888 if( !aComplexLabel.empty() )
889 aResult = comphelper::containerToSequence(aComplexLabel);
891 else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
893 auto nPointIndex = o3tl::toUInt32(aRange.subView( strlen(lcl_aCategoriesPointRangeNamePrefix) ));
894 std::vector< uno::Any > aComplexCategory = m_bDataInColumns
895 ? m_aInternalData.getComplexRowLabel( nPointIndex )
896 : m_aInternalData.getComplexColumnLabel( nPointIndex );
897 if( !aComplexCategory.empty() )
898 aResult = comphelper::containerToSequence(aComplexCategory);
900 else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
902 sal_Int32 nLevel = o3tl::toInt32(aRange.subView( strlen(lcl_aCategoriesLevelRangeNamePrefix) ));
903 const std::vector< std::vector< uno::Any > > & aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
904 if( nLevel < lcl_getInnerLevelCount( aCategories ) )
905 aResult = CommonFunctors::convertToSequence(aCategories, lcl_copyFromLevel(nLevel));
907 else if( aRange == lcl_aCategoriesRangeName )
909 const std::vector< std::vector< uno::Any > > & aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
910 sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories );
911 if( nLevelCount == 1 )
913 aResult = getDataByRangeRepresentation( lcl_aCategoriesLevelRangeNamePrefix + OUString::number( 0 ) );
915 else
917 // Maybe this 'else' part and the functions is not necessary anymore.
918 const Sequence< OUString > aLabels = m_bDataInColumns ? getRowDescriptions() : getColumnDescriptions();
919 aResult = CommonFunctors::convertToSequence(aLabels, CommonFunctors::makeAny());
922 else
924 sal_Int32 nIndex = aRange.toInt32();
925 if( nIndex >= 0 )
927 const Sequence< double > aData = m_bDataInColumns
928 ? m_aInternalData.getColumnValues(nIndex)
929 : m_aInternalData.getRowValues(nIndex);
930 if( aData.hasElements() )
931 aResult = CommonFunctors::convertToSequence(aData, CommonFunctors::makeAny());
935 return aResult;
938 void SAL_CALL InternalDataProvider::setDataByRangeRepresentation(
939 const OUString& aRange, const Sequence< uno::Any >& aNewData )
941 auto aNewVector( comphelper::sequenceToContainer<std::vector< uno::Any >>(aNewData) );
942 if( aRange.match( lcl_aLabelRangePrefix ) )
944 sal_uInt32 nIndex = o3tl::toInt32(aRange.subView( strlen(lcl_aLabelRangePrefix)));
945 if( m_bDataInColumns )
946 m_aInternalData.setComplexColumnLabel( nIndex, std::move(aNewVector) );
947 else
948 m_aInternalData.setComplexRowLabel( nIndex, std::move(aNewVector) );
950 else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
952 sal_Int32 nPointIndex = o3tl::toInt32(aRange.subView( strlen(lcl_aCategoriesLevelRangeNamePrefix)));
953 if( m_bDataInColumns )
954 m_aInternalData.setComplexRowLabel( nPointIndex, std::move(aNewVector) );
955 else
956 m_aInternalData.setComplexColumnLabel( nPointIndex, std::move(aNewVector) );
958 else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
960 sal_Int32 nLevel = o3tl::toInt32(aRange.subView( strlen(lcl_aCategoriesLevelRangeNamePrefix)));
961 std::vector< std::vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
963 //ensure equal length
964 if( aNewVector.size() > aComplexCategories.size() )
965 aComplexCategories.resize( aNewVector.size() );
966 else if( aNewVector.size() < aComplexCategories.size() )
967 aNewVector.resize( aComplexCategories.size() );
969 transform( aComplexCategories.begin(), aComplexCategories.end(), aNewVector.begin(),
970 aComplexCategories.begin(), lcl_setAnyAtLevel(nLevel) );
972 if( m_bDataInColumns )
973 m_aInternalData.setComplexRowLabels( std::move(aComplexCategories) );
974 else
975 m_aInternalData.setComplexColumnLabels( std::move(aComplexCategories) );
977 else if( aRange == lcl_aCategoriesRangeName )
979 std::vector< std::vector< uno::Any > > aComplexCategories;
980 aComplexCategories.resize( aNewVector.size() );
981 transform( aComplexCategories.begin(), aComplexCategories.end(), aNewVector.begin(),
982 aComplexCategories.begin(), lcl_setAnyAtLevel(0) );
983 if( m_bDataInColumns )
984 m_aInternalData.setComplexRowLabels( std::move(aComplexCategories) );
985 else
986 m_aInternalData.setComplexColumnLabels( std::move(aComplexCategories) );
988 else
990 sal_Int32 nIndex = aRange.toInt32();
991 if( nIndex>=0 )
993 std::vector< double > aNewDataVec;
994 aNewDataVec.reserve(aNewData.getLength());
995 transform( aNewData.begin(), aNewData.end(),
996 back_inserter( aNewDataVec ), CommonFunctors::ToDouble());
997 if( m_bDataInColumns )
998 m_aInternalData.setColumnValues( nIndex, aNewDataVec );
999 else
1000 m_aInternalData.setRowValues( nIndex, aNewDataVec );
1005 void SAL_CALL InternalDataProvider::insertSequence( ::sal_Int32 nAfterIndex )
1007 if( m_bDataInColumns )
1009 increaseMapReferences( nAfterIndex + 1, m_aInternalData.getColumnCount());
1010 m_aInternalData.insertColumn( nAfterIndex );
1012 else
1014 increaseMapReferences( nAfterIndex + 1, m_aInternalData.getRowCount());
1015 m_aInternalData.insertRow( nAfterIndex );
1019 void SAL_CALL InternalDataProvider::deleteSequence( ::sal_Int32 nAtIndex )
1021 deleteMapReferences( OUString::number( nAtIndex ));
1022 deleteMapReferences( lcl_aLabelRangePrefix + OUString::number( nAtIndex ));
1023 if( m_bDataInColumns )
1025 decreaseMapReferences( nAtIndex + 1, m_aInternalData.getColumnCount());
1026 m_aInternalData.deleteColumn( nAtIndex );
1028 else
1030 decreaseMapReferences( nAtIndex + 1, m_aInternalData.getRowCount());
1031 m_aInternalData.deleteRow( nAtIndex );
1035 void SAL_CALL InternalDataProvider::appendSequence()
1037 if( m_bDataInColumns )
1038 m_aInternalData.appendColumn();
1039 else
1040 m_aInternalData.appendRow();
1043 void SAL_CALL InternalDataProvider::insertComplexCategoryLevel( sal_Int32 nLevel )
1045 OSL_ENSURE( nLevel> 0, "you can only insert category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
1046 if( nLevel>0 )
1048 std::vector< std::vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
1049 std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_insertAnyAtLevel(nLevel) );
1050 if( m_bDataInColumns )
1051 m_aInternalData.setComplexRowLabels( std::move(aComplexCategories) );
1052 else
1053 m_aInternalData.setComplexColumnLabels( std::move(aComplexCategories) );
1055 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1056 std::for_each( aRange.first, aRange.second, lcl_setModified());
1059 void SAL_CALL InternalDataProvider::deleteComplexCategoryLevel( sal_Int32 nLevel )
1061 OSL_ENSURE( nLevel>0, "you can only delete category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
1062 if( nLevel>0 )
1064 std::vector< std::vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
1065 std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_removeAnyAtLevel(nLevel) );
1066 if( m_bDataInColumns )
1067 m_aInternalData.setComplexRowLabels( std::move(aComplexCategories) );
1068 else
1069 m_aInternalData.setComplexColumnLabels( std::move(aComplexCategories) );
1071 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1072 std::for_each( aRange.first, aRange.second, lcl_setModified());
1076 void SAL_CALL InternalDataProvider::insertDataPointForAllSequences( ::sal_Int32 nAfterIndex )
1078 sal_Int32 nMaxRep = 0;
1079 if( m_bDataInColumns )
1081 m_aInternalData.insertRow( nAfterIndex );
1082 nMaxRep = m_aInternalData.getColumnCount();
1084 else
1086 m_aInternalData.insertColumn( nAfterIndex );
1087 nMaxRep = m_aInternalData.getRowCount();
1090 // notify change to all affected ranges
1091 tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( u"0"_ustr));
1092 tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
1093 std::for_each( aBegin, aEnd, lcl_setModified());
1095 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1096 std::for_each( aRange.first, aRange.second, lcl_setModified());
1099 void SAL_CALL InternalDataProvider::deleteDataPointForAllSequences( ::sal_Int32 nAtIndex )
1101 sal_Int32 nMaxRep = 0;
1102 if( m_bDataInColumns )
1104 m_aInternalData.deleteRow( nAtIndex );
1105 nMaxRep = m_aInternalData.getColumnCount();
1107 else
1109 m_aInternalData.deleteColumn( nAtIndex );
1110 nMaxRep = m_aInternalData.getRowCount();
1113 // notify change to all affected ranges
1114 tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( u"0"_ustr));
1115 tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
1116 std::for_each( aBegin, aEnd, lcl_setModified());
1118 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1119 std::for_each( aRange.first, aRange.second, lcl_setModified());
1122 void SAL_CALL InternalDataProvider::swapDataPointWithNextOneForAllSequences( ::sal_Int32 nAtIndex )
1124 if( m_bDataInColumns )
1125 m_aInternalData.swapRowWithNext( nAtIndex );
1126 else
1127 m_aInternalData.swapColumnWithNext( nAtIndex );
1128 sal_Int32 nMaxRep = (m_bDataInColumns
1129 ? m_aInternalData.getColumnCount()
1130 : m_aInternalData.getRowCount());
1132 // notify change to all affected ranges
1133 tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( u"0"_ustr));
1134 tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
1135 std::for_each( aBegin, aEnd, lcl_setModified());
1137 tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
1138 std::for_each( aRange.first, aRange.second, lcl_setModified());
1141 void SAL_CALL InternalDataProvider::registerDataSequenceForChanges( const Reference< chart2::data::XDataSequence >& xSeq )
1143 if( xSeq.is())
1144 addDataSequenceToMap( xSeq->getSourceRangeRepresentation(), xSeq );
1147 void SAL_CALL InternalDataProvider::insertDataSeries(::sal_Int32 nAfterIndex)
1149 // call the dialog insertion
1150 DataBrowserModel aDBM(m_xChartModel);
1151 aDBM.insertDataSeries(nAfterIndex);
1154 // ____ XRangeXMLConversion ____
1155 OUString SAL_CALL InternalDataProvider::convertRangeToXML( const OUString& aRangeRepresentation )
1157 XMLRangeHelper::CellRange aRange;
1158 aRange.aTableName = "local-table";
1160 // attention: this data provider has the limitation that it stores
1161 // internally if data comes from columns or rows. It is intended for
1162 // creating only one used data source.
1163 // @todo: add this information in the range representation strings
1164 if( aRangeRepresentation.match( lcl_aCategoriesRangeName ))
1166 OSL_ASSERT( aRangeRepresentation == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
1167 aRange.aUpperLeft.bIsEmpty = false;
1168 if( m_bDataInColumns )
1170 aRange.aUpperLeft.nColumn = 0;
1171 aRange.aUpperLeft.nRow = 1;
1172 aRange.aLowerRight = aRange.aUpperLeft;
1173 aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
1175 else
1177 aRange.aUpperLeft.nColumn = 1;
1178 aRange.aUpperLeft.nRow = 0;
1179 aRange.aLowerRight = aRange.aUpperLeft;
1180 aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
1183 else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
1185 sal_Int32 nIndex = o3tl::toInt32(aRangeRepresentation.subView( strlen(lcl_aLabelRangePrefix)));
1186 aRange.aUpperLeft.bIsEmpty = false;
1187 aRange.aLowerRight.bIsEmpty = true;
1188 if( m_bDataInColumns )
1190 aRange.aUpperLeft.nColumn = nIndex + 1;
1191 aRange.aUpperLeft.nRow = 0;
1193 else
1195 aRange.aUpperLeft.nColumn = 0;
1196 aRange.aUpperLeft.nRow = nIndex + 1;
1199 else if( aRangeRepresentation == lcl_aCompleteRange )
1201 aRange.aUpperLeft.bIsEmpty = false;
1202 aRange.aLowerRight.bIsEmpty = false;
1203 aRange.aUpperLeft.nColumn = 0;
1204 aRange.aUpperLeft.nRow = 0;
1205 aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
1206 aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
1208 else
1210 sal_Int32 nIndex = aRangeRepresentation.toInt32();
1211 aRange.aUpperLeft.bIsEmpty = false;
1212 if( m_bDataInColumns )
1214 aRange.aUpperLeft.nColumn = nIndex + 1;
1215 aRange.aUpperLeft.nRow = 1;
1216 aRange.aLowerRight = aRange.aUpperLeft;
1217 aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
1219 else
1221 aRange.aUpperLeft.nColumn = 1;
1222 aRange.aUpperLeft.nRow = nIndex + 1;
1223 aRange.aLowerRight = aRange.aUpperLeft;
1224 aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
1228 return XMLRangeHelper::getXMLStringFromCellRange( aRange );
1231 OUString SAL_CALL InternalDataProvider::convertRangeFromXML( const OUString& aXMLRange )
1233 // Handle non-standards-conforming table:cell-range-address="PivotChart", see
1234 // <https://bugs.documentfoundation.org/show_bug.cgi?id=112783> "PIVOT CHARTS: Save produces
1235 // invalid file because of invalid cell address":
1236 if (aXMLRange == "PivotChart") {
1237 return u""_ustr;
1240 static constexpr OUString aPivotTableID(u"PT@"_ustr);
1241 if (aXMLRange.startsWith(aPivotTableID))
1242 return aXMLRange.copy(aPivotTableID.getLength());
1244 XMLRangeHelper::CellRange aRange( XMLRangeHelper::getCellRangeFromXMLString( aXMLRange ));
1245 if( aRange.aUpperLeft.bIsEmpty )
1247 OSL_ENSURE( aRange.aLowerRight.bIsEmpty, "Weird Range" );
1248 return OUString();
1251 // "all"
1252 if( !aRange.aLowerRight.bIsEmpty &&
1253 ( aRange.aUpperLeft.nColumn != aRange.aLowerRight.nColumn ) &&
1254 ( aRange.aUpperLeft.nRow != aRange.aLowerRight.nRow ) )
1255 return lcl_aCompleteRange;
1257 // attention: this data provider has the limitation that it stores
1258 // internally if data comes from columns or rows. It is intended for
1259 // creating only one used data source.
1260 // @todo: add this information in the range representation strings
1262 // data in columns
1263 if( m_bDataInColumns )
1265 if( aRange.aUpperLeft.nColumn == 0 )
1266 return lcl_aCategoriesRangeName;
1267 if( aRange.aUpperLeft.nRow == 0 )
1268 return lcl_aLabelRangePrefix + OUString::number( aRange.aUpperLeft.nColumn - 1 );
1270 return OUString::number( aRange.aUpperLeft.nColumn - 1 );
1273 // data in rows
1274 if( aRange.aUpperLeft.nRow == 0 )
1275 return lcl_aCategoriesRangeName;
1276 if( aRange.aUpperLeft.nColumn == 0 )
1277 return lcl_aLabelRangePrefix + OUString::number( aRange.aUpperLeft.nRow - 1 );
1279 return OUString::number( aRange.aUpperLeft.nRow - 1 );
1282 namespace
1285 template< class Type >
1286 Sequence< Sequence< Type > > lcl_convertVectorVectorToSequenceSequence( const std::vector< std::vector< Type > >& rIn )
1288 return CommonFunctors::convertToSequence(rIn, [](auto& v)
1289 { return comphelper::containerToSequence(v); });
1292 template< class Type >
1293 std::vector< std::vector< Type > > lcl_convertSequenceSequenceToVectorVector( const Sequence< Sequence< Type > >& rIn )
1295 std::vector< std::vector< Type > > aRet;
1296 aRet.reserve(rIn.getLength());
1297 std::transform(rIn.begin(), rIn.end(), std::back_inserter(aRet),
1298 [](auto& s) { return comphelper::sequenceToContainer<std::vector<Type>>(s); });
1299 return aRet;
1302 Sequence< Sequence< OUString > > lcl_convertComplexAnyVectorToStringSequence( const std::vector< std::vector< uno::Any > >& rIn )
1304 return CommonFunctors::convertToSequence(
1305 rIn,
1306 [](auto& v) { return CommonFunctors::convertToSequence(v, CommonFunctors::ToString()); });
1309 std::vector< std::vector< uno::Any > > lcl_convertComplexStringSequenceToAnyVector( const Sequence< Sequence< OUString > >& rIn )
1311 std::vector< std::vector< uno::Any > > aRet;
1312 aRet.reserve(rIn.getLength());
1313 std::transform(rIn.begin(), rIn.end(), std::back_inserter(aRet),
1314 [](auto& s) { return lcl_StringToAnyVector(s); });
1315 return aRet;
1318 class SplitCategoriesProvider_ForComplexDescriptions : public SplitCategoriesProvider
1320 public:
1322 explicit SplitCategoriesProvider_ForComplexDescriptions( const std::vector< std::vector< uno::Any > >& rComplexDescriptions )
1323 : m_rComplexDescriptions( rComplexDescriptions )
1326 virtual sal_Int32 getLevelCount() const override;
1327 virtual uno::Sequence< OUString > getStringsForLevel( sal_Int32 nIndex ) const override;
1329 private:
1330 const std::vector< std::vector< uno::Any > >& m_rComplexDescriptions;
1333 sal_Int32 SplitCategoriesProvider_ForComplexDescriptions::getLevelCount() const
1335 return lcl_getInnerLevelCount( m_rComplexDescriptions );
1337 uno::Sequence< OUString > SplitCategoriesProvider_ForComplexDescriptions::getStringsForLevel( sal_Int32 nLevel ) const
1339 if( nLevel < lcl_getInnerLevelCount( m_rComplexDescriptions ) )
1340 return CommonFunctors::convertToSequence(m_rComplexDescriptions, lcl_getStringFromLevelVector(nLevel));
1341 return {};
1344 }//anonymous namespace
1346 // ____ XDateCategories ____
1347 Sequence< double > SAL_CALL InternalDataProvider::getDateCategories()
1349 const std::vector< std::vector< uno::Any > > & aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
1350 sal_Int32 nCount = aCategories.size();
1351 Sequence< double > aDoubles( nCount );
1352 auto aDoublesRange = asNonConstRange(aDoubles);
1353 sal_Int32 nN=0;
1354 for (auto const& category : aCategories)
1356 double fValue;
1357 if( category.empty() || !(category[0]>>=fValue) )
1358 fValue = std::numeric_limits<double>::quiet_NaN();
1359 aDoublesRange[nN++]=fValue;
1361 return aDoubles;
1364 void SAL_CALL InternalDataProvider::setDateCategories( const Sequence< double >& rDates )
1366 sal_Int32 nCount = rDates.getLength();
1367 std::vector< std::vector< uno::Any > > aNewCategories;
1368 aNewCategories.reserve(nCount);
1369 std::vector< uno::Any > aSingleLabel(1);
1371 for(sal_Int32 nN=0; nN<nCount; ++nN )
1373 aSingleLabel[0] <<= rDates[nN];
1374 aNewCategories.push_back(aSingleLabel);
1377 if( m_bDataInColumns )
1378 m_aInternalData.setComplexRowLabels( std::move(aNewCategories) );
1379 else
1380 m_aInternalData.setComplexColumnLabels( std::move(aNewCategories) );
1383 // ____ XAnyDescriptionAccess ____
1384 Sequence< Sequence< uno::Any > > SAL_CALL InternalDataProvider::getAnyRowDescriptions()
1386 return lcl_convertVectorVectorToSequenceSequence( m_aInternalData.getComplexRowLabels() );
1388 void SAL_CALL InternalDataProvider::setAnyRowDescriptions( const Sequence< Sequence< uno::Any > >& aRowDescriptions )
1390 m_aInternalData.setComplexRowLabels( lcl_convertSequenceSequenceToVectorVector( aRowDescriptions ) );
1392 Sequence< Sequence< uno::Any > > SAL_CALL InternalDataProvider::getAnyColumnDescriptions()
1394 return lcl_convertVectorVectorToSequenceSequence( m_aInternalData.getComplexColumnLabels() );
1396 void SAL_CALL InternalDataProvider::setAnyColumnDescriptions( const Sequence< Sequence< uno::Any > >& aColumnDescriptions )
1398 m_aInternalData.setComplexColumnLabels( lcl_convertSequenceSequenceToVectorVector( aColumnDescriptions ) );
1401 // ____ XComplexDescriptionAccess ____
1402 Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexRowDescriptions()
1404 return lcl_convertComplexAnyVectorToStringSequence( m_aInternalData.getComplexRowLabels() );
1406 void SAL_CALL InternalDataProvider::setComplexRowDescriptions( const Sequence< Sequence< OUString > >& aRowDescriptions )
1408 m_aInternalData.setComplexRowLabels( lcl_convertComplexStringSequenceToAnyVector(aRowDescriptions) );
1410 Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexColumnDescriptions()
1412 return lcl_convertComplexAnyVectorToStringSequence( m_aInternalData.getComplexColumnLabels() );
1414 void SAL_CALL InternalDataProvider::setComplexColumnDescriptions( const Sequence< Sequence< OUString > >& aColumnDescriptions )
1416 m_aInternalData.setComplexColumnLabels( lcl_convertComplexStringSequenceToAnyVector(aColumnDescriptions) );
1419 // ____ XChartDataArray ____
1420 Sequence< Sequence< double > > SAL_CALL InternalDataProvider::getData()
1422 return m_aInternalData.getData();
1425 void SAL_CALL InternalDataProvider::setData( const Sequence< Sequence< double > >& rDataInRows )
1427 return m_aInternalData.setData( rDataInRows );
1430 void SAL_CALL InternalDataProvider::setRowDescriptions( const Sequence< OUString >& aRowDescriptions )
1432 std::vector< std::vector< uno::Any > > aComplexDescriptions( aRowDescriptions.getLength() );
1433 transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aRowDescriptions.begin(),
1434 aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
1435 m_aInternalData.setComplexRowLabels( std::move(aComplexDescriptions) );
1438 void SAL_CALL InternalDataProvider::setColumnDescriptions( const Sequence< OUString >& aColumnDescriptions )
1440 std::vector< std::vector< uno::Any > > aComplexDescriptions( aColumnDescriptions.getLength() );
1441 transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aColumnDescriptions.begin(),
1442 aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
1443 m_aInternalData.setComplexColumnLabels( std::move(aComplexDescriptions) );
1446 Sequence< OUString > SAL_CALL InternalDataProvider::getRowDescriptions()
1448 const std::vector< std::vector< uno::Any > > & aComplexLabels( m_aInternalData.getComplexRowLabels() );
1449 SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels );
1450 return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider );
1453 Sequence< OUString > SAL_CALL InternalDataProvider::getColumnDescriptions()
1455 const std::vector< std::vector< uno::Any > > & aComplexLabels( m_aInternalData.getComplexColumnLabels() );
1456 SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels );
1457 return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider );
1460 // ____ XChartData (base of XChartDataArray) ____
1461 void SAL_CALL InternalDataProvider::addChartDataChangeEventListener(
1462 const Reference< css::chart::XChartDataChangeEventListener >& )
1466 void SAL_CALL InternalDataProvider::removeChartDataChangeEventListener(
1467 const Reference< css::chart::XChartDataChangeEventListener >& )
1471 double SAL_CALL InternalDataProvider::getNotANumber()
1473 return std::numeric_limits<double>::quiet_NaN();
1476 sal_Bool SAL_CALL InternalDataProvider::isNotANumber( double nNumber )
1478 return std::isnan( nNumber )
1479 || std::isinf( nNumber );
1481 // lang::XInitialization:
1482 void SAL_CALL InternalDataProvider::initialize(const uno::Sequence< uno::Any > & _aArguments)
1484 comphelper::SequenceAsHashMap aArgs(_aArguments);
1485 if ( aArgs.getUnpackedValueOrDefault( u"CreateDefaultData"_ustr, false ) )
1486 m_aInternalData.createDefaultData();
1489 // ____ XCloneable ____
1490 Reference< util::XCloneable > SAL_CALL InternalDataProvider::createClone()
1492 return Reference< util::XCloneable >( new InternalDataProvider( *this ));
1495 OUString SAL_CALL InternalDataProvider::getImplementationName()
1497 // note: in xmloff this name is used to indicate usage of own data
1498 return u"com.sun.star.comp.chart.InternalDataProvider"_ustr;
1501 sal_Bool SAL_CALL InternalDataProvider::supportsService( const OUString& rServiceName )
1503 return cppu::supportsService(this, rServiceName);
1506 css::uno::Sequence< OUString > SAL_CALL InternalDataProvider::getSupportedServiceNames()
1508 return { u"com.sun.star.chart2.data.DataProvider"_ustr };
1511 } // namespace chart
1513 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1514 com_sun_star_comp_chart_InternalDataProvider_get_implementation(css::uno::XComponentContext *,
1515 css::uno::Sequence<css::uno::Any> const &)
1517 return cppu::acquire(new ::chart::InternalDataProvider);
1520 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */