1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "precompiled_chart2.hxx"
25 
26 #include "ChartModelClone.hxx"
27 #include "ChartModelHelper.hxx"
28 #include "ControllerLockGuard.hxx"
29 #include "DataSourceHelper.hxx"
30 
31 /** === begin UNO includes === **/
32 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
33 #include <com/sun/star/util/XCloneable.hpp>
34 #include <com/sun/star/chart2/XChartDocument.hpp>
35 #include <com/sun/star/view/XSelectionSupplier.hpp>
36 #include <com/sun/star/lang/XComponent.hpp>
37 #include <com/sun/star/chart2/XTitled.hpp>
38 #include <com/sun/star/util/XModifiable.hpp>
39 #include <com/sun/star/chart2/data/XDataSource.hpp>
40 #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
41 /** === end UNO includes === **/
42 
43 #include <comphelper/property.hxx>
44 #include <tools/diagnose_ex.h>
45 
46 //......................................................................................................................
47 namespace chart
48 {
49 //......................................................................................................................
50 
51 	/** === begin UNO using === **/
52 	using ::com::sun::star::uno::Reference;
53 	using ::com::sun::star::uno::XInterface;
54 	using ::com::sun::star::uno::UNO_QUERY;
55 	using ::com::sun::star::uno::UNO_QUERY_THROW;
56 	using ::com::sun::star::uno::UNO_SET_THROW;
57 	using ::com::sun::star::uno::Exception;
58 	using ::com::sun::star::uno::RuntimeException;
59 	using ::com::sun::star::uno::Any;
60 	using ::com::sun::star::uno::makeAny;
61 	using ::com::sun::star::uno::Sequence;
62 	using ::com::sun::star::uno::Type;
63     using ::com::sun::star::frame::XModel;
64     using ::com::sun::star::util::XCloneable;
65     using ::com::sun::star::chart2::XChartDocument;
66     using ::com::sun::star::chart2::XInternalDataProvider;
67     using ::com::sun::star::chart2::XAnyDescriptionAccess;
68     using ::com::sun::star::view::XSelectionSupplier;
69     using ::com::sun::star::lang::XComponent;
70     using ::com::sun::star::chart2::XTitled;
71     using ::com::sun::star::util::XModifiable;
72     using ::com::sun::star::chart2::data::XDataSource;
73     using ::com::sun::star::chart2::data::XLabeledDataSequence;
74     /** === end UNO using === **/
75 
76     // =================================================================================================================
77     // = helper
78     // =================================================================================================================
79     namespace
80     {
lcl_cloneModel(const Reference<XModel> & xModel)81         Reference< XModel > lcl_cloneModel( const Reference< XModel > & xModel )
82         {
83             Reference< XModel > xResult;
84             try
85             {
86                 const Reference< XCloneable > xCloneable( xModel, UNO_QUERY_THROW );
87                 xResult.set( xCloneable->createClone(), UNO_QUERY_THROW );
88             }
89             catch( const Exception& )
90             {
91         	    DBG_UNHANDLED_EXCEPTION();
92             }
93             return xResult;
94         }
95 
96     }
97 
98     // =================================================================================================================
99     // = ChartModelClone
100     // =================================================================================================================
101     // -----------------------------------------------------------------------------------------------------------------
ChartModelClone(const Reference<XModel> & i_model,const ModelFacet i_facet)102     ChartModelClone::ChartModelClone( const Reference< XModel >& i_model, const ModelFacet i_facet )
103     {
104         m_xModelClone.set( lcl_cloneModel( i_model ) );
105 
106         try
107         {
108             if ( i_facet == E_MODEL_WITH_DATA )
109             {
110                 const Reference< XChartDocument > xChartDoc( m_xModelClone, UNO_QUERY_THROW );
111                 ENSURE_OR_THROW( xChartDoc->hasInternalDataProvider(), "invalid chart model" );
112 
113                 const Reference< XCloneable > xCloneable( xChartDoc->getDataProvider(), UNO_QUERY_THROW );
114                 m_xDataClone.set( xCloneable->createClone(), UNO_QUERY_THROW );
115             }
116 
117             if ( i_facet == E_MODEL_WITH_SELECTION )
118             {
119                 const Reference< XSelectionSupplier > xSelSupp( m_xModelClone->getCurrentController(), UNO_QUERY_THROW );
120                 m_aSelection = xSelSupp->getSelection();
121             }
122         }
123         catch( const Exception& )
124         {
125             DBG_UNHANDLED_EXCEPTION();
126         }
127     }
128 
129 
130     // -----------------------------------------------------------------------------------------------------------------
~ChartModelClone()131     ChartModelClone::~ChartModelClone()
132     {
133         if ( !impl_isDisposed() )
134             dispose();
135     }
136 
137     // -----------------------------------------------------------------------------------------------------------------
dispose()138     void ChartModelClone::dispose()
139     {
140         if ( impl_isDisposed() )
141             return;
142 
143         try
144         {
145             Reference< XComponent > xComp( m_xModelClone, UNO_QUERY_THROW );
146             xComp->dispose();
147         }
148         catch( const Exception& )
149         {
150     	    DBG_UNHANDLED_EXCEPTION();
151         }
152         m_xModelClone.clear();
153         m_xDataClone.clear();
154         m_aSelection.clear();
155     }
156 
157     // -----------------------------------------------------------------------------------------------------------------
getFacet() const158     ModelFacet ChartModelClone::getFacet() const
159     {
160         if ( m_aSelection.hasValue() )
161             return E_MODEL_WITH_SELECTION;
162         if ( m_xDataClone.is() )
163             return E_MODEL_WITH_DATA;
164         return E_MODEL;
165     }
166 
167     // -----------------------------------------------------------------------------------------------------------------
applyToModel(const Reference<XModel> & i_model) const168     void ChartModelClone::applyToModel( const Reference< XModel >& i_model ) const
169     {
170         applyModelContentToModel( i_model, m_xModelClone, m_xDataClone );
171 
172         if ( m_aSelection.hasValue() )
173         {
174             try
175             {
176                 Reference< XSelectionSupplier > xCurrentSelectionSuppl( i_model->getCurrentController(), UNO_QUERY_THROW );
177                 xCurrentSelectionSuppl->select( m_aSelection );
178             }
179             catch( const Exception& )
180             {
181         	    DBG_UNHANDLED_EXCEPTION();
182             }
183         }
184     }
185 
186     // -----------------------------------------------------------------------------------------------------------------
187     namespace
188     {
ImplApplyDataToModel(const Reference<XModel> & i_model,const Reference<XInternalDataProvider> & i_data)189         void ImplApplyDataToModel( const Reference< XModel >& i_model, const Reference< XInternalDataProvider > & i_data )
190         {
191             Reference< XChartDocument > xDoc( i_model, UNO_QUERY );
192             OSL_ASSERT( xDoc.is() && xDoc->hasInternalDataProvider() );
193 
194             // copy data from stored internal data provider
195             if( xDoc.is() && xDoc->hasInternalDataProvider())
196             {
197                 Reference< XAnyDescriptionAccess > xCurrentData( xDoc->getDataProvider(), UNO_QUERY );
198                 Reference< XAnyDescriptionAccess > xSavedData( i_data, UNO_QUERY );
199                 if ( xCurrentData.is() && xSavedData.is() )
200                 {
201                     xCurrentData->setData( xSavedData->getData() );
202                     xCurrentData->setAnyRowDescriptions( xSavedData->getAnyRowDescriptions());
203                     xCurrentData->setAnyColumnDescriptions( xSavedData->getAnyColumnDescriptions());
204                 }
205             }
206         }
207     }
208 
209     // -----------------------------------------------------------------------------------------------------------------
applyModelContentToModel(const Reference<XModel> & i_model,const Reference<XModel> & i_modelToCopyFrom,const Reference<XInternalDataProvider> & i_data)210     void ChartModelClone::applyModelContentToModel( const Reference< XModel >& i_model,
211         const Reference< XModel >& i_modelToCopyFrom, const Reference< XInternalDataProvider >& i_data )
212     {
213         ENSURE_OR_RETURN_VOID( i_model.is(), "ChartModelElement::applyModelContentToModel: invalid source model!" );
214         ENSURE_OR_RETURN_VOID( i_modelToCopyFrom.is(), "ChartModelElement::applyModelContentToModel: invalid source model!" );
215         try
216         {
217             // /-- loccked controllers of destination
218             ControllerLockGuard aLockedControllers( i_model );
219             Reference< XChartDocument > xSource( i_modelToCopyFrom, UNO_QUERY_THROW );
220             Reference< XChartDocument > xDestination( i_model, UNO_QUERY_THROW );
221 
222             // propagate the correct flag for plotting of hidden values to the data provider and all used sequences
223             ChartModelHelper::setIncludeHiddenCells( ChartModelHelper::isIncludeHiddenCells( i_modelToCopyFrom ) , i_model );
224 
225             // diagram
226             xDestination->setFirstDiagram( xSource->getFirstDiagram() );
227 
228             // main title
229             Reference< XTitled > xDestinationTitled( xDestination, UNO_QUERY_THROW );
230             Reference< XTitled > xSourceTitled( xSource, UNO_QUERY_THROW );
231             xDestinationTitled->setTitleObject( xSourceTitled->getTitleObject() );
232 
233             // page background
234             ::comphelper::copyProperties(
235                 xSource->getPageBackground(),
236                 xDestination->getPageBackground() );
237 
238             // apply data (not applied in standard Undo)
239             if ( i_data.is() )
240                 ImplApplyDataToModel( i_model, i_data );
241 
242             // register all sequences at the internal data provider to get adapted
243             // indexes when columns are added/removed
244             if ( xDestination->hasInternalDataProvider() )
245             {
246                 Reference< XInternalDataProvider > xNewDataProvider( xDestination->getDataProvider(), UNO_QUERY );
247                 Reference< XDataSource > xUsedData( DataSourceHelper::getUsedData( i_model ) );
248                 if ( xUsedData.is() && xNewDataProvider.is() )
249                 {
250                     Sequence< Reference< XLabeledDataSequence > > aData( xUsedData->getDataSequences() );
251                     for( sal_Int32 i=0; i<aData.getLength(); ++i )
252                     {
253                         xNewDataProvider->registerDataSequenceForChanges( aData[i]->getValues() );
254                         xNewDataProvider->registerDataSequenceForChanges( aData[i]->getLabel() );
255                     }
256                 }
257             }
258 
259             // restore modify status
260             Reference< XModifiable > xSourceMod( xSource, UNO_QUERY );
261             Reference< XModifiable > xDestMod( xDestination, UNO_QUERY );
262             if ( xSourceMod.is() && xDestMod.is() && !xSourceMod->isModified() )
263             {
264                 xDestMod->setModified( sal_False );
265             }
266             // \-- loccked controllers of destination
267         }
268         catch( const Exception& )
269         {
270             DBG_UNHANDLED_EXCEPTION();
271         }
272     }
273 
274 
275 //......................................................................................................................
276 } // namespace chart
277 //......................................................................................................................
278