Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/tools/DataSeriesHelper.cxx
Line
Count
Source
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 <DataSeriesHelper.hxx>
21
#include <DataSeries.hxx>
22
#include <DataSource.hxx>
23
#include <ChartType.hxx>
24
#include <unonames.hxx>
25
#include <Diagram.hxx>
26
#include <BaseCoordinateSystem.hxx>
27
#include <Axis.hxx>
28
29
#include <com/sun/star/beans/XPropertySet.hpp>
30
#include <com/sun/star/chart2/DataPointLabel.hpp>
31
#include <com/sun/star/chart2/StackingDirection.hpp>
32
#include <com/sun/star/chart2/AxisType.hpp>
33
34
#include <comphelper/sequence.hxx>
35
#include <comphelper/diagnose_ex.hxx>
36
37
#include <algorithm>
38
#include <iterator>
39
#include <utility>
40
#include <vector>
41
#include <set>
42
43
using namespace ::com::sun::star;
44
using namespace ::com::sun::star::chart2;
45
46
using ::com::sun::star::uno::Reference;
47
using ::com::sun::star::uno::Sequence;
48
49
namespace
50
{
51
52
class lcl_MatchesRole
53
{
54
public:
55
    explicit lcl_MatchesRole( OUString aRole, bool bMatchPrefix ) :
56
0
            m_aRole(std::move( aRole )),
57
0
            m_bMatchPrefix( bMatchPrefix )
58
0
    {}
59
60
    bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
61
0
    {
62
0
        if(!xSeq.is())
63
0
            return false;
64
0
        Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
65
0
        OUString aRole;
66
67
0
        if( m_bMatchPrefix )
68
0
            return ( xProp.is() &&
69
0
                     (xProp->getPropertyValue( u"Role"_ustr ) >>= aRole ) &&
70
0
                     aRole.match( m_aRole ));
71
72
0
        return ( xProp.is() &&
73
0
                 (xProp->getPropertyValue( u"Role"_ustr ) >>= aRole ) &&
74
0
                 m_aRole == aRole );
75
0
    }
76
77
private:
78
    OUString m_aRole;
79
    bool     m_bMatchPrefix;
80
};
81
82
void lcl_getCooSysAndChartTypeOfSeries(
83
    const rtl::Reference< ::chart::DataSeries > & xSeries,
84
    const rtl::Reference< ::chart::Diagram > & xDiagram,
85
    rtl::Reference< ::chart::BaseCoordinateSystem > & xOutCooSys,
86
    rtl::Reference< ::chart::ChartType > & xOutChartType )
87
0
{
88
0
    if( !xDiagram.is())
89
0
        return;
90
91
0
    for( rtl::Reference< ::chart::BaseCoordinateSystem > const & coords : xDiagram->getBaseCoordinateSystems() )
92
0
    {
93
0
        for( rtl::Reference< ::chart::ChartType > const & chartType : coords->getChartTypes2() )
94
0
        {
95
0
            for( rtl::Reference< ::chart::DataSeries > const & dataSeries : chartType->getDataSeries2() )
96
0
            {
97
0
                if( dataSeries == xSeries )
98
0
                {
99
0
                    xOutCooSys = coords;
100
0
                    xOutChartType = chartType;
101
0
                }
102
0
            }
103
0
        }
104
0
    }
105
0
}
106
107
108
} // anonymous namespace
109
110
namespace chart::DataSeriesHelper
111
{
112
113
OUString getRole( const uno::Reference< chart2::data::XLabeledDataSequence >& xLabeledDataSequence )
114
0
{
115
0
    OUString aRet;
116
0
    if( xLabeledDataSequence.is() )
117
0
    {
118
0
        Reference< beans::XPropertySet > xProp( xLabeledDataSequence->getValues(), uno::UNO_QUERY );
119
0
        if( xProp.is() )
120
0
            xProp->getPropertyValue( u"Role"_ustr ) >>= aRet;
121
0
    }
122
0
    return aRet;
123
0
}
124
125
uno::Reference< chart2::data::XLabeledDataSequence >
126
    getDataSequenceByRole(
127
        const Reference< chart2::data::XDataSource > & xSource,
128
        const OUString& aRole,
129
        bool bMatchPrefix /* = false */ )
130
0
{
131
0
    uno::Reference< chart2::data::XLabeledDataSequence > aNoResult;
132
0
    if( ! xSource.is())
133
0
        return aNoResult;
134
0
    const Sequence< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences());
135
0
    try
136
0
    {
137
0
        for (auto const & i : aLabeledSeq)
138
0
        {
139
0
            if (lcl_MatchesRole(aRole, bMatchPrefix)(i))
140
0
                return i;
141
0
        }
142
0
    }
143
0
    catch (const lang::DisposedException&)
144
0
    {
145
0
        TOOLS_WARN_EXCEPTION( "chart2", "unexpected exception caught" );
146
0
    }
147
148
0
    return aNoResult;
149
0
}
150
151
std::vector< uno::Reference< chart2::data::XLabeledDataSequence > >
152
    getAllDataSequencesByRole( const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aDataSequences,
153
                               const OUString& aRole )
