Line data Source code
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 "SchXMLTools.hxx"
21 :
22 : #include <rtl/ustrbuf.hxx>
23 : #include <comphelper/InlineContainer.hxx>
24 : #include <xmloff/xmluconv.hxx>
25 : #include <xmloff/xmlement.hxx>
26 : #include <xmloff/xmlimppr.hxx>
27 : #include <xmloff/prstylei.hxx>
28 : #include <xmloff/xmlprmap.hxx>
29 : #include <xmloff/xmlexp.hxx>
30 : #include <xmloff/xmlnmspe.hxx>
31 : #include <xmloff/xmlmetai.hxx>
32 : #include <xmloff/maptype.hxx>
33 :
34 : #include <com/sun/star/beans/PropertyAttribute.hpp>
35 : #include <com/sun/star/uno/XComponentContext.hpp>
36 : #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
37 : #include <com/sun/star/chart2/data/XDataProvider.hpp>
38 : #include <com/sun/star/chart2/data/XDataReceiver.hpp>
39 : #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
40 : #include <com/sun/star/chart2/XChartDocument.hpp>
41 : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
42 : #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
43 : #include <com/sun/star/container/XChild.hpp>
44 : #include <com/sun/star/document/XDocumentProperties.hpp>
45 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
46 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
47 : #include <com/sun/star/lang/XServiceName.hpp>
48 :
49 : #include <comphelper/processfactory.hxx>
50 : #include <algorithm>
51 :
52 : using namespace com::sun::star;
53 : using namespace ::xmloff::token;
54 :
55 : using ::com::sun::star::uno::Reference;
56 : using ::com::sun::star::uno::Sequence;
57 :
58 : namespace
59 : {
60 :
61 1285 : OUString lcl_getGeneratorFromModel( const uno::Reference< frame::XModel >& xChartModel )
62 : {
63 1285 : OUString aGenerator;
64 2570 : uno::Reference< document::XDocumentPropertiesSupplier> xChartDocumentPropertiesSupplier( xChartModel, uno::UNO_QUERY );
65 1285 : if( xChartDocumentPropertiesSupplier.is() )
66 : {
67 : uno::Reference< document::XDocumentProperties > xChartDocumentProperties(
68 1222 : xChartDocumentPropertiesSupplier->getDocumentProperties());
69 1222 : if( xChartDocumentProperties.is() )
70 1222 : aGenerator = xChartDocumentProperties->getGenerator();
71 : }
72 2570 : return aGenerator;
73 : }
74 :
75 123 : OUString lcl_getGeneratorFromModelOrItsParent( const uno::Reference< frame::XModel >& xChartModel )
76 : {
77 123 : OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
78 123 : if( aGenerator.isEmpty() ) //try to get the missing info from the parent document
79 : {
80 41 : uno::Reference< container::XChild > xChild( xChartModel, uno::UNO_QUERY );
81 41 : if( xChild.is() )
82 41 : aGenerator = lcl_getGeneratorFromModel( uno::Reference< frame::XModel >( xChild->getParent(), uno::UNO_QUERY) );
83 : }
84 123 : return aGenerator;
85 : }
86 :
87 0 : sal_Int32 lcl_getBuildIDFromGenerator( const OUString& rGenerator )
88 : {
89 : //returns -1 if nothing found
90 0 : sal_Int32 nBuildId = -1;
91 0 : const OUString sBuildCompare( "$Build-" );
92 0 : sal_Int32 nBegin = rGenerator.indexOf( sBuildCompare );
93 0 : if( nBegin >= 0 )
94 : {
95 0 : OUString sBuildId( rGenerator.copy( nBegin + sBuildCompare.getLength() ) );
96 0 : nBuildId = sBuildId.toInt32();
97 : }
98 0 : return nBuildId;
99 : }
100 :
101 340 : OUString lcl_ConvertRange( const OUString & rRange, const Reference< chart2::data::XDataProvider >& xDataProvider )
102 : {
103 340 : OUString aResult = rRange;
104 680 : Reference< chart2::data::XRangeXMLConversion > xRangeConversion( xDataProvider, uno::UNO_QUERY );
105 340 : if( xRangeConversion.is())
106 340 : aResult = xRangeConversion->convertRangeFromXML( rRange );
107 680 : return aResult;
108 : }
109 :
110 0 : Reference< chart2::data::XDataSequence > lcl_createNewSequenceFromCachedXMLRange( const Reference< chart2::data::XDataSequence >& xSeq, const Reference< chart2::data::XDataProvider >& xDataProvider )
111 : {
112 0 : Reference< chart2::data::XDataSequence > xRet;
113 0 : OUString aRange;
114 0 : if( xSeq.is() && SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq, aRange, /* bClearProp = */ true ) )
115 : {
116 0 : xRet.set( xDataProvider->createDataSequenceByRangeRepresentation(
117 0 : lcl_ConvertRange( aRange, xDataProvider )) );
118 : SchXMLTools::copyProperties( Reference< beans::XPropertySet >( xSeq, uno::UNO_QUERY ),
119 0 : Reference< beans::XPropertySet >( xRet, uno::UNO_QUERY ));
120 : }
121 0 : return xRet;
122 : }
123 :
124 : } // anonymous namespace
125 :
126 : namespace SchXMLTools
127 : {
128 :
129 : static const SvXMLEnumMapEntry aXMLChartClassMap[] =
130 : {
131 : { XML_LINE, XML_CHART_CLASS_LINE },
132 : { XML_AREA, XML_CHART_CLASS_AREA },
133 : { XML_CIRCLE, XML_CHART_CLASS_CIRCLE },
134 : { XML_RING, XML_CHART_CLASS_RING },
135 : { XML_SCATTER, XML_CHART_CLASS_SCATTER },
136 : { XML_RADAR, XML_CHART_CLASS_RADAR },
137 : { XML_FILLED_RADAR, XML_CHART_CLASS_FILLED_RADAR },
138 : { XML_BAR, XML_CHART_CLASS_BAR },
139 : { XML_STOCK, XML_CHART_CLASS_STOCK },
140 : { XML_BUBBLE, XML_CHART_CLASS_BUBBLE },
141 : { XML_GL3DBAR, XML_CHART_CLASS_GL3DBAR },
142 : { XML_SURFACE, XML_CHART_CLASS_BAR }, //@todo change this if a surface chart is available
143 : { XML_ADD_IN, XML_CHART_CLASS_ADDIN },
144 : { XML_TOKEN_INVALID, XML_CHART_CLASS_UNKNOWN }
145 : };
146 :
147 86 : SchXMLChartTypeEnum GetChartTypeEnum( const OUString& rClassName )
148 : {
149 86 : sal_uInt16 nEnumVal = XML_CHART_CLASS_UNKNOWN;
150 86 : if( !SvXMLUnitConverter::convertEnum(
151 86 : nEnumVal, rClassName, aXMLChartClassMap ) )
152 0 : nEnumVal = XML_CHART_CLASS_UNKNOWN;
153 86 : return SchXMLChartTypeEnum(nEnumVal);
154 : }
155 :
156 : typedef ::comphelper::MakeMap< OUString, OUString > tMakeStringStringMap;
157 : //static
158 0 : const tMakeStringStringMap& lcl_getChartTypeNameMap()
159 : {
160 : //shape property -- chart model object property
161 : static const tMakeStringStringMap g_aChartTypeNameMap =
162 : tMakeStringStringMap
163 : ( OUString( "com.sun.star.chart.LineDiagram" )
164 : , OUString( "com.sun.star.chart2.LineChartType" ) )
165 :
166 : ( OUString( "com.sun.star.chart.AreaDiagram" )
167 0 : , OUString( "com.sun.star.chart2.AreaChartType" ) )
168 :
169 : ( OUString( "com.sun.star.chart.BarDiagram" )
170 0 : , OUString( "com.sun.star.chart2.ColumnChartType" ) )
171 :
172 : ( OUString( "com.sun.star.chart.PieDiagram" )
173 0 : , OUString( "com.sun.star.chart2.PieChartType" ) )
174 :
175 : ( OUString( "com.sun.star.chart.DonutDiagram" )
176 0 : , OUString( "com.sun.star.chart2.DonutChartType" ) )
177 :
178 : ( OUString( "com.sun.star.chart.XYDiagram" )
179 0 : , OUString( "com.sun.star.chart2.ScatterChartType" ) )
180 :
181 : ( OUString( "com.sun.star.chart.NetDiagram" )
182 0 : , OUString( "com.sun.star.chart2.NetChartType" ) )
183 :
184 : ( OUString( "com.sun.star.chart.FilledNetDiagram" )
185 0 : , OUString( "com.sun.star.chart2.FilledNetChartType" ) )
186 :
187 : ( OUString( "com.sun.star.chart.StockDiagram" )
188 0 : , OUString( "com.sun.star.chart2.CandleStickChartType" ) )
189 :
190 : ( OUString( "com.sun.star.chart.BubbleDiagram" )
191 0 : , OUString( "com.sun.star.chart2.BubbleChartType" ) )
192 :
193 : ( OUString( "com.sun.star.chart.GL3DBarDiagram" )
194 0 : , OUString( "com.sun.star.chart2.GL3DBarChartType" ) )
195 :
196 : ;
197 0 : return g_aChartTypeNameMap;
198 : }
199 :
200 0 : OUString GetNewChartTypeName( const OUString & rOldChartTypeName )
201 : {
202 0 : OUString aNew(rOldChartTypeName);
203 :
204 0 : const tMakeStringStringMap& rMap = lcl_getChartTypeNameMap();
205 0 : tMakeStringStringMap::const_iterator aIt( rMap.find( rOldChartTypeName ));
206 0 : if( aIt != rMap.end())
207 : {
208 0 : aNew = aIt->second;
209 : }
210 0 : return aNew;
211 : }
212 :
213 321 : OUString GetChartTypeByClassName(
214 : const OUString & rClassName, bool bUseOldNames )
215 : {
216 321 : OUStringBuffer aResultBuffer;
217 321 : bool bInternalType = false;
218 :
219 321 : if( bUseOldNames )
220 86 : aResultBuffer.append( "com.sun.star.chart.");
221 : else
222 235 : aResultBuffer.append( "com.sun.star.chart2.");
223 :
224 321 : bInternalType = true;
225 :
226 321 : if( IsXMLToken( rClassName, XML_LINE ))
227 48 : aResultBuffer.append("Line");
228 273 : else if( IsXMLToken( rClassName, XML_AREA ))
229 7 : aResultBuffer.append("Area");
230 266 : else if( IsXMLToken( rClassName, XML_BAR ))
231 : {
232 157 : if( bUseOldNames )
233 37 : aResultBuffer.append("Bar");
234 : else
235 : {
236 120 : aResultBuffer.append("Column");
237 : // @todo: might be Bar
238 : }
239 : }
240 109 : else if( IsXMLToken( rClassName, XML_CIRCLE ))
241 14 : aResultBuffer.append("Pie");
242 95 : else if( IsXMLToken( rClassName, XML_RING ))
243 4 : aResultBuffer.append("Donut");
244 91 : else if( IsXMLToken( rClassName, XML_SCATTER ))
245 : {
246 85 : if( bUseOldNames )
247 26 : aResultBuffer.append("XY");
248 : else
249 59 : aResultBuffer.append("Scatter");
250 : }
251 :
252 6 : else if( IsXMLToken( rClassName, XML_BUBBLE ))
253 0 : aResultBuffer.append("Bubble");
254 6 : else if( IsXMLToken( rClassName, XML_RADAR ))
255 0 : aResultBuffer.append("Net");
256 6 : else if( IsXMLToken( rClassName, XML_FILLED_RADAR ))
257 4 : aResultBuffer.append("FilledNet");
258 2 : else if( IsXMLToken( rClassName, XML_STOCK ))
259 : {
260 2 : if( bUseOldNames )
261 1 : aResultBuffer.append("Stock");
262 : else
263 1 : aResultBuffer.append("CandleStick");
264 : }
265 0 : else if( IsXMLToken( rClassName, XML_SURFACE ))
266 : {
267 : //@todo change this if a surface chart is available
268 0 : if( bUseOldNames )
269 0 : aResultBuffer.append("Bar");
270 : else
271 0 : aResultBuffer.append("Column");
272 : }
273 0 : else if (IsXMLToken(rClassName, XML_GL3DBAR))
274 0 : aResultBuffer.append("GL3DBar");
275 : else
276 0 : bInternalType = false;
277 :
278 321 : if( ! bInternalType )
279 0 : return OUString();
280 :
281 321 : if( bUseOldNames )
282 86 : aResultBuffer.append("Diagram");
283 : else
284 235 : aResultBuffer.append("ChartType");
285 :
286 321 : return aResultBuffer.makeStringAndClear();
287 :
288 : }
289 :
290 868 : XMLTokenEnum getTokenByChartType(
291 : const OUString & rChartTypeService, bool bUseOldNames )
292 : {
293 868 : XMLTokenEnum eResult = XML_TOKEN_INVALID;
294 1736 : OUString aPrefix, aPostfix;
295 :
296 868 : if( bUseOldNames )
297 : {
298 269 : aPrefix = "com.sun.star.chart.";
299 269 : aPostfix = "Diagram";
300 : }
301 : else
302 : {
303 599 : aPrefix = "com.sun.star.chart2.";
304 599 : aPostfix = "ChartType";
305 : }
306 :
307 868 : if( rChartTypeService.match( aPrefix ))
308 : {
309 868 : sal_Int32 nSkip = aPrefix.getLength();
310 : SAL_WARN_IF( rChartTypeService.getLength() < nSkip, "xmloff.chart", "ChartTypeService.getLength() < nSkip" );
311 868 : sal_Int32 nTypeLength = rChartTypeService.getLength() - nSkip - aPostfix.getLength();
312 : // if postfix matches and leaves a non-empty type
313 868 : if( nTypeLength > 0 && rChartTypeService.match( aPostfix, nSkip + nTypeLength ))
314 : {
315 868 : OUString aServiceName( rChartTypeService.copy( nSkip, nTypeLength ));
316 :
317 868 : if ( aServiceName == "Line" )
318 74 : eResult = XML_LINE;
319 794 : else if ( aServiceName == "Area" )
320 30 : eResult = XML_AREA;
321 1949 : else if( aServiceName == "Bar" ||
322 1125 : (!bUseOldNames && aServiceName == "Column"))
323 580 : eResult = XML_BAR;
324 184 : else if ( aServiceName == "Pie" )
325 90 : eResult = XML_CIRCLE;
326 94 : else if ( aServiceName == "Donut" )
327 12 : eResult = XML_RING;
328 200 : else if( (bUseOldNames && aServiceName == "XY") ||
329 108 : (!bUseOldNames && aServiceName == "Scatter"))
330 58 : eResult = XML_SCATTER;
331 24 : else if ( aServiceName == "Bubble" )
332 0 : eResult = XML_BUBBLE;
333 24 : else if ( aServiceName == "Net" )
334 0 : eResult = XML_RADAR;
335 24 : else if ( aServiceName == "FilledNet" )
336 18 : eResult = XML_FILLED_RADAR;
337 12 : else if( (bUseOldNames && aServiceName == "Stock") ||
338 0 : (!bUseOldNames && aServiceName == "CandleStick"))
339 6 : eResult = XML_STOCK;
340 0 : else if (aServiceName == "GL3DBar")
341 0 : eResult = XML_GL3DBAR;
342 : }
343 : }
344 :
345 868 : if( eResult == XML_TOKEN_INVALID && !rChartTypeService.isEmpty() )
346 0 : eResult = XML_ADD_IN;
347 :
348 1736 : return eResult;
349 : }
350 :
351 251 : Reference< chart2::data::XLabeledDataSequence2 > GetNewLabeledDataSequence()
352 : {
353 251 : Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
354 251 : Reference< chart2::data::XLabeledDataSequence2 > xResult = chart2::data::LabeledDataSequence::create(xContext);
355 251 : return xResult;
356 : }
357 :
358 340 : Reference< chart2::data::XDataSequence > CreateDataSequence(
359 : const OUString & rRange,
360 : const Reference< chart2::XChartDocument >& xChartDoc )
361 : {
362 340 : Reference< chart2::data::XDataSequence > xRet;
363 :
364 340 : if( !xChartDoc.is() )
365 : {
366 : SAL_WARN("xmloff.chart", "need a chart document" );
367 0 : return xRet;
368 : }
369 :
370 680 : Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
371 340 : if( !xDataProvider.is() )
372 : {
373 : SAL_WARN("xmloff.chart", "need a data provider" );
374 0 : return xRet;
375 : }
376 :
377 340 : bool bUseInternal = false;
378 680 : uno::Reference<beans::XPropertySet> xPropSet(xDataProvider, uno::UNO_QUERY);
379 340 : if (xPropSet.is())
380 : {
381 : try
382 : {
383 97 : bool bVal = false;
384 97 : uno::Any any = xPropSet->getPropertyValue("UseInternalDataProvider");
385 97 : if (any >>= bVal)
386 97 : bUseInternal = static_cast<bool>(bVal);
387 : }
388 0 : catch (const beans::UnknownPropertyException&)
389 : {
390 : // Do nothing
391 : }
392 : }
393 :
394 340 : if (!bUseInternal)
395 : {
396 : try
397 : {
398 340 : xRet.set( xDataProvider->createDataSequenceByRangeRepresentation( lcl_ConvertRange( rRange, xDataProvider )));
399 340 : SchXMLTools::setXMLRangePropertyAtDataSequence( xRet, rRange );
400 : }
401 0 : catch( const lang::IllegalArgumentException & )
402 : {
403 : SAL_WARN("xmloff.chart", "could not create data sequence" );
404 : }
405 : }
406 :
407 340 : if( !xRet.is() && !xChartDoc->hasInternalDataProvider() && !rRange.isEmpty() )
408 : {
409 : //#i103911# switch to internal data in case the parent cannot provide the requested data
410 0 : xChartDoc->createInternalDataProvider( sal_True /* bCloneExistingData */ );
411 0 : xDataProvider = xChartDoc->getDataProvider();
412 : try
413 : {
414 0 : xRet.set( xDataProvider->createDataSequenceByRangeRepresentation( lcl_ConvertRange( rRange, xDataProvider )));
415 0 : SchXMLTools::setXMLRangePropertyAtDataSequence( xRet, rRange );
416 : }
417 0 : catch( const lang::IllegalArgumentException & )
418 : {
419 : SAL_WARN("xmloff.chart", "could not create data sequence" );
420 : }
421 : }
422 340 : return xRet;
423 : }
424 :
425 2 : Reference< chart2::data::XDataSequence > CreateDataSequenceWithoutConvert(
426 : const OUString & rRange,
427 : const Reference< chart2::XChartDocument >& xChartDoc )
428 : {
429 2 : Reference< chart2::data::XDataSequence > xRet;
430 :
431 2 : if( !xChartDoc.is() )
432 : {
433 : SAL_WARN("xmloff.chart", "need a chart document" );
434 0 : return xRet;
435 : }
436 :
437 4 : Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
438 2 : if( !xDataProvider.is() )
439 : {
440 : SAL_WARN("xmloff.chart", "need a data provider" );
441 0 : return xRet;
442 : }
443 :
444 : try
445 : {
446 2 : xRet.set( xDataProvider->createDataSequenceByRangeRepresentation( rRange ) );
447 2 : SchXMLTools::setXMLRangePropertyAtDataSequence( xRet, rRange );
448 : }
449 0 : catch( const lang::IllegalArgumentException & )
450 : {
451 : SAL_WARN("xmloff.chart", "could not create data sequence" );
452 : }
453 :
454 2 : return xRet;
455 : }
456 :
457 53 : void CreateCategories(
458 : const uno::Reference< chart2::data::XDataProvider > & xDataProvider,
459 : const uno::Reference< chart2::XChartDocument > & xNewDoc,
460 : const OUString & rRangeAddress,
461 : sal_Int32 nCooSysIndex,
462 : sal_Int32 nDimensionIndex,
463 : tSchXMLLSequencesPerIndex * pLSequencesPerIndex )
464 : {
465 : try
466 : {
467 53 : if( xNewDoc.is() && !rRangeAddress.isEmpty())
468 : {
469 53 : if( xDataProvider.is())
470 : {
471 53 : uno::Reference< chart2::XDiagram > xDia( xNewDoc->getFirstDiagram());
472 53 : if( !xDia.is())
473 53 : return;
474 :
475 106 : uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDia, uno::UNO_QUERY_THROW );
476 : uno::Sequence< uno::Reference< chart2::XCoordinateSystem > >
477 106 : aCooSysSeq( xCooSysCnt->getCoordinateSystems());
478 53 : if( nCooSysIndex < aCooSysSeq.getLength())
479 : {
480 53 : uno::Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIndex] );
481 : SAL_WARN_IF( !xCooSys.is(), "xmloff.chart", "xCooSys is NULL");
482 53 : if( nDimensionIndex < xCooSys->getDimension() )
483 : {
484 53 : const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
485 109 : for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
486 : {
487 56 : uno::Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nI ));
488 56 : if( xAxis.is() )
489 : {
490 56 : chart2::ScaleData aData( xAxis->getScaleData());
491 : uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
492 112 : GetNewLabeledDataSequence(), uno::UNO_QUERY_THROW);
493 : try
494 : {
495 56 : OUString aConvertedRange( rRangeAddress );
496 56 : bool bRangeConverted = false;
497 56 : if( ! (xNewDoc->hasInternalDataProvider() && aConvertedRange == "categories"))
498 : {
499 54 : Reference< chart2::data::XRangeXMLConversion > xXMLConv( xDataProvider, uno::UNO_QUERY );
500 54 : if( xXMLConv.is())
501 : {
502 54 : aConvertedRange = xXMLConv->convertRangeFromXML( rRangeAddress );
503 54 : bRangeConverted = true;
504 54 : }
505 : }
506 : Reference< chart2::data::XDataSequence > xSeq(
507 112 : xDataProvider->createDataSequenceByRangeRepresentation( aConvertedRange ));
508 56 : xLabeledSeq->setValues( xSeq );
509 56 : if( bRangeConverted )
510 110 : setXMLRangePropertyAtDataSequence( xSeq, rRangeAddress );
511 : }
512 0 : catch( const lang::IllegalArgumentException & ex )
513 : {
514 : SAL_WARN("xmloff.chart", "IllegalArgumentException caught, Message: " << ex.Message );
515 : }
516 56 : aData.Categories.set( xLabeledSeq );
517 56 : if( pLSequencesPerIndex )
518 : {
519 : // register for setting local data if external data provider is not present
520 : pLSequencesPerIndex->insert(
521 : tSchXMLLSequencesPerIndex::value_type(
522 54 : tSchXMLIndexWithPart( SCH_XML_CATEGORIES_INDEX, SCH_XML_PART_VALUES ), xLabeledSeq ));
523 : }
524 112 : xAxis->setScaleData( aData );
525 : }
526 56 : }
527 53 : }
528 53 : }
529 : }
530 : }
531 : }
532 0 : catch( uno::Exception & )
533 : {
534 : SAL_WARN("xmloff.chart", "Exception caught while creating Categories" );
535 : }
536 : }
537 :
538 883 : uno::Any getPropertyFromContext( const OUString& rPropertyName, const XMLPropStyleContext* pPropStyleContext, const SvXMLStylesContext* pStylesCtxt )
539 : {
540 883 : uno::Any aRet;
541 883 : if( !pPropStyleContext || !pStylesCtxt )
542 0 : return aRet;
543 883 : const ::std::vector< XMLPropertyState >& rProperties = pPropStyleContext->GetProperties();
544 883 : const rtl::Reference< XMLPropertySetMapper >& rMapper = pStylesCtxt->GetImportPropertyMapper( pPropStyleContext->GetFamily()/*XML_STYLE_FAMILY_SCH_CHART_ID*/ )->getPropertySetMapper();
545 883 : ::std::vector< XMLPropertyState >::const_iterator aEnd( rProperties.end() );
546 883 : ::std::vector< XMLPropertyState >::const_iterator aPropIter( rProperties.begin() );
547 7062 : for( aPropIter = rProperties.begin(); aPropIter != aEnd; ++aPropIter )
548 : {
549 6548 : sal_Int32 nIdx = aPropIter->mnIndex;
550 6548 : if( nIdx == -1 )
551 0 : continue;
552 6548 : OUString aPropName = rMapper->GetEntryAPIName( nIdx );
553 6548 : if(rPropertyName.equals(aPropName))
554 369 : return aPropIter->maValue;
555 6179 : }
556 514 : return aRet;
557 : }
558 :
559 5895 : void exportText( SvXMLExport& rExport, const OUString& rText, bool bConvertTabsLFs )
560 : {
561 : SvXMLElementExport aPara( rExport, XML_NAMESPACE_TEXT,
562 5895 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_P ),
563 5895 : true, false );
564 :
565 5895 : if( bConvertTabsLFs )
566 : {
567 522 : sal_Int32 nStartPos = 0;
568 522 : sal_Int32 nEndPos = rText.getLength();
569 : sal_Unicode cChar;
570 :
571 1566 : for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
572 : {
573 1044 : cChar = rText[ nPos ];
574 1044 : switch( cChar )
575 : {
576 : case 0x0009: // tabulator
577 : {
578 0 : if( nPos > nStartPos )
579 0 : rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nPos - nStartPos)) );
580 0 : nStartPos = nPos + 1;
581 :
582 : SvXMLElementExport aElem( rExport, XML_NAMESPACE_TEXT,
583 0 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_TAB_STOP ),
584 0 : false, false );
585 : }
586 0 : break;
587 :
588 : case 0x000A: // linefeed
589 : {
590 0 : if( nPos > nStartPos )
591 0 : rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nPos - nStartPos)) );
592 0 : nStartPos = nPos + 1;
593 :
594 : SvXMLElementExport aElem( rExport, XML_NAMESPACE_TEXT,
595 0 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_LINE_BREAK ),
596 0 : false, false );
597 : }
598 0 : break;
599 : }
600 : }
601 522 : if( nEndPos > nStartPos )
602 : {
603 522 : if( nStartPos == 0 )
604 522 : rExport.GetDocHandler()->characters( rText );
605 : else
606 0 : rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nEndPos - nStartPos)) );
607 : }
608 : }
609 : else // do not convert tabs and linefeeds (eg for numbers coming from unit converter)
610 : {
611 5373 : rExport.GetDocHandler()->characters( rText );
612 5895 : }
613 5895 : }
614 :
615 38 : void exportRangeToSomewhere( SvXMLExport& rExport, const OUString& rValue )
616 : {
617 : //with issue #i366# and CWS chart20 ranges for error bars were introduced
618 : //to keep them during copy paste from calc to impress for example it
619 : //was necessary to introduce a mapping between the used ranges within calc and the data written to the local table
620 : //this is why we write this ranges here
621 :
622 : //#i113950# first the range was exported to attribute text:id, but that attribute does not allow arbitrary strings anymore within ODF 1.2
623 : //as an alternative the range info is now saved into the description at an empty group element (not very nice, but ODF conform)
624 :
625 38 : const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
626 38 : if( nCurrentODFVersion == SvtSaveOptions::ODFVER_010 || nCurrentODFVersion == SvtSaveOptions::ODFVER_011 )
627 38 : return;//svg:desc is not allowed at draw:g in ODF1.0; but as the ranges for error bars are anyhow not allowed within ODF1.0 nor ODF1.1 we do not need the information
628 :
629 : SvXMLElementExport aEmptyShapeGroup( rExport, XML_NAMESPACE_DRAW,
630 38 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_G ),
631 38 : true, false );
632 : SvXMLElementExport aDescription( rExport, XML_NAMESPACE_SVG,
633 38 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DESC ),
634 76 : true, false );
635 76 : rExport.GetDocHandler()->characters( rValue );
636 : }
637 :
638 402 : void setXMLRangePropertyAtDataSequence(
639 : const Reference< chart2::data::XDataSequence > & xDataSequence,
640 : const OUString & rXMLRange )
641 : {
642 402 : if( !xDataSequence.is())
643 402 : return;
644 : try
645 : {
646 402 : const OUString aXMLRangePropName( "CachedXMLRange" );
647 804 : Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
648 804 : Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
649 402 : if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ))
650 696 : xProp->setPropertyValue( aXMLRangePropName, uno::makeAny( rXMLRange ));
651 : }
652 0 : catch( const uno::Exception & ex )
653 : {
654 : SAL_WARN("xmloff.chart", "Exception caught, Message: " << ex.Message );
655 : }
656 : }
657 :
658 282 : bool getXMLRangePropertyFromDataSequence(
659 : const Reference< chart2::data::XDataSequence > & xDataSequence,
660 : OUString & rOutXMLRange,
661 : bool bClearProp /* = false */)
662 : {
663 282 : bool bResult = false;
664 282 : if( xDataSequence.is())
665 : {
666 : try
667 : {
668 282 : const OUString aXMLRangePropName( "CachedXMLRange" );
669 564 : Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
670 564 : Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
671 : bResult =
672 1128 : ( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ) &&
673 1974 : ( xProp->getPropertyValue( aXMLRangePropName ) >>= rOutXMLRange ) &&
674 564 : !rOutXMLRange.isEmpty());
675 : // clear the property after usage
676 282 : if( bClearProp && bResult )
677 564 : xProp->setPropertyValue( aXMLRangePropName, uno::Any( OUString()));
678 : }
679 0 : catch( const uno::Exception & ex )
680 : {
681 : SAL_WARN("xmloff.chart", "Exception caught, Message: " << ex.Message );
682 : }
683 : }
684 282 : return bResult;
685 : }
686 :
687 3 : void copyProperties(
688 : const Reference< beans::XPropertySet > & xSource,
689 : const Reference< beans::XPropertySet > & xDestination )
690 : {
691 3 : if( ! (xSource.is() && xDestination.is()) )
692 6 : return;
693 :
694 : try
695 : {
696 0 : Reference< beans::XPropertySetInfo > xSrcInfo( xSource->getPropertySetInfo(), uno::UNO_QUERY_THROW );
697 0 : Reference< beans::XPropertySetInfo > xDestInfo( xDestination->getPropertySetInfo(), uno::UNO_QUERY_THROW );
698 0 : Sequence< beans::Property > aProperties( xSrcInfo->getProperties());
699 0 : const sal_Int32 nLength = aProperties.getLength();
700 0 : for( sal_Int32 i = 0; i < nLength; ++i )
701 : {
702 0 : OUString aName( aProperties[i].Name);
703 0 : if( xDestInfo->hasPropertyByName( aName ))
704 : {
705 0 : beans::Property aProp( xDestInfo->getPropertyByName( aName ));
706 0 : if( (aProp.Attributes & beans::PropertyAttribute::READONLY) == 0 )
707 0 : xDestination->setPropertyValue(
708 0 : aName, xSource->getPropertyValue( aName ));
709 : }
710 0 : }
711 : }
712 0 : catch( const uno::Exception & )
713 : {
714 : SAL_WARN("xmloff.chart", "Copying property sets failed!" );
715 : }
716 : }
717 :
718 0 : bool switchBackToDataProviderFromParent( const Reference< chart2::XChartDocument >& xChartDoc, const tSchXMLLSequencesPerIndex & rLSequencesPerIndex )
719 : {
720 : //return whether the switch is successful
721 0 : if( !xChartDoc.is() || !xChartDoc->hasInternalDataProvider() )
722 0 : return false;
723 0 : Reference< chart2::data::XDataProvider > xDataProviderFromParent( SchXMLTools::getDataProviderFromParent( xChartDoc ) );
724 0 : if( !xDataProviderFromParent.is() )
725 0 : return false;
726 0 : uno::Reference< chart2::data::XDataReceiver > xDataReceiver( xChartDoc, uno::UNO_QUERY );
727 0 : if( !xDataReceiver.is() )
728 0 : return false;
729 :
730 0 : xDataReceiver->attachDataProvider( xDataProviderFromParent );
731 :
732 0 : for( tSchXMLLSequencesPerIndex::const_iterator aLSeqIt( rLSequencesPerIndex.begin() );
733 0 : aLSeqIt != rLSequencesPerIndex.end(); ++aLSeqIt )
734 : {
735 0 : Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( aLSeqIt->second );
736 0 : if( !xLabeledSeq.is() )
737 0 : continue;
738 0 : Reference< chart2::data::XDataSequence > xNewSeq;
739 0 : xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getValues(), xDataProviderFromParent );
740 0 : if( xNewSeq.is() )
741 0 : xLabeledSeq->setValues( xNewSeq );
742 0 : xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getLabel(), xDataProviderFromParent );
743 0 : if( xNewSeq.is() )
744 0 : xLabeledSeq->setLabel( xNewSeq );
745 0 : }
746 0 : return true;
747 : }
748 :
749 86 : void setBuildIDAtImportInfo( uno::Reference< frame::XModel > xModel, Reference< beans::XPropertySet > xImportInfo )
750 : {
751 86 : OUString aGenerator( lcl_getGeneratorFromModelOrItsParent(xModel) );
752 86 : if( !aGenerator.isEmpty() )
753 82 : SvXMLMetaDocumentContext::setBuildId( aGenerator, xImportInfo );
754 86 : }
755 :
756 3 : bool isDocumentGeneratedWithOpenOfficeOlderThan3_3( const uno::Reference< frame::XModel >& xChartModel )
757 : {
758 3 : bool bResult = isDocumentGeneratedWithOpenOfficeOlderThan3_0( xChartModel );
759 3 : if( !bResult )
760 : {
761 3 : OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
762 3 : if( aGenerator.indexOf( "OpenOffice.org_project/3" ) != -1 )
763 : {
764 0 : if( aGenerator.indexOf( "OpenOffice.org_project/300m" ) != -1 )
765 : {
766 0 : sal_Int32 nBuilId = lcl_getBuildIDFromGenerator( lcl_getGeneratorFromModel(xChartModel) );
767 0 : if( nBuilId>0 && nBuilId<9491 ) //9491 is build id of dev300m76
768 0 : bResult= true;
769 : }
770 0 : else if( aGenerator.indexOf( "OpenOffice.org_project/310m" ) != -1 )
771 0 : bResult= true;
772 0 : else if( aGenerator.indexOf( "OpenOffice.org_project/320m" ) != -1 )
773 0 : bResult= true;
774 3 : }
775 : }
776 3 : return bResult;
777 : }
778 :
779 282 : bool isDocumentGeneratedWithOpenOfficeOlderThan3_0( const uno::Reference< frame::XModel >& xChartModel )
780 : {
781 282 : bool bResult = isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel );
782 282 : if( !bResult )
783 : {
784 282 : OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
785 282 : if( aGenerator.indexOf( "OpenOffice.org_project/680m" ) != -1 )
786 0 : bResult= true;
787 : }
788 282 : return bResult;
789 : }
790 :
791 193 : bool isDocumentGeneratedWithOpenOfficeOlderThan2_4( const uno::Reference< frame::XModel >& xChartModel )
792 : {
793 193 : if( isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel ) )
794 0 : return true;
795 :
796 193 : if( isDocumentGeneratedWithOpenOfficeOlderThan3_0( xChartModel ) )
797 : {
798 0 : sal_Int32 nBuilId = lcl_getBuildIDFromGenerator( lcl_getGeneratorFromModel(xChartModel) );
799 0 : if( nBuilId>0 && nBuilId<=9238 ) //9238 is build id of OpenOffice.org 2.3.1
800 0 : return true;
801 : }
802 193 : return false;
803 : }
804 :
805 799 : bool isDocumentGeneratedWithOpenOfficeOlderThan2_3( const uno::Reference< frame::XModel >& xChartModel )
806 : {
807 799 : bool bResult = false;
808 799 : OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
809 : //if there is a meta stream at the chart object it was not written with an older OpenOffice version < 2.3
810 799 : if( aGenerator.isEmpty() )
811 : {
812 : //if there is no meta stream at the chart object we need to check whether the parent document is OpenOffice at all
813 37 : uno::Reference< container::XChild > xChild( xChartModel, uno::UNO_QUERY );
814 37 : if( xChild.is() )
815 : {
816 37 : aGenerator = lcl_getGeneratorFromModel( uno::Reference< frame::XModel >( xChild->getParent(), uno::UNO_QUERY) );
817 37 : if( aGenerator.indexOf( "OpenOffice.org_project" ) != -1 )
818 : {
819 : //the chart application has not created files without a meta stream since OOo 2.3 (OOo 2.3 has written a metastream already)
820 : //only the report builder extension has created some files with OOo 3.1 that do not have a meta stream
821 0 : if( aGenerator.indexOf( "OpenOffice.org_project/31" ) != -1 )
822 0 : bResult = false;//#i100102# probably generated with OOo 3.1 by the report designer
823 : else
824 0 : bResult= true; //in this case the OLE chart was created by an older version, as OLE objects are sometimes stream copied the version can differ from the parents version, so the parents version is not a reliable indicator
825 : }
826 37 : else if( isDocumentGeneratedWithOpenOfficeOlderThan2_0(xChartModel) )
827 0 : bResult= true;
828 37 : }
829 : }
830 799 : return bResult;
831 : }
832 :
833 37 : bool isDocumentGeneratedWithOpenOfficeOlderThan2_0( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xChartModel)
834 : {
835 37 : bool bResult = false;
836 37 : OUString aGenerator( lcl_getGeneratorFromModelOrItsParent(xChartModel) );
837 74 : if( aGenerator.startsWith( "OpenOffice.org 1" )
838 37 : || aGenerator.startsWith( "StarOffice 6" )
839 37 : || aGenerator.startsWith( "StarOffice 7" )
840 37 : || aGenerator.startsWith( "StarSuite 6" )
841 74 : || aGenerator.startsWith( "StarSuite 7" )
842 : )
843 0 : bResult= true;
844 37 : return bResult;
845 : }
846 :
847 0 : Reference< chart2::data::XDataProvider > getDataProviderFromParent( const Reference< chart2::XChartDocument >& xChartDoc )
848 : {
849 0 : Reference< chart2::data::XDataProvider > xRet;
850 0 : uno::Reference< container::XChild > xChild( xChartDoc, uno::UNO_QUERY );
851 0 : if( xChild.is() )
852 : {
853 0 : Reference< lang::XMultiServiceFactory > xFact( xChild->getParent(), uno::UNO_QUERY );
854 0 : if( xFact.is() )
855 : {
856 0 : const OUString aDataProviderServiceName( "com.sun.star.chart2.data.DataProvider");
857 0 : const uno::Sequence< OUString > aServiceNames( xFact->getAvailableServiceNames());
858 0 : const OUString * pBegin = aServiceNames.getConstArray();
859 0 : const OUString * pEnd = pBegin + aServiceNames.getLength();
860 0 : if( ::std::find( pBegin, pEnd, aDataProviderServiceName ) != pEnd )
861 : {
862 0 : xRet = Reference< chart2::data::XDataProvider >(
863 0 : xFact->createInstance( aDataProviderServiceName ), uno::UNO_QUERY );
864 0 : }
865 0 : }
866 : }
867 0 : return xRet;
868 : }
869 :
870 : } // namespace SchXMLTools
871 :
872 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|