/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include "DialogModel.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; namespace { constexpr OUStringLiteral lcl_aLabelRole( u"label" ); OUString lcl_ConvertRole( const OUString & rRoleString ) { OUString aResult( rRoleString ); typedef std::map< OUString, OUString > tTranslationMap; static const tTranslationMap aTranslationMap = { { "categories", ::chart::SchResId( STR_DATA_ROLE_CATEGORIES ) }, { "error-bars-x", ::chart::SchResId( STR_DATA_ROLE_X_ERROR ) }, { "error-bars-x-positive", ::chart::SchResId( STR_DATA_ROLE_X_ERROR_POSITIVE ) }, { "error-bars-x-negative", ::chart::SchResId( STR_DATA_ROLE_X_ERROR_NEGATIVE ) }, { "error-bars-y", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR ) }, { "error-bars-y-positive", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_POSITIVE ) }, { "error-bars-y-negative", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_NEGATIVE ) }, { "label", ::chart::SchResId( STR_DATA_ROLE_LABEL ) }, { "values-first", ::chart::SchResId( STR_DATA_ROLE_FIRST ) }, { "values-last", ::chart::SchResId( STR_DATA_ROLE_LAST ) }, { "values-max", ::chart::SchResId( STR_DATA_ROLE_MAX ) }, { "values-min", ::chart::SchResId( STR_DATA_ROLE_MIN ) }, { "values-x", ::chart::SchResId( STR_DATA_ROLE_X ) }, { "values-y", ::chart::SchResId( STR_DATA_ROLE_Y ) }, { "values-size", ::chart::SchResId( STR_DATA_ROLE_SIZE ) }, { "FillColor", ::chart::SchResId( STR_PROPERTY_ROLE_FILLCOLOR ) }, { "BorderColor", ::chart::SchResId( STR_PROPERTY_ROLE_BORDERCOLOR ) }, }; tTranslationMap::const_iterator aIt( aTranslationMap.find( rRoleString )); if( aIt != aTranslationMap.end()) { aResult = (*aIt).second; } return aResult; } typedef std::map< OUString, sal_Int32 > lcl_tRoleIndexMap; lcl_tRoleIndexMap lcl_createRoleIndexMap() { lcl_tRoleIndexMap aMap; sal_Int32 nIndex = 0; aMap[ "label" ] = ++nIndex; aMap[ "categories" ] = ++nIndex; aMap[ "values-x" ] = ++nIndex; aMap[ "values-y" ] = ++nIndex; aMap[ "error-bars-x" ] = ++nIndex; aMap[ "error-bars-x-positive" ] = ++nIndex; aMap[ "error-bars-x-negative" ] = ++nIndex; aMap[ "error-bars-y" ] = ++nIndex; aMap[ "error-bars-y-positive" ] = ++nIndex; aMap[ "error-bars-y-negative" ] = ++nIndex; aMap[ "values-first" ] = ++nIndex; aMap[ "values-min" ] = ++nIndex; aMap[ "values-max" ] = ++nIndex; aMap[ "values-last" ] = ++nIndex; aMap[ "values-size" ] = ++nIndex; return aMap; } struct lcl_RolesWithRangeAppend { typedef Reference< data::XLabeledDataSequence > value_type; typedef ::chart::DialogModel::tRolesWithRanges tContainerType; explicit lcl_RolesWithRangeAppend( tContainerType * rCnt, OUString aLabelRole ) : m_rDestCnt( rCnt ), m_aRoleForLabelSeq(std::move( aLabelRole )) {} lcl_RolesWithRangeAppend & operator= ( const value_type & xVal ) { try { if( xVal.is()) { // data sequence Reference< data::XDataSequence > xSeq( xVal->getValues()); if( xSeq.is()) { OUString aRole; Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW ); if( xProp->getPropertyValue( "Role" ) >>= aRole ) { m_rDestCnt->emplace(aRole, xSeq->getSourceRangeRepresentation()); // label if( aRole == m_aRoleForLabelSeq ) { Reference< data::XDataSequence > xLabelSeq( xVal->getLabel()); if( xLabelSeq.is()) { m_rDestCnt->emplace( lcl_aLabelRole, xLabelSeq->getSourceRangeRepresentation()); } } } } } } catch( const uno::Exception & ) { DBG_UNHANDLED_EXCEPTION("chart2"); } return *this; } // Implement output operator requirements as required by std::copy (and // implement prefix increment in terms of postfix increment to avoid unused // member function warnings for the latter in the common case where // std::copy would not actually need it): lcl_RolesWithRangeAppend & operator* () { return *this; } lcl_RolesWithRangeAppend & operator++ () { return operator++(0); } lcl_RolesWithRangeAppend & operator++ (int) { return *this; } private: tContainerType * m_rDestCnt; OUString m_aRoleForLabelSeq; }; } namespace std { template<> struct iterator_traits { typedef std::output_iterator_tag iterator_category; typedef Reference< data::XLabeledDataSequence > value_type; typedef value_type& reference; }; } namespace { void lcl_SetSequenceRole( const Reference< data::XDataSequence > & xSeq, const OUString & rRole ) { Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY ); if( xProp.is()) xProp->setPropertyValue( "Role" , uno::Any( rRole )); } Sequence< OUString > lcl_CopyExcludingValuesFirst( Sequence< OUString > const & i_aInput ) { Sequence< OUString > aOutput( i_aInput.getLength()); auto pOutput = aOutput.getArray(); int nSourceIndex, nDestIndex; for( nSourceIndex = nDestIndex = 0; nSourceIndex < i_aInput.getLength(); nSourceIndex++ ) { if( i_aInput[nSourceIndex] == "values-first" ) { aOutput.realloc( aOutput.getLength() - 1 ); pOutput = aOutput.getArray(); } else { pOutput[nDestIndex] = i_aInput[nSourceIndex]; nDestIndex++; } } return aOutput; } rtl::Reference< ::chart::DataSeries > lcl_CreateNewSeries( const rtl::Reference< ::chart::ChartType > & xChartType, sal_Int32 nNewSeriesIndex, sal_Int32 nTotalNumberOfSeriesInCTGroup, const rtl::Reference< ::chart::Diagram > & xDiagram, const rtl::Reference< ::chart::ChartTypeTemplate > & xTemplate, bool bCreateDataCachedSequences ) { // create plain series rtl::Reference< ::chart::DataSeries > xResult = new ::chart::DataSeries(); if( xTemplate.is()) { // @deprecated: correct default color should be found by view // without setting it as hard attribute Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); if( xColorScheme.is()) xResult->setPropertyValue( "Color" , uno::Any( xColorScheme->getColorByIndex( nNewSeriesIndex ))); std::size_t nGroupIndex=0; if( xChartType.is()) { std::vector< rtl::Reference< ::chart::ChartType > > aCTs( ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram )); for( ; nGroupIndex < aCTs.size(); ++nGroupIndex) if( aCTs[nGroupIndex] == xChartType ) break; if( nGroupIndex == aCTs.size()) nGroupIndex = 0; } xTemplate->applyStyle( xResult, nGroupIndex, nNewSeriesIndex, nTotalNumberOfSeriesInCTGroup ); } if( bCreateDataCachedSequences ) { // set chart type specific roles if( xChartType.is() ) { std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSequences; const OUString aRoleOfSeqForSeriesLabel = xChartType->getRoleOfSequenceForSeriesLabel(); const OUString aLabel(::chart::SchResId(STR_DATA_UNNAMED_SERIES)); Sequence< OUString > aPossibleRoles( xChartType->getSupportedMandatoryRoles()); Sequence< OUString > aPossibleOptRoles( xChartType->getSupportedOptionalRoles()); //special handling for candlestick type if( xTemplate.is()) { rtl::Reference< ::chart::DataInterpreter > xInterpreter( xTemplate->getDataInterpreter()); if( xInterpreter.is()) { sal_Int32 nStockVariant; if( xInterpreter->getChartTypeSpecificData("stock variant") >>= nStockVariant ) { if( nStockVariant == 0 || nStockVariant == 2) { //delete "values-first" role aPossibleRoles = lcl_CopyExcludingValuesFirst(aPossibleRoles); aPossibleOptRoles = lcl_CopyExcludingValuesFirst(aPossibleOptRoles); } } } } const Sequence< OUString > aRoles( aPossibleRoles ); const Sequence< OUString > aOptRoles( aPossibleOptRoles ); for(OUString const & role : aRoles) { if( role == lcl_aLabelRole ) continue; Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence() ); lcl_SetSequenceRole( xSeq, role ); // assert that aRoleOfSeqForSeriesLabel is part of the mandatory roles if( role == aRoleOfSeqForSeriesLabel ) { Reference< data::XDataSequence > xLabel( ::chart::DataSourceHelper::createCachedDataSequence( aLabel )); lcl_SetSequenceRole( xLabel, lcl_aLabelRole ); aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq, xLabel )); } else aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq )); } for(OUString const & role : aOptRoles) { if( role == lcl_aLabelRole ) continue; Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence()); lcl_SetSequenceRole( xSeq, role ); aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq )); } xResult->setData( aNewSequences ); } } return xResult; } struct lcl_addSeriesNumber { sal_Int32 operator() ( sal_Int32 nCurrentNumber, const Reference< XDataSeriesContainer > & xCnt ) const { if( xCnt.is()) return nCurrentNumber + (xCnt->getDataSeries().getLength()); return nCurrentNumber; } }; } // anonymous namespace namespace chart { DialogModelTimeBasedInfo::DialogModelTimeBasedInfo(): bTimeBased(false), nStart(0), nEnd(0) { } DialogModel::DialogModel( rtl::Reference<::chart::ChartModel> xChartDocument ) : m_xChartDocument(std::move( xChartDocument )), m_aTimerTriggeredControllerLock( m_xChartDocument ) { } DialogModel::~DialogModel() { if(maTimeBasedInfo.bTimeBased) { getModel().setTimeBasedRange(maTimeBasedInfo.nStart, maTimeBasedInfo.nEnd); } } void DialogModel::setTemplate( const rtl::Reference< ChartTypeTemplate > & xTemplate ) { m_xTemplate = xTemplate; } std::shared_ptr< RangeSelectionHelper > const & DialogModel::getRangeSelectionHelper() const { if( ! m_spRangeSelectionHelper) m_spRangeSelectionHelper = std::make_shared( m_xChartDocument ); return m_spRangeSelectionHelper; } const rtl::Reference<::chart::ChartModel> & DialogModel::getChartModel() const { return m_xChartDocument; } Reference< data::XDataProvider > DialogModel::getDataProvider() const { Reference< data::XDataProvider > xResult; if( m_xChartDocument.is()) xResult.set( m_xChartDocument->getDataProvider()); return xResult; } std::vector< rtl::Reference< ChartType > > DialogModel::getAllDataSeriesContainers() const { std::vector< rtl::Reference< ChartType > > aResult; try { if( !m_xChartDocument ) return {}; rtl::Reference< Diagram > xDiagram = m_xChartDocument->getFirstChartDiagram(); if( xDiagram.is()) { const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysSeq( xDiagram->getBaseCoordinateSystems()); for( rtl::Reference< BaseCoordinateSystem > const & coords : aCooSysSeq ) { for (const auto & rxChartType : coords->getChartTypes2()) aResult.push_back(rxChartType); } } } catch( const uno::Exception & ) { DBG_UNHANDLED_EXCEPTION("chart2"); } return aResult; } std::vector< DialogModel::tSeriesWithChartTypeByName > DialogModel::getAllDataSeriesWithLabel() const { std::vector< tSeriesWithChartTypeByName > aResult; std::vector< rtl::Reference< ChartType > > aContainers( getAllDataSeriesContainers()); for (const auto & rxChartType : aContainers ) { try { const std::vector< rtl::Reference< DataSeries > > & aSeq = rxChartType->getDataSeries2(); OUString aRole = rxChartType->getRoleOfSequenceForSeriesLabel(); for( rtl::Reference< DataSeries > const & dataSeries : aSeq ) { aResult.push_back( ::chart::DialogModel::tSeriesWithChartTypeByName( ::chart::DataSeriesHelper::getDataSeriesLabel( dataSeries, aRole ), std::make_pair( dataSeries, rxChartType ))); } } catch( const uno::Exception & ) { DBG_UNHANDLED_EXCEPTION("chart2"); } } return aResult; } namespace { void addMissingRoles(DialogModel::tRolesWithRanges& rResult, const uno::Sequence& rRoles) { for(OUString const & role : rRoles) { if(rResult.find(role) == rResult.end()) rResult.emplace(role, OUString()); } } /** * Insert a new data series to chart type at position after specified series * position. * * @param xChartType chart type that contains data series. * @param xSeries insertion position. The new series will be inserted after * this one. * @param xNewSeries new data series to insert. */ void addNewSeriesToContainer( const rtl::Reference& xChartType, const rtl::Reference& xSeries, const rtl::Reference& xNewSeries ) { auto aSeries = xChartType->getDataSeries2(); auto aIt = std::find( aSeries.begin(), aSeries.end(), xSeries); if( aIt == aSeries.end()) // if we have no series we insert at the first position. aIt = aSeries.begin(); else // vector::insert inserts before, so we have to advance ++aIt; aSeries.insert(aIt, xNewSeries); xChartType->setDataSeries(aSeries); } } DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges( const Reference< XDataSeries > & xSeries, const OUString & aRoleOfSequenceForLabel, const rtl::Reference< ::chart::ChartType > & xChartType ) { DialogModel::tRolesWithRanges aResult; try { Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW ); const Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSource->getDataSequences()); std::copy( aSeq.begin(), aSeq.end(), lcl_RolesWithRangeAppend( &aResult, aRoleOfSequenceForLabel )); if( xChartType.is()) { // add missing mandatory roles Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles()); addMissingRoles(aResult, aRoles); // add missing optional roles aRoles = xChartType->getSupportedOptionalRoles(); addMissingRoles(aResult, aRoles); // add missing property roles aRoles = xChartType->getSupportedPropertyRoles(); addMissingRoles(aResult, aRoles); } } catch( const uno::Exception & ) { DBG_UNHANDLED_EXCEPTION("chart2"); } return aResult; } void DialogModel::moveSeries( const Reference< XDataSeries > & xSeries, MoveDirection eDirection ) { m_aTimerTriggeredControllerLock.startTimer(); ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram()); DiagramHelper::moveSeries( xDiagram, xSeries, eDirection==MoveDirection::Down ); } rtl::Reference< ::chart::DataSeries > DialogModel::insertSeriesAfter( const Reference< XDataSeries > & xUnoSeries, const rtl::Reference< ::chart::ChartType > & xChartType, bool bCreateDataCachedSequences /* = false */ ) { m_aTimerTriggeredControllerLock.startTimer(); ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); rtl::Reference< ::chart::DataSeries > xNewSeries; rtl::Reference xSeries = dynamic_cast(xUnoSeries.get()); assert(xSeries || !xUnoSeries); try { rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram() ); ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); sal_Int32 nSeriesInChartType = 0; const sal_Int32 nTotalSeries = countSeries(); if( xChartType.is()) { nSeriesInChartType = xChartType->getDataSeries().getLength(); } // create new series xNewSeries = lcl_CreateNewSeries( xChartType, nTotalSeries, // new series' index nSeriesInChartType, xDiagram, m_xTemplate, bCreateDataCachedSequences ); // add new series to container if( xNewSeries.is()) addNewSeriesToContainer(xChartType, xSeries, xNewSeries); ThreeDHelper::setScheme( xDiagram, e3DScheme ); } catch( const uno::Exception & ) { DBG_UNHANDLED_EXCEPTION("chart2"); } return xNewSeries; } void DialogModel::deleteSeries( const Reference< XDataSeries > & xSeries, const rtl::Reference< ChartType > & xChartType ) { m_aTimerTriggeredControllerLock.startTimer(); ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); DataSeriesHelper::deleteSeries( xSeries, xChartType ); } uno::Reference< chart2::data::XLabeledDataSequence > DialogModel::getCategories() const { uno::Reference< chart2::data::XLabeledDataSequence > xResult; try { if( m_xChartDocument.is()) { rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram()); xResult = DiagramHelper::getCategoriesFromDiagram( xDiagram ); } } catch( const uno::Exception & ) { DBG_UNHANDLED_EXCEPTION("chart2"); } return xResult; } void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories ) { if( !m_xChartDocument.is()) return; rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram()); if( !xDiagram.is()) return; // categories bool bSupportsCategories = true; rtl::Reference< ChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); if( xFirstChartType.is() ) { sal_Int32 nAxisType = ChartTypeHelper::getAxisType( xFirstChartType, 0 ); // x-axis bSupportsCategories = (nAxisType == AxisType::CATEGORY); } DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram, true, bSupportsCategories ); } OUString DialogModel::getCategoriesRange() const { uno::Reference< chart2::data::XLabeledDataSequence > xLSeq( getCategories()); OUString aRange; if( xLSeq.is()) { Reference< data::XDataSequence > xSeq( xLSeq->getValues()); if( xSeq.is()) aRange = xSeq->getSourceRangeRepresentation(); } return aRange; } bool DialogModel::isCategoryDiagram() const { bool bRet = false; if( m_xChartDocument.is()) bRet = DiagramHelper::isCategoryDiagram( m_xChartDocument->getFirstChartDiagram() ); return bRet; } void DialogModel::detectArguments( OUString & rOutRangeString, bool & rOutUseColumns, bool & rOutFirstCellAsLabel, bool & rOutHasCategories ) const { try { uno::Sequence< sal_Int32 > aSequenceMapping;//todo YYYX // Note: unused data is currently not supported in being passed to detectRangeSegmentation if( m_xChartDocument.is()) { (void)DataSourceHelper::detectRangeSegmentation( m_xChartDocument, rOutRangeString, aSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories ); } } catch( const uno::Exception & ) { DBG_UNHANDLED_EXCEPTION("chart2"); } } bool DialogModel::allArgumentsForRectRangeDetected() const { return DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument ); } void DialogModel::startControllerLockTimer() { m_aTimerTriggeredControllerLock.startTimer(); } void DialogModel::setData( const Sequence< beans::PropertyValue > & rArguments ) { m_aTimerTriggeredControllerLock.startTimer(); ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); Reference< data::XDataProvider > xDataProvider( getDataProvider()); if( ! xDataProvider.is() || ! m_xTemplate.is() ) { OSL_FAIL( "Model objects missing" ); return; } try { Reference< chart2::data::XDataSource > xDataSource( xDataProvider->createDataSource( rArguments ) ); rtl::Reference< ::chart::DataInterpreter > xInterpreter( m_xTemplate->getDataInterpreter()); if( xInterpreter.is()) { rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram() ); ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); std::vector< rtl::Reference< DataSeries > > aSeriesToReUse = DiagramHelper::getDataSeriesFromDiagram( xDiagram ); applyInterpretedData( xInterpreter->interpretDataSource( xDataSource, rArguments, aSeriesToReUse ), aSeriesToReUse); ThreeDHelper::setScheme( xDiagram, e3DScheme ); } } catch( const uno::Exception & ) { DBG_UNHANDLED_EXCEPTION("chart2"); } } void DialogModel::setTimeBasedRange( bool bTimeBased, sal_Int32 nStart, sal_Int32 nEnd) const { maTimeBasedInfo.nStart = nStart; maTimeBasedInfo.nEnd = nEnd; maTimeBasedInfo.bTimeBased = bTimeBased; } OUString DialogModel::ConvertRoleFromInternalToUI( const OUString & rRoleString ) { return lcl_ConvertRole( rRoleString ); } OUString DialogModel::GetRoleDataLabel() { return ::chart::SchResId(STR_OBJECT_DATALABELS); } sal_Int32 DialogModel::GetRoleIndexForSorting( const OUString & rInternalRoleString ) { static lcl_tRoleIndexMap aRoleIndexMap = lcl_createRoleIndexMap(); lcl_tRoleIndexMap::const_iterator aIt( aRoleIndexMap.find( rInternalRoleString )); if( aIt != aRoleIndexMap.end()) return aIt->second; return 0; } // private methods void DialogModel::applyInterpretedData( const InterpretedData & rNewData, const std::vector< rtl::Reference< DataSeries > > & rSeriesToReUse ) { if( ! m_xChartDocument.is()) return; m_aTimerTriggeredControllerLock.startTimer(); rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram()); if( !xDiagram.is()) return; // styles if( m_xTemplate.is() ) { sal_Int32 nGroup = 0; sal_Int32 nSeriesCounter = 0; sal_Int32 nNewSeriesIndex = static_cast< sal_Int32 >( rSeriesToReUse.size()); const sal_Int32 nOuterSize=rNewData.Series.size(); for(; nGroup < nOuterSize; ++nGroup) { const std::vector< rtl::Reference< DataSeries > > & aSeries( rNewData.Series[ nGroup ] ); const sal_Int32 nSeriesInGroup = aSeries.size(); for( sal_Int32 nSeries=0; nSeries xColorScheme( xDiagram->getDefaultColorScheme()); if( xColorScheme.is()) aSeries[nSeries]->setPropertyValue( "Color" , uno::Any( xColorScheme->getColorByIndex( nSeriesCounter ))); } m_xTemplate->applyStyle( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup ); } } } } // data series std::vector< rtl::Reference< ChartType > > aSeriesCnt = getAllDataSeriesContainers(); OSL_ASSERT( aSeriesCnt.size() == rNewData.Series.size()); auto aSrcIt = rNewData.Series.begin(); auto aDestIt = aSeriesCnt.begin(); for(; aSrcIt != rNewData.Series.end() && aDestIt != aSeriesCnt.end(); ++aSrcIt, ++aDestIt ) { try { OSL_ASSERT( (*aDestIt).is()); (*aDestIt)->setDataSeries( *aSrcIt ); } catch( const uno::Exception & ) { DBG_UNHANDLED_EXCEPTION("chart2"); } } DialogModel::setCategories(rNewData.Categories); } sal_Int32 DialogModel::countSeries() const { std::vector< rtl::Reference< ChartType > > aCnt( getAllDataSeriesContainers()); return std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber()); } ChartModel& DialogModel::getModel() const { return *m_xChartDocument; } } // namespace chart /* vim:set shiftwidth=4 softtabstop=4 expandtab: */