154
0
{
155
0
    std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aResultVec;
156
0
    for (const auto & i : aDataSequences)
157
0
    {
158
0
        if (lcl_MatchesRole(aRole, /*bMatchPrefix*/true)(i))
159
0
            aResultVec.push_back(i);
160
0
    }
161
0
    return aResultVec;
162
0
}
163
164
std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence > >
165
    getAllDataSequencesByRole( const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aDataSequences,
166
                               const OUString& aRole )
167
0
{
168
0
    std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > aResultVec;
169
0
    std::copy_if( aDataSequences.begin(), aDataSequences.end(),
170
0
                           std::back_inserter( aResultVec ),
171
0
                           lcl_MatchesRole(aRole, /*bMatchPrefix*/true) );
172
0
    return aResultVec;
173
0
}
174
175
std::vector<uno::Reference<chart2::data::XLabeledDataSequence> >
176
getAllDataSequences( const std::vector<rtl::Reference<DataSeries> >& aSeries )
177
0
{
178
0
    std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSeqVec;
179
180
0
    for( rtl::Reference<DataSeries> const & dataSeries : aSeries )
181
0
    {
182
0
        const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aSeq( dataSeries->getDataSequences2());
183
0
        aSeqVec.insert( aSeqVec.end(), aSeq.begin(), aSeq.end() );
184
0
    }
185
186
0
    return aSeqVec;
187
0
}
188
189
rtl::Reference< DataSource >
190
    getDataSource( const std::vector< rtl::Reference< DataSeries > > & aSeries )
191
0
{
192
0
    return new DataSource(getAllDataSequences(aSeries));
193
0
}
194
195
void setStackModeAtSeries(
196
    const std::vector< rtl::Reference< DataSeries > > & aSeries,
197
    const rtl::Reference< BaseCoordinateSystem > & xCorrespondingCoordinateSystem,
198
    StackMode eStackMode )
199
0
{
200
0
    const uno::Any aPropValue(
201
0
        ( (eStackMode == StackMode::YStacked) ||
202
0
          (eStackMode == StackMode::YStackedPercent) )
203
0
        ? chart2::StackingDirection_Y_STACKING
204
0
        : (eStackMode == StackMode::ZStacked )
205
0
        ? chart2::StackingDirection_Z_STACKING
206
0
        : chart2::StackingDirection_NO_STACKING );
207
208
0
    std::set< sal_Int32 > aAxisIndexSet;
209
0
    for( rtl::Reference< DataSeries > const & dataSeries : aSeries )
210
0
    {
211
0
        try
212
0
        {
213
0
            if( dataSeries.is() )
214
0
            {
215
0
                dataSeries->setPropertyValue( u"StackingDirection"_ustr, aPropValue );
216
217
0
                sal_Int32 nAxisIndex = 0;
218
0
                dataSeries->getPropertyValue( u"AttachedAxisIndex"_ustr ) >>= nAxisIndex;
219
0
                aAxisIndexSet.insert(nAxisIndex);
220
0
            }
221
0
        }
222
0
        catch( const uno::Exception & )
223
0
        {
224
0
            DBG_UNHANDLED_EXCEPTION("chart2");
225
0
        }
226
0
    }
227
228
0
    if( !(xCorrespondingCoordinateSystem.is() &&
229
0
        1 < xCorrespondingCoordinateSystem->getDimension()) )
230
0
        return;
231
232
0
    if( aAxisIndexSet.empty() )
233
0
    {
234
0
        aAxisIndexSet.insert(0);
235
0
    }
236
237
0
    for (auto const& axisIndex : aAxisIndexSet)
238
0
    {
239
0
        rtl::Reference< Axis > xAxis =
240
0
            xCorrespondingCoordinateSystem->getAxisByDimension2(1, axisIndex);
241
0
        if( xAxis.is())
242
0
        {
243
0
            bool bPercent = (eStackMode == StackMode::YStackedPercent);
244
0
            chart2::ScaleData aScaleData = xAxis->getScaleData();
245
246
0
            if( bPercent != (aScaleData.AxisType==chart2::AxisType::PERCENT) )
247
0
            {
248
0
                if( bPercent )
249
0
                    aScaleData.AxisType = chart2::AxisType::PERCENT;
250
0
                else
251
0
                    aScaleData.AxisType = chart2::AxisType::REALNUMBER;
252
0
                xAxis->setScaleData( aScaleData );
253
0
            }
254
0
        }
255
0
    }
256
0
}
257
258
sal_Int32 getNumberFormatKeyFromAxis(
259
    const rtl::Reference< DataSeries > & xSeries,
260
    const rtl::Reference< BaseCoordinateSystem > & xCorrespondingCoordinateSystem,
261
    sal_Int32 nDimensionIndex,
262
    sal_Int32 nAxisIndex /* = -1 */ )
