nss: upgrade to release 3.73
[LibreOffice.git] / chart2 / source / tools / DataSourceHelper.cxx
blob3d6bb54592fe08630b1eeb89138445c4b0f65004
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <DataSourceHelper.hxx>
21 #include <ChartModel.hxx>
22 #include <ChartModelHelper.hxx>
23 #include <DiagramHelper.hxx>
24 #include <DataSeriesHelper.hxx>
25 #include <DataSource.hxx>
26 #include <ControllerLockGuard.hxx>
27 #include <CachedDataSequence.hxx>
28 #include <LabeledDataSequence.hxx>
29 #include <unonames.hxx>
31 #include <com/sun/star/chart2/XChartDocument.hpp>
32 #include <com/sun/star/chart2/data/XDataSource.hpp>
33 #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
35 #include <com/sun/star/chart/ChartDataRowSource.hpp>
36 #include <com/sun/star/chart/ErrorBarStyle.hpp>
37 #include <tools/diagnose_ex.h>
39 namespace chart
41 using namespace ::com::sun::star;
42 using namespace ::com::sun::star::chart2;
43 using ::com::sun::star::uno::Reference;
44 using ::com::sun::star::uno::Sequence;
46 namespace
48 void lcl_addRanges( std::vector< OUString > & rOutResult,
49 const uno::Reference< data::XLabeledDataSequence > & xLabeledSeq )
51 if( ! xLabeledSeq.is())
52 return;
53 uno::Reference< data::XDataSequence > xSeq( xLabeledSeq->getLabel());
54 if( xSeq.is())
55 rOutResult.push_back( xSeq->getSourceRangeRepresentation());
56 xSeq.set( xLabeledSeq->getValues());
57 if( xSeq.is())
58 rOutResult.push_back( xSeq->getSourceRangeRepresentation());
61 void lcl_addDataSourceRanges(
62 std::vector< OUString > & rOutResult,
63 const uno::Reference< data::XDataSource > & xDataSource )
65 if( xDataSource.is() )
67 const auto aDataSequences(xDataSource->getDataSequences());
68 for (const auto& rDataSequence : aDataSequences)
69 lcl_addRanges(rOutResult, rDataSequence);
73 void lcl_addErrorBarRanges(
74 std::vector< OUString > & rOutResult,
75 const uno::Reference< XDataSeries > & xDataSeries )
77 uno::Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
78 if( !xSeriesProp.is())
79 return;
81 try
83 uno::Reference< beans::XPropertySet > xErrorBarProp;
84 if( ( xSeriesProp->getPropertyValue( CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarProp ) &&
85 xErrorBarProp.is())
87 sal_Int32 eStyle = css::chart::ErrorBarStyle::NONE;
88 if( ( xErrorBarProp->getPropertyValue( "ErrorBarStyle") >>= eStyle ) &&
89 eStyle == css::chart::ErrorBarStyle::FROM_DATA )
91 uno::Reference< data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY );
92 if( xErrorBarDataSource.is() )
93 lcl_addDataSourceRanges( rOutResult, xErrorBarDataSource );
97 if( ( xSeriesProp->getPropertyValue(CHART_UNONAME_ERRORBAR_X) >>= xErrorBarProp ) && xErrorBarProp.is())
99 sal_Int32 eStyle = css::chart::ErrorBarStyle::NONE;
100 if( ( xErrorBarProp->getPropertyValue("ErrorBarStyle") >>= eStyle ) &&
101 eStyle == css::chart::ErrorBarStyle::FROM_DATA )
103 uno::Reference< data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY );
104 if( xErrorBarDataSource.is() )
105 lcl_addDataSourceRanges( rOutResult, xErrorBarDataSource );
109 catch( const uno::Exception & )
111 DBG_UNHANDLED_EXCEPTION("chart2");
115 } // anonymous namespace
117 Reference< chart2::data::XDataSource > DataSourceHelper::createDataSource(
118 const Sequence< Reference< chart2::data::XLabeledDataSequence > >& rSequences )
120 return new DataSource(rSequences);
123 Reference< chart2::data::XDataSequence > DataSourceHelper::createCachedDataSequence()
125 return new ::chart::CachedDataSequence();
128 Reference< chart2::data::XDataSequence > DataSourceHelper::createCachedDataSequence( const OUString& rSingleText )
130 return new ::chart::CachedDataSequence( rSingleText );
133 Reference< chart2::data::XLabeledDataSequence > DataSourceHelper::createLabeledDataSequence(
134 const Reference< chart2::data::XDataSequence >& xValues ,
135 const Reference< chart2::data::XDataSequence >& xLabels )
137 return new ::chart::LabeledDataSequence( xValues, xLabels );
140 Reference< chart2::data::XLabeledDataSequence > DataSourceHelper::createLabeledDataSequence(
141 const Reference< chart2::data::XDataSequence >& xValues )
143 return new ::chart::LabeledDataSequence( xValues );
146 Reference< chart2::data::XLabeledDataSequence > DataSourceHelper::createLabeledDataSequence()
148 return new ::chart::LabeledDataSequence;
151 uno::Sequence< beans::PropertyValue > DataSourceHelper::createArguments(
152 bool bUseColumns, bool bFirstCellAsLabel, bool bHasCategories )
154 css::chart::ChartDataRowSource eRowSource = css::chart::ChartDataRowSource_ROWS;
155 if( bUseColumns )
156 eRowSource = css::chart::ChartDataRowSource_COLUMNS;
158 uno::Sequence< beans::PropertyValue > aArguments(3);
159 aArguments[0] = beans::PropertyValue( "DataRowSource"
160 , -1, uno::Any( eRowSource )
161 , beans::PropertyState_DIRECT_VALUE );
162 aArguments[1] = beans::PropertyValue( "FirstCellAsLabel"
163 , -1, uno::Any( bFirstCellAsLabel )
164 , beans::PropertyState_DIRECT_VALUE );
165 aArguments[2] = beans::PropertyValue( "HasCategories"
166 , -1, uno::Any( bHasCategories )
167 , beans::PropertyState_DIRECT_VALUE );
169 return aArguments;
172 uno::Sequence< beans::PropertyValue > DataSourceHelper::createArguments(
173 const OUString & rRangeRepresentation,
174 const uno::Sequence< sal_Int32 >& rSequenceMapping,
175 bool bUseColumns, bool bFirstCellAsLabel, bool bHasCategories )
177 uno::Sequence< beans::PropertyValue > aArguments( createArguments( bUseColumns, bFirstCellAsLabel, bHasCategories ));
178 aArguments.realloc( aArguments.getLength() + 1 );
179 aArguments[aArguments.getLength() - 1] =
180 beans::PropertyValue( "CellRangeRepresentation"
181 , -1, uno::Any( rRangeRepresentation )
182 , beans::PropertyState_DIRECT_VALUE );
183 if( rSequenceMapping.hasElements() )
185 aArguments.realloc( aArguments.getLength() + 1 );
186 aArguments[aArguments.getLength() - 1] =
187 beans::PropertyValue( "SequenceMapping"
188 , -1, uno::Any( rSequenceMapping )
189 , beans::PropertyState_DIRECT_VALUE );
191 return aArguments;
194 void DataSourceHelper::readArguments( const uno::Sequence< beans::PropertyValue >& rArguments
195 , OUString & rRangeRepresentation, uno::Sequence< sal_Int32 >& rSequenceMapping
196 , bool& bUseColumns, bool& bFirstCellAsLabel, bool& bHasCategories )
198 for(const beans::PropertyValue& rProperty : rArguments)
200 if ( rProperty.Name == "DataRowSource" )
202 css::chart::ChartDataRowSource eRowSource;
203 if( rProperty.Value >>= eRowSource )
204 bUseColumns = (eRowSource==css::chart::ChartDataRowSource_COLUMNS);
206 else if ( rProperty.Name == "FirstCellAsLabel" )
208 rProperty.Value >>= bFirstCellAsLabel;
210 else if ( rProperty.Name == "HasCategories" )
212 rProperty.Value >>= bHasCategories;
214 else if ( rProperty.Name == "CellRangeRepresentation" )
216 rProperty.Value >>= rRangeRepresentation;
218 else if ( rProperty.Name == "SequenceMapping" )
220 rProperty.Value >>= rSequenceMapping;
225 uno::Reference< chart2::data::XDataSource > DataSourceHelper::pressUsedDataIntoRectangularFormat(
226 const uno::Reference< chart2::XChartDocument >& xChartDoc )
228 std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultVector;
230 //categories are always the first sequence
231 Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
233 Reference< chart2::data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) );
234 if( xCategories.is() )
235 aResultVector.push_back( xCategories );
237 std::vector< Reference< chart2::XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
238 uno::Reference< chart2::data::XDataSource > xSeriesSource(
239 DataSeriesHelper::getDataSource( comphelper::containerToSequence(aSeriesVector) ) );
240 const Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xSeriesSource->getDataSequences() );
242 //the first x-values is always the next sequence //todo ... other x-values get lost for old format
243 Reference< chart2::data::XLabeledDataSequence > xXValues(
244 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, "values-x" ) );
245 if( xXValues.is() )
246 aResultVector.push_back( xXValues );
248 //add all other sequences now without x-values
249 for( Reference< chart2::data::XLabeledDataSequence > const & labeledData : aDataSequences )
251 OUString aRole = DataSeriesHelper::getRole(labeledData);
252 if( aRole != "values-x" )
253 aResultVector.push_back( labeledData );
256 return new DataSource( comphelper::containerToSequence(aResultVector) );
259 uno::Sequence< OUString > DataSourceHelper::getUsedDataRanges(
260 const uno::Reference< chart2::XDiagram > & xDiagram )
262 std::vector< OUString > aResult;
264 if( xDiagram.is())
266 uno::Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) );
267 if( xCategories.is() )
268 lcl_addRanges( aResult, xCategories );
270 std::vector< uno::Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
271 for (auto const& series : aSeriesVector)
273 uno::Reference< data::XDataSource > xDataSource(series, uno::UNO_QUERY);
274 lcl_addDataSourceRanges( aResult, xDataSource );
275 lcl_addErrorBarRanges( aResult, series );
279 return comphelper::containerToSequence( aResult );
282 uno::Sequence< OUString > DataSourceHelper::getUsedDataRanges( const uno::Reference< frame::XModel > & xChartModel )
284 uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
285 return getUsedDataRanges( xDiagram );
288 uno::Reference< chart2::data::XDataSource > DataSourceHelper::getUsedData(
289 const uno::Reference< chart2::XChartDocument >& xChartDoc )
291 return pressUsedDataIntoRectangularFormat( xChartDoc );
294 uno::Reference< chart2::data::XDataSource > DataSourceHelper::getUsedData(
295 const uno::Reference< frame::XModel >& xChartModel )
297 std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aResult;
299 uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
300 uno::Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) );
301 if( xCategories.is() )
302 aResult.push_back( xCategories );
304 std::vector< uno::Reference< XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xChartModel ) );
305 for (auto const& series : aSeriesVector)
307 uno::Reference< data::XDataSource > xDataSource(series, uno::UNO_QUERY);
308 if( !xDataSource.is() )
309 continue;
310 uno::Sequence< uno::Reference< data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );
311 aResult.insert( aResult.end(), aDataSequences.begin(), aDataSequences.end() );
314 return uno::Reference< chart2::data::XDataSource >(
315 new DataSource( comphelper::containerToSequence( aResult )));
318 uno::Reference< chart2::data::XDataSource > DataSourceHelper::getUsedData(
319 ChartModel& rModel )
321 std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aResult;
323 uno::Reference< XDiagram > xDiagram( rModel.getFirstDiagram() );
324 uno::Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) );
325 if( xCategories.is() )
326 aResult.push_back( xCategories );
328 std::vector< uno::Reference< XDataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( rModel ) );
329 for (auto const& series : aSeriesVector)
331 uno::Reference< data::XDataSource > xDataSource(series, uno::UNO_QUERY);
332 if( !xDataSource.is() )
333 continue;
334 uno::Sequence< uno::Reference< data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );
335 aResult.insert( aResult.end(), aDataSequences.begin(), aDataSequences.end() );
338 return uno::Reference< chart2::data::XDataSource >(
339 new DataSource( comphelper::containerToSequence( aResult )));
342 bool DataSourceHelper::detectRangeSegmentation(
343 const uno::Reference<
344 frame::XModel >& xChartModel
345 , OUString& rOutRangeString
346 , css::uno::Sequence< sal_Int32 >& rSequenceMapping
347 , bool& rOutUseColumns
348 , bool& rOutFirstCellAsLabel
349 , bool& rOutHasCategories )
351 bool bSomethingDetected = false;
353 uno::Reference< XChartDocument > xChartDocument( xChartModel, uno::UNO_QUERY );
354 if( !xChartDocument.is() )
355 return bSomethingDetected;
356 uno::Reference< data::XDataProvider > xDataProvider( xChartDocument->getDataProvider() );
357 if( !xDataProvider.is() )
358 return bSomethingDetected;
362 DataSourceHelper::readArguments(
363 xDataProvider->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument ) ),
364 rOutRangeString, rSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories );
365 bSomethingDetected = !rOutRangeString.isEmpty();
367 uno::Reference< chart2::data::XLabeledDataSequence > xCategories(
368 DiagramHelper::getCategoriesFromDiagram( xChartDocument->getFirstDiagram() ));
369 rOutHasCategories = xCategories.is();
371 catch( uno::Exception & )
373 DBG_UNHANDLED_EXCEPTION("chart2");
375 return bSomethingDetected;
378 bool DataSourceHelper::allArgumentsForRectRangeDetected(
379 const uno::Reference< chart2::XChartDocument >& xChartDocument )
381 bool bHasDataRowSource = false;
382 bool bHasFirstCellAsLabel = false;
383 bool bHasCellRangeRepresentation = false;
385 uno::Reference< data::XDataProvider > xDataProvider( xChartDocument->getDataProvider() );
386 if( !xDataProvider.is() )
387 return false;
391 const uno::Sequence< beans::PropertyValue > aArguments(
392 xDataProvider->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument )));
393 for(const beans::PropertyValue& rProperty : aArguments)
395 if ( rProperty.Name == "DataRowSource" )
397 bHasDataRowSource =
398 (rProperty.Value.hasValue() && rProperty.Value.isExtractableTo(
399 cppu::UnoType<css::chart::ChartDataRowSource>::get()));
401 else if ( rProperty.Name == "FirstCellAsLabel" )
403 bHasFirstCellAsLabel =
404 (rProperty.Value.hasValue() && rProperty.Value.isExtractableTo(cppu::UnoType<bool>::get()));
406 else if ( rProperty.Name == "CellRangeRepresentation" )
408 OUString aRange;
409 bHasCellRangeRepresentation =
410 (rProperty.Value.hasValue() && (rProperty.Value >>= aRange) && !aRange.isEmpty());
414 catch( const uno::Exception & )
416 DBG_UNHANDLED_EXCEPTION("chart2");
419 return (bHasCellRangeRepresentation && bHasDataRowSource && bHasFirstCellAsLabel);
422 void DataSourceHelper::setRangeSegmentation(
423 const uno::Reference< frame::XModel >& xChartModel
424 , const css::uno::Sequence< sal_Int32 >& rSequenceMapping
425 , bool bUseColumns , bool bFirstCellAsLabel, bool bUseCategories )
427 uno::Reference< XChartDocument > xChartDocument( xChartModel, uno::UNO_QUERY );
428 if( !xChartDocument.is() )
429 return;
430 uno::Reference< data::XDataProvider > xDataProvider( xChartDocument->getDataProvider() );
431 if( !xDataProvider.is() )
432 return;
433 uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
434 if( !xDiagram.is() )
435 return;
436 uno::Reference< chart2::XChartTypeManager > xChartTypeManager( xChartDocument->getChartTypeManager() );
437 if( !xChartTypeManager.is() )
438 return;
439 uno::Reference< lang::XMultiServiceFactory > xTemplateFactory( xChartTypeManager, uno::UNO_QUERY );
440 if( !xTemplateFactory.is() )
441 return;
443 OUString aRangeString;
444 bool bDummy;
445 uno::Sequence< sal_Int32 > aDummy;
446 readArguments( xDataProvider->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument )),
447 aRangeString, aDummy, bDummy, bDummy, bDummy );
449 uno::Sequence< beans::PropertyValue > aArguments(
450 createArguments( aRangeString, rSequenceMapping, bUseColumns, bFirstCellAsLabel, bUseCategories ) );
452 uno::Reference< chart2::data::XDataSource > xDataSource( xDataProvider->createDataSource(
453 aArguments ) );
454 if( !xDataSource.is() )
455 return;
457 ControllerLockGuardUNO aCtrlLockGuard( xChartModel );
458 xDiagram->setDiagramData( xDataSource, aArguments );
461 Sequence< OUString > DataSourceHelper::getRangesFromLabeledDataSequence(
462 const Reference< data::XLabeledDataSequence > & xLSeq )
464 Sequence< OUString > aResult;
465 if( xLSeq.is())
467 Reference< data::XDataSequence > xLabel( xLSeq->getLabel());
468 Reference< data::XDataSequence > xValues( xLSeq->getValues());
470 if( xLabel.is())
472 if( xValues.is())
474 aResult.realloc( 2 );
475 aResult[0] = xLabel->getSourceRangeRepresentation();
476 aResult[1] = xValues->getSourceRangeRepresentation();
478 else
480 aResult.realloc( 1 );
481 aResult[0] = xLabel->getSourceRangeRepresentation();
484 else if( xValues.is())
486 aResult.realloc( 1 );
487 aResult[0] = xValues->getSourceRangeRepresentation();
490 return aResult;
493 OUString DataSourceHelper::getRangeFromValues(
494 const Reference< data::XLabeledDataSequence > & xLSeq )
496 OUString aResult;
497 if( xLSeq.is() )
499 Reference< data::XDataSequence > xValues( xLSeq->getValues() );
500 if( xValues.is() )
501 aResult = xValues->getSourceRangeRepresentation();
503 return aResult;
506 Sequence< OUString > DataSourceHelper::getRangesFromDataSource( const Reference< data::XDataSource > & xSource )
508 std::vector< OUString > aResult;
509 if( xSource.is())
511 const Sequence< Reference< data::XLabeledDataSequence > > aLSeqSeq( xSource->getDataSequences());
512 for( Reference< data::XLabeledDataSequence > const & labeledData : aLSeqSeq )
514 Reference< data::XDataSequence > xLabel( labeledData->getLabel());
515 Reference< data::XDataSequence > xValues( labeledData->getValues());
517 if( xLabel.is())
518 aResult.push_back( xLabel->getSourceRangeRepresentation());
519 if( xValues.is())
520 aResult.push_back( xValues->getSourceRangeRepresentation());
523 return comphelper::containerToSequence( aResult );
526 } //namespace chart
528 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */