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