Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/controller/main/ChartModelClone.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 "ChartModelClone.hxx"
21
#include <ChartModel.hxx>
22
#include <ControllerLockGuard.hxx>
23
#include <DataSource.hxx>
24
#include <DataSourceHelper.hxx>
25
26
#include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
27
#include <com/sun/star/chart2/XInternalDataProvider.hpp>
28
#include <com/sun/star/util/XCloneable.hpp>
29
#include <com/sun/star/chart2/XChartDocument.hpp>
30
#include <com/sun/star/view/XSelectionSupplier.hpp>
31
#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
32
33
#include <comphelper/property.hxx>
34
#include <comphelper/diagnose_ex.hxx>
35
36
namespace chart
37
{
38
39
    using ::com::sun::star::uno::Reference;
40
    using ::com::sun::star::uno::UNO_QUERY;
41
    using ::com::sun::star::uno::UNO_QUERY_THROW;
42
    using ::com::sun::star::uno::Exception;
43
    using ::com::sun::star::uno::Sequence;
44
    using ::com::sun::star::frame::XModel;
45
    using ::com::sun::star::util::XCloneable;
46
    using ::com::sun::star::chart2::XChartDocument;
47
    using ::com::sun::star::chart2::XInternalDataProvider;
48
    using ::com::sun::star::chart2::XAnyDescriptionAccess;
49
    using ::com::sun::star::view::XSelectionSupplier;
50
    using ::com::sun::star::chart2::data::XLabeledDataSequence;
51
52
    // = helper
53
    namespace
54
    {
55
        rtl::Reference<::chart::ChartModel> lcl_cloneModel( const rtl::Reference<::chart::ChartModel> & xModel )
56
0
        {
57
0
            try
58
0
            {
59
0
                return new ChartModel(*xModel);
60
0
            }
61
0
            catch( const Exception& )
62
0
            {
63
0
                DBG_UNHANDLED_EXCEPTION("chart2");
64
0
            }
65
0
            return nullptr;
66
0
        }
67
68
    }
69
70
    // = ChartModelClone
71
    ChartModelClone::ChartModelClone( const rtl::Reference<::chart::ChartModel>& i_model, const ModelFacet i_facet )
72
0
    {
73
0
        m_xModelClone = lcl_cloneModel( i_model );
74
75
0
        try
76
0
        {
77
0
            if ( i_facet == E_MODEL_WITH_DATA )
78
0
            {
79
0
                ENSURE_OR_THROW( m_xModelClone && m_xModelClone->hasInternalDataProvider(), "invalid chart model" );
80
81
0
                const Reference< XCloneable > xCloneable( m_xModelClone->getDataProvider(), UNO_QUERY_THROW );
82
0
                m_xDataClone.set( xCloneable->createClone(), UNO_QUERY_THROW );
83
0
            }
84
85
0
            if ( i_facet == E_MODEL_WITH_SELECTION )
86
0
            {
87
0
                const Reference< XSelectionSupplier > xSelSupp( m_xModelClone->getCurrentController(), UNO_QUERY_THROW );
88
0
                m_aSelection = xSelSupp->getSelection();
89
0
            }
90
0
        }
91
0
        catch( const Exception& )
92
0
        {
93
0
            DBG_UNHANDLED_EXCEPTION("chart2");
94
0
        }
95
0
    }
96
97
    ChartModelClone::~ChartModelClone()
98
0
    {
99
0
        if ( !impl_isDisposed() )
100
0
            dispose();
101
0
    }
102
103
    void ChartModelClone::dispose()
104
0
    {
105
0
        if ( impl_isDisposed() )
106
0
            return;
107
108
0
        m_xModelClone.clear();
109
0
        m_xDataClone.clear();
110
0
        m_aSelection.clear();
111
0
    }
112
113
    ModelFacet ChartModelClone::getFacet() const
114
0
    {
115
0
        if ( m_aSelection.hasValue() )
116
0
            return E_MODEL_WITH_SELECTION;
117
0
        if ( m_xDataClone.is() )
118
0
            return E_MODEL_WITH_DATA;
119
0
        return E_MODEL;
120
0
    }
121
122
    void ChartModelClone::applyToModel( const rtl::Reference<::chart::ChartModel>& i_model ) const
123
0
    {
124
0
        applyModelContentToModel( i_model, m_xModelClone, m_xDataClone );
125
126
0
        if ( m_aSelection.hasValue() )
127
0
        {
128
0
            try
129
0
            {
130
0
                Reference< XSelectionSupplier > xCurrentSelectionSuppl( i_model->getCurrentController(), UNO_QUERY_THROW );
131
0
                xCurrentSelectionSuppl->select( m_aSelection );
132
0
            }
133
0
            catch( const Exception& )
134
0
            {
135
0
                DBG_UNHANDLED_EXCEPTION("chart2");
136
0
            }
137
0
        }
138
0
    }
139
140
    namespace
141
    {
142
        void ImplApplyDataToModel( const Reference< XModel >& i_model, const Reference< XInternalDataProvider > & i_data )
143
0
        {
144
0
            Reference< XChartDocument > xDoc( i_model, UNO_QUERY );
145
0
            OSL_ASSERT( xDoc.is() && xDoc->hasInternalDataProvider() );
146
147
            // copy data from stored internal data provider
148
0
            if( xDoc.is() && xDoc->hasInternalDataProvider())
149
0
            {
150
0
                Reference< XAnyDescriptionAccess > xCurrentData( xDoc->getDataProvider(), UNO_QUERY );
151
0
                Reference< XAnyDescriptionAccess > xSavedData( i_data, UNO_QUERY );
152
0
                if ( xCurrentData.is() && xSavedData.is() )
153
0
                {
154
0
                    xCurrentData->setData( xSavedData->getData() );
155
0
                    xCurrentData->setAnyRowDescriptions( xSavedData->getAnyRowDescriptions());
156
0
                    xCurrentData->setAnyColumnDescriptions( xSavedData->getAnyColumnDescriptions());
157
0
                }
158
0
            }
159
0
        }
160
    }
161
162
    void ChartModelClone::applyModelContentToModel( const rtl::Reference<::chart::ChartModel>& i_model,
163
        const rtl::Reference<::chart::ChartModel>& i_modelToCopyFrom,
164
        const Reference< XInternalDataProvider >& i_data )
165
0
    {
166
0
        ENSURE_OR_RETURN_VOID( i_model.is(), "ChartModelElement::applyModelContentToModel: invalid source model!" );
167
0
        ENSURE_OR_RETURN_VOID( i_modelToCopyFrom.is(), "ChartModelElement::applyModelContentToModel: invalid source model!" );
168
0
        try
169
0
        {
170
            // locked controllers of destination
171
0
            ControllerLockGuardUNO aLockedControllers( i_model );
172
173
            // propagate the correct flag for plotting of hidden values to the data provider and all used sequences
174
0
            i_model->setIncludeHiddenCells(i_modelToCopyFrom->isIncludeHiddenCells());
175
176
            // diagram
177
0
            i_model->setFirstDiagram( i_modelToCopyFrom->getFirstDiagram() );
178
179
            // main title
180
0
            i_model->setTitleObject( i_modelToCopyFrom->getTitleObject() );
181
182
            // page background
183
0
            ::comphelper::copyProperties(
184
0
                i_modelToCopyFrom->getPageBackground(),
185
0
                i_model->getPageBackground() );
186
187
            // apply data (not applied in standard Undo)
188
0
            if ( i_data.is() )
189
0
                ImplApplyDataToModel( i_model, i_data );
190
191
            // register all sequences at the internal data provider to get adapted
192
            // indexes when columns are added/removed
193
0
            if ( i_model->hasInternalDataProvider() )
194
0
            {
195
0
                Reference< XInternalDataProvider > xNewDataProvider( i_model->getDataProvider(), UNO_QUERY );
196
0
                rtl::Reference< DataSource > xUsedData = DataSourceHelper::getUsedData( *i_model );
197
0
                if ( xUsedData.is() && xNewDataProvider.is() )
198
0
                {
199
0
                    const Sequence< Reference< XLabeledDataSequence > > aData( xUsedData->getDataSequences() );
200
0
                    for( Reference< XLabeledDataSequence > const & labeledDataSeq : aData )
201
0
                    {
202
0
                        xNewDataProvider->registerDataSequenceForChanges( labeledDataSeq->getValues() );
203
0
                        xNewDataProvider->registerDataSequenceForChanges( labeledDataSeq->getLabel() );
204
0
                    }
205
0
                }
206
0
            }
207
208
            // restore modify status
209
0
            if ( !i_modelToCopyFrom->isModified() )
210
0
            {
211
0
                i_model->setModified( false );
212
0
            }
213
            // \-- locked controllers of destination
214
0
        }
215
0
        catch( const Exception& )
216
0
        {
217
0
            DBG_UNHANDLED_EXCEPTION("chart2");
218
0
        }
219
0
    }
220
221
} // namespace chart
222
223
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */