1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
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
;
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
> >
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());
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
);
89 Reference
< util::XModifiable
> xMod( xSeq
, uno::UNO_QUERY
);
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
;
121 auto aValues( comphelper::sequenceToContainer
<std::vector
< double >>( xValues
->getNumericalData()));
122 if( m_bDataInColumns
)
123 m_rInternalData
.setColumnValues( nNewIndex
, aValues
);
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
));
137 if( m_bDataInColumns
)
138 m_rInternalData
.setComplexColumnLabel( nNewIndex
, lcl_StringToAnyVector( xLabel
->getTextualData() ) );
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
) );
153 if( m_bConnectToModel
)
154 aNewSeriesData
[i
].set( new LabeledDataSequence( xNewValues
) );
157 if( m_bConnectToModel
)
158 xSeries
->setData( aNewSeriesData
);
162 InternalData
& m_rInternalData
;
163 InternalDataProvider
& m_rProvider
;
164 bool m_bConnectToModel
;
165 bool m_bDataInColumns
;
168 struct lcl_copyFromLevel
172 explicit lcl_copyFromLevel( sal_Int32 nLevel
) : m_nLevel( nLevel
)
175 uno::Any
operator() ( const std::vector
< uno::Any
>& rVector
)
178 if( m_nLevel
< static_cast< sal_Int32
>(rVector
.size()) )
179 aRet
= rVector
[m_nLevel
];
187 struct lcl_getStringFromLevelVector
191 explicit lcl_getStringFromLevelVector( sal_Int32 nLevel
) : m_nLevel( nLevel
)
194 OUString
operator() ( const std::vector
< uno::Any
>& rVector
)
197 if( m_nLevel
< static_cast< sal_Int32
>(rVector
.size()) )
198 aString
= CommonFunctors::ToString()(rVector
[m_nLevel
]);
206 struct lcl_setAnyAtLevel
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
;
226 struct lcl_setAnyAtLevelFromStringSequence
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
;
246 struct lcl_insertAnyAtLevel
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 );
261 rVector
.insert( rVector
.begin() + m_nLevel
, uno::Any() );
269 struct lcl_removeAnyAtLevel
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
);
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
)
302 m_xChartModel
= xModel
.get();
305 rtl::Reference
< Diagram
> xDiagram( xModel
->getFirstChartDiagram() );
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
;
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
] );
338 Sequence
< uno::Any
> aDataSeq
;
339 Reference
< chart2::data::XDataSequence
> xSeq( xLDS
->getValues() );
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
) );
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
) );
366 m_aInternalData
.setComplexColumnLabels( std::move(aNewCategories
) );
367 if( bConnectToModel
)
368 xDiagram
->setCategories(
369 new LabeledDataSequence(
370 createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName
))
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
)
381 catch( const uno::Exception
& )
383 DBG_UNHANDLED_EXCEPTION("chart2");
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
);
421 Reference
< container::XNamed
> xNamed( xSeq
, uno::UNO_QUERY
);
423 xNamed
->setName( OUString());
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
);
441 Reference
< container::XNamed
> xNamed( xSeq
, uno::UNO_QUERY
);
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
"");
484 xSeq
.set(new UncachedDataSequence(this, rRangeRepresentation
));
485 addDataSequenceToMap(rRangeRepresentation
, 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.
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;
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) == '"')
521 bInQuote
= !bInQuote
;
531 aElem
= OUString(pElem
, p
-pElem
);
533 if (!aElem
.isEmpty())
535 // Restore also escaped double quotation marks
536 aRawElems
.push_back(aElem
.replaceAll("\"\"", "\""));
545 else if (*p
== ';' && !bInQuote
)
547 // element separator.
549 aElem
= OUString(pElem
, p
-pElem
);
550 aRawElems
.push_back(aElem
);
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
);
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());
593 for (const OUString
& aRawElem
: aRawElems
)
595 if (!aRawElem
.isEmpty())
596 aValues
.push_back(aRawElem
.toDouble());
598 aValues
.push_back(NAN
);
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")
618 // Store date categories as numbers.
619 bool bStoreNumeric
= rRoleQualifier
== u
"date";
621 for (size_t i
= 0; i
< aRawElems
.size(); ++i
)
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
);
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
);
670 // ____ XDataProvider ____
671 sal_Bool SAL_CALL
InternalDataProvider::createDataSourcePossible( const Sequence
< beans::PropertyValue
>& /* aArguments */ )
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
);
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
) ) );
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
;
734 aResultLSeqVec
.push_back(
735 new LabeledDataSequence( createDataSequenceAndAddToMap( lcl_aCategoriesRangeName
, lcl_aCategoriesRoleName
) ) );
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
)
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
)
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(
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.
804 sal_Bool SAL_CALL
InternalDataProvider::createDataSequenceByRangeRepresentationPossible( const OUString
& /* aRangeRepresentation */ )
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
817 return createDataSequenceAndAddToMap( lcl_aCategoriesRangeName
, lcl_aCategoriesRoleName
);
819 else if( aRangeRepresentation
.match( lcl_aLabelRangePrefix
))
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())
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
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()));
871 sal_Int32 nIndex
= aRange
.toInt32();
872 bResult
= (nIndex
< (m_bDataInColumns
? m_aInternalData
.getColumnCount(): m_aInternalData
.getRowCount()));
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 ) );
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());
924 sal_Int32 nIndex
= aRange
.toInt32();
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());
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
) );
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
) );
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
) );
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
) );
986 m_aInternalData
.setComplexColumnLabels( std::move(aComplexCategories
) );
990 sal_Int32 nIndex
= aRange
.toInt32();
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
);
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
);
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
);
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();
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
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
) );
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
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
) );
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();
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();
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
);
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
)
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();
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;
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();
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();
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") {
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" );
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
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 );
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 );
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
); });
1302 Sequence
< Sequence
< OUString
> > lcl_convertComplexAnyVectorToStringSequence( const std::vector
< std::vector
< uno::Any
> >& rIn
)
1304 return CommonFunctors::convertToSequence(
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
); });
1318 class SplitCategoriesProvider_ForComplexDescriptions
: public SplitCategoriesProvider
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
;
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
));
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
);
1354 for (auto const& category
: aCategories
)
1357 if( category
.empty() || !(category
[0]>>=fValue
) )
1358 fValue
= std::numeric_limits
<double>::quiet_NaN();
1359 aDoublesRange
[nN
++]=fValue
;
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
) );
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: */