263
0
{
264
0
    sal_Int32 nResult =  0;
265
0
    if( nAxisIndex == -1 )
266
0
        nAxisIndex = xSeries->getAttachedAxisIndex();
267
0
    try
268
0
    {
269
0
        rtl::Reference< Axis > xAxisProp =
270
0
            xCorrespondingCoordinateSystem->getAxisByDimension2( nDimensionIndex, nAxisIndex );
271
0
        if( xAxisProp.is())
272
0
            xAxisProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nResult;
273
0
    }
274
0
    catch( const uno::Exception & )
275
0
    {
276
0
        DBG_UNHANDLED_EXCEPTION("chart2");
277
0
    }
278
279
0
    return nResult;
280
0
}
281
282
rtl::Reference< ::chart::BaseCoordinateSystem > getCoordinateSystemOfSeries(
283
    const rtl::Reference< DataSeries > & xSeries,
284
    const rtl::Reference< Diagram > & xDiagram )
285
0
{
286
0
    rtl::Reference< ::chart::BaseCoordinateSystem > xResult;
287
0
    rtl::Reference< ::chart::ChartType > xDummy;
288
0
    lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xResult, xDummy );
289
290
0
    return xResult;
291
0
}
292
293
rtl::Reference< ::chart::ChartType > getChartTypeOfSeries(
294
    const rtl::Reference< DataSeries > & xSeries,
295
    const rtl::Reference< Diagram > & xDiagram )
296
0
{
297
0
    rtl::Reference< ::chart::ChartType > xResult;
298
0
    rtl::Reference< ::chart::BaseCoordinateSystem > xDummy;
299
0
    lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xDummy, xResult );
300
301
0
    return xResult;
302
0
}
303
304
sal_Int32 translateIndexFromHiddenToFullSequence( sal_Int32 nIndex, const Reference< chart2::data::XDataSequence >& xDataSequence, bool bTranslate )
305
0
{
306
0
    if( !bTranslate )
307
0
        return nIndex;
308
309
0
    try
310
0
    {
311
0
        uno::Reference<beans::XPropertySet> xProp( xDataSequence, uno::UNO_QUERY );
312
0
        if( xProp.is())
313
0
        {
314
0
            Sequence<sal_Int32> aHiddenIndicesSeq;
315
0
            xProp->getPropertyValue( u"HiddenValues"_ustr ) >>= aHiddenIndicesSeq;
316
0
            if( aHiddenIndicesSeq.hasElements() )
317
0
            {
318
0
                auto aHiddenIndices( comphelper::sequenceToContainer<std::vector< sal_Int32 >>( aHiddenIndicesSeq ) );
319
0
                std::sort( aHiddenIndices.begin(), aHiddenIndices.end() );
320
321
0
                sal_Int32 nHiddenCount = static_cast<sal_Int32>(aHiddenIndices.size());
322
0
                for( sal_Int32 nN = 0; nN < nHiddenCount; ++nN)
323
0
                {
324
0
                    if( aHiddenIndices[nN] <= nIndex )
325
0
                        nIndex += 1;
326
0
                    else
327
0
                        break;
328
0
                }
329
0
            }
330
0
        }
331
0
    }
332
0
    catch (const beans::UnknownPropertyException&)
333
0
    {
334
0
    }
335
0
    return nIndex;
336
0
}
337
338
void insertDataLabelToPoint( const Reference< beans::XPropertySet >& xPointProp )
339
0
{
340
0
    try
341
0
    {
342
0
        if( xPointProp.is() )
343
0
        {
344
0
            DataPointLabel aLabel;
345
0
            xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel;
346
0
            aLabel.ShowNumber = true;
347
0
            xPointProp->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabel));
348
0
        }
349
0
    }
350
0
    catch(const uno::Exception &)
351
0
    {
352
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
353
0
    }
354
0
}
355
356
void deleteDataLabelsFromPoint( const Reference< beans::XPropertySet >& xPointProp )
357
0
{
358
0
    try
359
0
    {
360
0
        if( xPointProp.is() )
361
0
        {
362
0
            DataPointLabel aLabel;
363
0
            xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel;
364
0
            aLabel.ShowNumber = false;
365
0
            aLabel.ShowNumberInPercent = false;
366
0
            aLabel.ShowCategoryName = false;
367
0
            aLabel.ShowCustomLabel = false;
368
0
            aLabel.ShowSeriesName = false;
369
0
            xPointProp->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabel));
370
0
            xPointProp->setPropertyValue(CHART_UNONAME_CUSTOM_LABEL_FIELDS, uno::Any());
371
0
        }
372
0
    }
373
0
    catch(const uno::Exception &)
374
0
    {
375
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
376
0
    }
377
0
}
378
379
} //  namespace chart
380
381
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */