1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "SchXMLTools.hxx"
23 #include <rtl/ustrbuf.hxx>
24 #include <comphelper/InlineContainer.hxx>
25 // header for class SvXMLUnitConverter
26 #include <xmloff/xmluconv.hxx>
27 // header for struct SvXMLEnumMapEntry
28 #include <xmloff/xmlement.hxx>
29 #include <tools/solar.h>
31 // header for class SvXMLImportPropertyMapper
32 #include <xmloff/xmlimppr.hxx>
33 // header for class XMLPropStyleContext
34 #include <xmloff/prstylei.hxx>
35 // header for class XMLPropertySetMapper
36 #include <xmloff/xmlprmap.hxx>
37 #include <xmloff/xmlexp.hxx>
38 #include "xmloff/xmlnmspe.hxx"
39 #include <xmloff/xmlmetai.hxx>
41 #include <com/sun/star/beans/PropertyAttribute.hpp>
42 #include <com/sun/star/uno/XComponentContext.hpp>
43 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
44 #include <com/sun/star/chart2/data/XDataProvider.hpp>
45 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
46 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
47 #include <com/sun/star/chart2/XChartDocument.hpp>
48 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
49 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
50 #include <com/sun/star/container/XChild.hpp>
51 #include <com/sun/star/document/XDocumentProperties.hpp>
52 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
53 #include <com/sun/star/lang/XServiceName.hpp>
55 #include <comphelper/processfactory.hxx>
57 using namespace com::sun::star
;
58 using namespace ::xmloff::token
;
60 using ::com::sun::star::uno::Reference
;
61 using ::com::sun::star::uno::Sequence
;
66 OUString
lcl_getGeneratorFromModel( const uno::Reference
< frame::XModel
>& xChartModel
)
69 uno::Reference
< document::XDocumentPropertiesSupplier
> xChartDocumentPropertiesSupplier( xChartModel
, uno::UNO_QUERY
);
70 if( xChartDocumentPropertiesSupplier
.is() )
72 uno::Reference
< document::XDocumentProperties
> xChartDocumentProperties(
73 xChartDocumentPropertiesSupplier
->getDocumentProperties());
74 if( xChartDocumentProperties
.is() )
75 aGenerator
= xChartDocumentProperties
->getGenerator();
80 OUString
lcl_getGeneratorFromModelOrItsParent( const uno::Reference
< frame::XModel
>& xChartModel
)
82 OUString
aGenerator( lcl_getGeneratorFromModel(xChartModel
) );
83 if( aGenerator
.isEmpty() ) //try to get the missing info from the parent document
85 uno::Reference
< container::XChild
> xChild( xChartModel
, uno::UNO_QUERY
);
87 aGenerator
= lcl_getGeneratorFromModel( uno::Reference
< frame::XModel
>( xChild
->getParent(), uno::UNO_QUERY
) );
92 sal_Int32
lcl_getBuildIDFromGenerator( const OUString
& rGenerator
)
94 //returns -1 if nothing found
95 sal_Int32 nBuildId
= -1;
96 const OUString
sBuildCompare( "$Build-" );
97 sal_Int32 nBegin
= rGenerator
.indexOf( sBuildCompare
);
100 OUString
sBuildId( rGenerator
.copy( nBegin
+ sBuildCompare
.getLength() ) );
101 nBuildId
= sBuildId
.toInt32();
106 OUString
lcl_ConvertRange( const OUString
& rRange
, const Reference
< chart2::data::XDataProvider
>& xDataProvider
)
108 OUString aResult
= rRange
;
109 Reference
< chart2::data::XRangeXMLConversion
> xRangeConversion( xDataProvider
, uno::UNO_QUERY
);
110 if( xRangeConversion
.is())
111 aResult
= xRangeConversion
->convertRangeFromXML( rRange
);
115 Reference
< chart2::data::XDataSequence
> lcl_createNewSequenceFromCachedXMLRange( const Reference
< chart2::data::XDataSequence
>& xSeq
, const Reference
< chart2::data::XDataProvider
>& xDataProvider
)
117 Reference
< chart2::data::XDataSequence
> xRet
;
119 if( xSeq
.is() && SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq
, aRange
, /* bClearProp = */ true ) )
121 xRet
.set( xDataProvider
->createDataSequenceByRangeRepresentation(
122 lcl_ConvertRange( aRange
, xDataProvider
)) );
123 SchXMLTools::copyProperties( Reference
< beans::XPropertySet
>( xSeq
, uno::UNO_QUERY
),
124 Reference
< beans::XPropertySet
>( xRet
, uno::UNO_QUERY
));
129 } // anonymous namespace
131 // ----------------------------------------
133 namespace SchXMLTools
136 static SvXMLEnumMapEntry aXMLChartClassMap
[] =
138 { XML_LINE
, XML_CHART_CLASS_LINE
},
139 { XML_AREA
, XML_CHART_CLASS_AREA
},
140 { XML_CIRCLE
, XML_CHART_CLASS_CIRCLE
},
141 { XML_RING
, XML_CHART_CLASS_RING
},
142 { XML_SCATTER
, XML_CHART_CLASS_SCATTER
},
143 { XML_RADAR
, XML_CHART_CLASS_RADAR
},
144 { XML_FILLED_RADAR
, XML_CHART_CLASS_FILLED_RADAR
},
145 { XML_BAR
, XML_CHART_CLASS_BAR
},
146 { XML_STOCK
, XML_CHART_CLASS_STOCK
},
147 { XML_BUBBLE
, XML_CHART_CLASS_BUBBLE
},
148 { XML_SURFACE
, XML_CHART_CLASS_BAR
}, //@todo change this if a surface chart is available
149 { XML_ADD_IN
, XML_CHART_CLASS_ADDIN
},
150 { XML_TOKEN_INVALID
, XML_CHART_CLASS_UNKNOWN
}
153 SchXMLChartTypeEnum
GetChartTypeEnum( const OUString
& rClassName
)
155 sal_uInt16 nEnumVal
= XML_CHART_CLASS_UNKNOWN
;
156 if( !SvXMLUnitConverter::convertEnum(
157 nEnumVal
, rClassName
, aXMLChartClassMap
) )
158 nEnumVal
= XML_CHART_CLASS_UNKNOWN
;
159 return SchXMLChartTypeEnum(nEnumVal
);
162 typedef ::comphelper::MakeMap
< OUString
, OUString
> tMakeStringStringMap
;
164 const tMakeStringStringMap
& lcl_getChartTypeNameMap()
166 //shape property -- chart model object property
167 static tMakeStringStringMap g_aChartTypeNameMap
=
169 ( OUString( "com.sun.star.chart.LineDiagram" )
170 , OUString( "com.sun.star.chart2.LineChartType" ) )
172 ( OUString( "com.sun.star.chart.AreaDiagram" )
173 , OUString( "com.sun.star.chart2.AreaChartType" ) )
175 ( OUString( "com.sun.star.chart.BarDiagram" )
176 , OUString( "com.sun.star.chart2.ColumnChartType" ) )
178 ( OUString( "com.sun.star.chart.PieDiagram" )
179 , OUString( "com.sun.star.chart2.PieChartType" ) )
181 ( OUString( "com.sun.star.chart.DonutDiagram" )
182 , OUString( "com.sun.star.chart2.DonutChartType" ) )
184 ( OUString( "com.sun.star.chart.XYDiagram" )
185 , OUString( "com.sun.star.chart2.ScatterChartType" ) )
187 ( OUString( "com.sun.star.chart.NetDiagram" )
188 , OUString( "com.sun.star.chart2.NetChartType" ) )
190 ( OUString( "com.sun.star.chart.FilledNetDiagram" )
191 , OUString( "com.sun.star.chart2.FilledNetChartType" ) )
193 ( OUString( "com.sun.star.chart.StockDiagram" )
194 , OUString( "com.sun.star.chart2.CandleStickChartType" ) )
196 ( OUString( "com.sun.star.chart.BubbleDiagram" )
197 , OUString( "com.sun.star.chart2.BubbleChartType" ) )
200 return g_aChartTypeNameMap
;
204 OUString
GetNewChartTypeName( const OUString
& rOldChartTypeName
)
206 OUString
aNew(rOldChartTypeName
);
208 const tMakeStringStringMap
& rMap
= lcl_getChartTypeNameMap();
209 tMakeStringStringMap::const_iterator
aIt( rMap
.find( rOldChartTypeName
));
210 if( aIt
!= rMap
.end())
217 OUString
GetChartTypeByClassName(
218 const OUString
& rClassName
, bool bUseOldNames
)
220 OUStringBuffer aResultBuffer
;
221 bool bInternalType
= false;
224 aResultBuffer
.append( "com.sun.star.chart.");
226 aResultBuffer
.append( "com.sun.star.chart2.");
228 bInternalType
= true;
230 if( IsXMLToken( rClassName
, XML_LINE
))
231 aResultBuffer
.append("Line");
232 else if( IsXMLToken( rClassName
, XML_AREA
))
233 aResultBuffer
.append("Area");
234 else if( IsXMLToken( rClassName
, XML_BAR
))
237 aResultBuffer
.append("Bar");
240 aResultBuffer
.append("Column");
241 // @todo: might be Bar
244 else if( IsXMLToken( rClassName
, XML_CIRCLE
))
245 aResultBuffer
.append("Pie");
246 else if( IsXMLToken( rClassName
, XML_RING
))
247 aResultBuffer
.append("Donut");
248 else if( IsXMLToken( rClassName
, XML_SCATTER
))
251 aResultBuffer
.append("XY");
253 aResultBuffer
.append("Scatter");
256 else if( IsXMLToken( rClassName
, XML_BUBBLE
))
257 aResultBuffer
.append("Bubble");
258 else if( IsXMLToken( rClassName
, XML_RADAR
))
259 aResultBuffer
.append("Net");
260 else if( IsXMLToken( rClassName
, XML_FILLED_RADAR
))
261 aResultBuffer
.append("FilledNet");
262 else if( IsXMLToken( rClassName
, XML_STOCK
))
265 aResultBuffer
.append("Stock");
267 aResultBuffer
.append("CandleStick");
269 else if( IsXMLToken( rClassName
, XML_SURFACE
))
271 //@todo change this if a surface chart is available
273 aResultBuffer
.append("Bar");
275 aResultBuffer
.append("Column");
278 bInternalType
= false;
280 if( ! bInternalType
)
284 aResultBuffer
.append("Diagram");
286 aResultBuffer
.append("ChartType");
288 return aResultBuffer
.makeStringAndClear();
292 XMLTokenEnum
getTokenByChartType(
293 const OUString
& rChartTypeService
, bool bUseOldNames
)
295 XMLTokenEnum eResult
= XML_TOKEN_INVALID
;
296 OUString aPrefix
, aPostfix
;
300 aPrefix
= OUString( "com.sun.star.chart.");
301 aPostfix
= OUString( "Diagram");
305 aPrefix
= OUString( "com.sun.star.chart2.");
306 aPostfix
= OUString( "ChartType");
309 if( rChartTypeService
.match( aPrefix
))
311 sal_Int32 nSkip
= aPrefix
.getLength();
312 SAL_WARN_IF( rChartTypeService
.getLength() < nSkip
, "xmloff.chart", "ChartTypeService.getLength() < nSkip" );
313 sal_Int32 nTypeLength
= rChartTypeService
.getLength() - nSkip
- aPostfix
.getLength();
314 // if postfix matches and leaves a non-empty type
315 if( nTypeLength
> 0 && rChartTypeService
.match( aPostfix
, nSkip
+ nTypeLength
))
317 OUString
aServiceName( rChartTypeService
.copy( nSkip
, nTypeLength
));
319 if ( aServiceName
== "Line" )
321 else if ( aServiceName
== "Area" )
323 else if( aServiceName
== "Bar" ||
324 (!bUseOldNames
&& aServiceName
== "Column"))
326 else if ( aServiceName
== "Pie" )
327 eResult
= XML_CIRCLE
;
328 else if ( aServiceName
== "Donut" )
330 else if( (bUseOldNames
&& aServiceName
== "XY") ||
331 (!bUseOldNames
&& aServiceName
== "Scatter"))
332 eResult
= XML_SCATTER
;
333 else if ( aServiceName
== "Bubble" )
334 eResult
= XML_BUBBLE
;
335 else if ( aServiceName
== "Net" )
337 else if ( aServiceName
== "FilledNet" )
338 eResult
= XML_FILLED_RADAR
;
339 else if( (bUseOldNames
&& aServiceName
== "Stock") ||
340 (!bUseOldNames
&& aServiceName
== "CandleStick"))
345 if( eResult
== XML_TOKEN_INVALID
&& !rChartTypeService
.isEmpty() )
346 eResult
= XML_ADD_IN
;
351 Reference
< chart2::data::XLabeledDataSequence2
> GetNewLabeledDataSequence()
353 Reference
< uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
354 Reference
< chart2::data::XLabeledDataSequence2
> xResult
= chart2::data::LabeledDataSequence::create(xContext
);
358 Reference
< chart2::data::XDataSequence
> CreateDataSequence(
359 const OUString
& rRange
,
360 const Reference
< chart2::XChartDocument
>& xChartDoc
)
362 Reference
< chart2::data::XDataSequence
> xRet
;
364 if( !xChartDoc
.is() )
366 SAL_WARN("xmloff.chart", "need a chart document" );
370 Reference
< chart2::data::XDataProvider
> xDataProvider( xChartDoc
->getDataProvider() );
371 if( !xDataProvider
.is() )
373 SAL_WARN("xmloff.chart", "need a data provider" );
377 bool bUseInternal
= false;
378 uno::Reference
<beans::XPropertySet
> xPropSet(xDataProvider
, uno::UNO_QUERY
);
383 sal_Bool bVal
= sal_False
;
384 uno::Any any
= xPropSet
->getPropertyValue("UseInternalDataProvider");
386 bUseInternal
= static_cast<bool>(bVal
);
388 catch (const beans::UnknownPropertyException
&)
398 xRet
.set( xDataProvider
->createDataSequenceByRangeRepresentation( lcl_ConvertRange( rRange
, xDataProvider
)));
399 SchXMLTools::setXMLRangePropertyAtDataSequence( xRet
, rRange
);
401 catch( const lang::IllegalArgumentException
& )
403 SAL_WARN("xmloff.chart", "could not create data sequence" );
407 if( !xRet
.is() && !xChartDoc
->hasInternalDataProvider() && !rRange
.isEmpty() )
409 //#i103911# switch to internal data in case the parent cannot provide the requested data
410 xChartDoc
->createInternalDataProvider( sal_True
/* bCloneExistingData */ );
411 xDataProvider
= xChartDoc
->getDataProvider();
414 xRet
.set( xDataProvider
->createDataSequenceByRangeRepresentation( lcl_ConvertRange( rRange
, xDataProvider
)));
415 SchXMLTools::setXMLRangePropertyAtDataSequence( xRet
, rRange
);
417 catch( const lang::IllegalArgumentException
& )
419 SAL_WARN("xmloff.chart", "could not create data sequence" );
425 void CreateCategories(
426 const uno::Reference
< chart2::data::XDataProvider
> & xDataProvider
,
427 const uno::Reference
< chart2::XChartDocument
> & xNewDoc
,
428 const OUString
& rRangeAddress
,
429 sal_Int32 nCooSysIndex
,
430 sal_Int32 nDimensionIndex
,
431 tSchXMLLSequencesPerIndex
* pLSequencesPerIndex
)
435 if( xNewDoc
.is() && !rRangeAddress
.isEmpty())
437 if( xDataProvider
.is())
439 uno::Reference
< chart2::XDiagram
> xDia( xNewDoc
->getFirstDiagram());
443 uno::Reference
< chart2::XCoordinateSystemContainer
> xCooSysCnt( xDia
, uno::UNO_QUERY_THROW
);
444 uno::Sequence
< uno::Reference
< chart2::XCoordinateSystem
> >
445 aCooSysSeq( xCooSysCnt
->getCoordinateSystems());
446 if( nCooSysIndex
< aCooSysSeq
.getLength())
448 uno::Reference
< chart2::XCoordinateSystem
> xCooSys( aCooSysSeq
[nCooSysIndex
] );
449 SAL_WARN_IF( !xCooSys
.is(), "xmloff.chart", "xCooSys is NULL");
450 if( nDimensionIndex
< xCooSys
->getDimension() )
452 const sal_Int32 nMaxAxisIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimensionIndex
);
453 for(sal_Int32 nI
=0; nI
<=nMaxAxisIndex
; ++nI
)
455 uno::Reference
< chart2::XAxis
> xAxis( xCooSys
->getAxisByDimension( nDimensionIndex
, nI
));
458 chart2::ScaleData
aData( xAxis
->getScaleData());
459 uno::Reference
< chart2::data::XLabeledDataSequence
> xLabeledSeq(
460 GetNewLabeledDataSequence(), uno::UNO_QUERY_THROW
);
463 OUString
aConvertedRange( rRangeAddress
);
464 bool bRangeConverted
= false;
465 if( ! (xNewDoc
->hasInternalDataProvider() && aConvertedRange
== "categories"))
467 Reference
< chart2::data::XRangeXMLConversion
> xXMLConv( xDataProvider
, uno::UNO_QUERY
);
470 aConvertedRange
= xXMLConv
->convertRangeFromXML( rRangeAddress
);
471 bRangeConverted
= true;
474 Reference
< chart2::data::XDataSequence
> xSeq(
475 xDataProvider
->createDataSequenceByRangeRepresentation( aConvertedRange
));
476 xLabeledSeq
->setValues( xSeq
);
477 if( bRangeConverted
)
478 setXMLRangePropertyAtDataSequence( xSeq
, rRangeAddress
);
480 catch( const lang::IllegalArgumentException
& ex
)
482 SAL_WARN("xmloff.chart", "IllegalArgumentException caught, Message: " << ex
.Message
);
484 aData
.Categories
.set( xLabeledSeq
);
485 if( pLSequencesPerIndex
)
487 // register for setting local data if external data provider is not present
488 pLSequencesPerIndex
->insert(
489 tSchXMLLSequencesPerIndex::value_type(
490 tSchXMLIndexWithPart( SCH_XML_CATEGORIES_INDEX
, SCH_XML_PART_VALUES
), xLabeledSeq
));
492 xAxis
->setScaleData( aData
);
500 catch( uno::Exception
& )
502 SAL_WARN("xmloff.chart", "Exception caught while creating Categories" );
507 uno::Any
getPropertyFromContext( const OUString
& rPropertyName
, const XMLPropStyleContext
* pPropStyleContext
, const SvXMLStylesContext
* pStylesCtxt
)
510 if( !pPropStyleContext
|| !pStylesCtxt
)
512 const ::std::vector
< XMLPropertyState
>& rProperties
= pPropStyleContext
->GetProperties();
513 const UniReference
< XMLPropertySetMapper
>& rMapper
= pStylesCtxt
->GetImportPropertyMapper( pPropStyleContext
->GetFamily()/*XML_STYLE_FAMILY_SCH_CHART_ID*/ )->getPropertySetMapper();
514 ::std::vector
< XMLPropertyState
>::const_iterator
aEnd( rProperties
.end() );
515 ::std::vector
< XMLPropertyState
>::const_iterator
aPropIter( rProperties
.begin() );
516 for( aPropIter
= rProperties
.begin(); aPropIter
!= aEnd
; ++aPropIter
)
518 sal_Int32 nIdx
= aPropIter
->mnIndex
;
521 OUString aPropName
= rMapper
->GetEntryAPIName( nIdx
);
522 if(rPropertyName
.equals(aPropName
))
523 return aPropIter
->maValue
;
528 void exportText( SvXMLExport
& rExport
, const OUString
& rText
, bool bConvertTabsLFs
)
530 SvXMLElementExport
aPara( rExport
, XML_NAMESPACE_TEXT
,
531 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_P
),
532 sal_True
, sal_False
);
534 if( bConvertTabsLFs
)
536 sal_Int32 nStartPos
= 0;
537 sal_Int32 nEndPos
= rText
.getLength();
540 for( sal_Int32 nPos
= 0; nPos
< nEndPos
; nPos
++ )
542 cChar
= rText
[ nPos
];
545 case 0x0009: // tabulator
547 if( nPos
> nStartPos
)
548 rExport
.GetDocHandler()->characters( rText
.copy( nStartPos
, (nPos
- nStartPos
)) );
549 nStartPos
= nPos
+ 1;
551 SvXMLElementExport
aElem( rExport
, XML_NAMESPACE_TEXT
,
552 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_TAB_STOP
),
553 sal_False
, sal_False
);
557 case 0x000A: // linefeed
559 if( nPos
> nStartPos
)
560 rExport
.GetDocHandler()->characters( rText
.copy( nStartPos
, (nPos
- nStartPos
)) );
561 nStartPos
= nPos
+ 1;
563 SvXMLElementExport
aElem( rExport
, XML_NAMESPACE_TEXT
,
564 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_LINE_BREAK
),
565 sal_False
, sal_False
);
570 if( nEndPos
> nStartPos
)
573 rExport
.GetDocHandler()->characters( rText
);
575 rExport
.GetDocHandler()->characters( rText
.copy( nStartPos
, (nEndPos
- nStartPos
)) );
578 else // do not convert tabs and linefeeds (eg for numbers coming from unit converter)
580 rExport
.GetDocHandler()->characters( rText
);
584 void exportRangeToSomewhere( SvXMLExport
& rExport
, const OUString
& rValue
)
586 //with issue #i366# and CWS chart20 ranges for error bars were introduced
587 //to keep them during copy paste from calc to impress for example it
588 //was necessary to introduce a mapping between the used ranges within calc and the data written to the local table
589 //this is why we write this ranges here
591 //#i113950# first the range was exported to attribute text:id, but that attribute does not allow arbitrary strings anymore within ODF 1.2
592 //as an alternative the range info is now saved into the description at an empty group element (not very nice, but ODF conform)
594 const SvtSaveOptions::ODFDefaultVersion
nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
595 if( nCurrentODFVersion
== SvtSaveOptions::ODFVER_010
|| nCurrentODFVersion
== SvtSaveOptions::ODFVER_011
)
596 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
598 SvXMLElementExport
aEmptyShapeGroup( rExport
, XML_NAMESPACE_DRAW
,
599 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_G
),
600 sal_True
, sal_False
);
601 SvXMLElementExport
aDescription( rExport
, XML_NAMESPACE_SVG
,
602 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DESC
),
603 sal_True
, sal_False
);
604 rExport
.GetDocHandler()->characters( rValue
);
607 Reference
< chart2::XRegressionCurve
> getRegressionCurve(
608 const Reference
< chart2::XDataSeries
> & xDataSeries
)
610 Reference
< chart2::XRegressionCurve
> xResult
;
612 Reference
< chart2::XRegressionCurveContainer
> xRegCurveCnt( xDataSeries
, uno::UNO_QUERY
);
613 if( xRegCurveCnt
.is())
615 // find equation properties of first regression curve
616 Sequence
< Reference
< chart2::XRegressionCurve
> > aCurveSeq(
617 xRegCurveCnt
->getRegressionCurves() );
618 for( sal_Int32 nI
=0; nI
<aCurveSeq
.getLength(); ++nI
)
620 // skip mean-value line
621 Reference
< lang::XServiceName
> xServiceName( aCurveSeq
[nI
], uno::UNO_QUERY
);
622 if( xServiceName
.is())
624 OUString
aServiceName( xServiceName
->getServiceName());
625 if( aServiceName
== "com.sun.star.chart2.MeanValueRegressionCurve" )
628 // take first non-empty curve
629 if( aCurveSeq
[nI
].is())
631 xResult
.set( aCurveSeq
[nI
] );
639 void setXMLRangePropertyAtDataSequence(
640 const Reference
< chart2::data::XDataSequence
> & xDataSequence
,
641 const OUString
& rXMLRange
)
643 if( !xDataSequence
.is())
647 const OUString
aXMLRangePropName( "CachedXMLRange" );
648 Reference
< beans::XPropertySet
> xProp( xDataSequence
, uno::UNO_QUERY_THROW
);
649 Reference
< beans::XPropertySetInfo
> xInfo( xProp
->getPropertySetInfo());
650 if( xInfo
.is() && xInfo
->hasPropertyByName( aXMLRangePropName
))
651 xProp
->setPropertyValue( aXMLRangePropName
, uno::makeAny( rXMLRange
));
653 catch( const uno::Exception
& ex
)
655 SAL_WARN("xmloff.chart", "Exception caught, Message: " << ex
.Message
);
659 bool getXMLRangePropertyFromDataSequence(
660 const Reference
< chart2::data::XDataSequence
> & xDataSequence
,
661 OUString
& rOutXMLRange
,
662 bool bClearProp
/* = false */)
664 bool bResult
= false;
665 if( xDataSequence
.is())
669 const OUString
aXMLRangePropName( "CachedXMLRange" );
670 Reference
< beans::XPropertySet
> xProp( xDataSequence
, uno::UNO_QUERY_THROW
);
671 Reference
< beans::XPropertySetInfo
> xInfo( xProp
->getPropertySetInfo());
673 ( xInfo
.is() && xInfo
->hasPropertyByName( aXMLRangePropName
) &&
674 ( xProp
->getPropertyValue( aXMLRangePropName
) >>= rOutXMLRange
) &&
675 !rOutXMLRange
.isEmpty());
676 // clear the property after usage
677 if( bClearProp
&& bResult
)
678 xProp
->setPropertyValue( aXMLRangePropName
, uno::Any( OUString()));
680 catch( const uno::Exception
& ex
)
682 SAL_WARN("xmloff.chart", "Exception caught, Message: " << ex
.Message
);
689 const Reference
< beans::XPropertySet
> & xSource
,
690 const Reference
< beans::XPropertySet
> & xDestination
)
692 if( ! (xSource
.is() && xDestination
.is()) )
697 Reference
< beans::XPropertySetInfo
> xSrcInfo( xSource
->getPropertySetInfo(), uno::UNO_QUERY_THROW
);
698 Reference
< beans::XPropertySetInfo
> xDestInfo( xDestination
->getPropertySetInfo(), uno::UNO_QUERY_THROW
);
699 Sequence
< beans::Property
> aProperties( xSrcInfo
->getProperties());
700 const sal_Int32 nLength
= aProperties
.getLength();
701 for( sal_Int32 i
= 0; i
< nLength
; ++i
)
703 OUString
aName( aProperties
[i
].Name
);
704 if( xDestInfo
->hasPropertyByName( aName
))
706 beans::Property
aProp( xDestInfo
->getPropertyByName( aName
));
707 if( (aProp
.Attributes
& beans::PropertyAttribute::READONLY
) == 0 )
708 xDestination
->setPropertyValue(
709 aName
, xSource
->getPropertyValue( aName
));
713 catch( const uno::Exception
& )
715 SAL_WARN("xmloff.chart", "Copying property sets failed!" );
719 bool switchBackToDataProviderFromParent( const Reference
< chart2::XChartDocument
>& xChartDoc
, const tSchXMLLSequencesPerIndex
& rLSequencesPerIndex
)
721 //return whether the switch is successful
722 if( !xChartDoc
.is() || !xChartDoc
->hasInternalDataProvider() )
724 Reference
< chart2::data::XDataProvider
> xDataProviderFromParent( SchXMLTools::getDataProviderFromParent( xChartDoc
) );
725 if( !xDataProviderFromParent
.is() )
727 uno::Reference
< chart2::data::XDataReceiver
> xDataReceiver( xChartDoc
, uno::UNO_QUERY
);
728 if( !xDataReceiver
.is() )
731 xDataReceiver
->attachDataProvider( xDataProviderFromParent
);
733 for( tSchXMLLSequencesPerIndex::const_iterator
aLSeqIt( rLSequencesPerIndex
.begin() );
734 aLSeqIt
!= rLSequencesPerIndex
.end(); ++aLSeqIt
)
736 Reference
< chart2::data::XLabeledDataSequence
> xLabeledSeq( aLSeqIt
->second
);
737 if( !xLabeledSeq
.is() )
739 Reference
< chart2::data::XDataSequence
> xNewSeq
;
740 xNewSeq
= lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq
->getValues(), xDataProviderFromParent
);
742 xLabeledSeq
->setValues( xNewSeq
);
743 xNewSeq
= lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq
->getLabel(), xDataProviderFromParent
);
745 xLabeledSeq
->setLabel( xNewSeq
);
750 void setBuildIDAtImportInfo( uno::Reference
< frame::XModel
> xModel
, Reference
< beans::XPropertySet
> xImportInfo
)
752 OUString
aGenerator( lcl_getGeneratorFromModelOrItsParent(xModel
) );
753 if( !aGenerator
.isEmpty() )
754 SvXMLMetaDocumentContext::setBuildId( aGenerator
, xImportInfo
);
757 bool isDocumentGeneratedWithOpenOfficeOlderThan3_3( const uno::Reference
< frame::XModel
>& xChartModel
)
759 bool bResult
= isDocumentGeneratedWithOpenOfficeOlderThan3_0( xChartModel
);
762 OUString
aGenerator( lcl_getGeneratorFromModel(xChartModel
) );
763 if( aGenerator
.indexOf( "OpenOffice.org_project/3" ) != -1 )
765 if( aGenerator
.indexOf( "OpenOffice.org_project/300m" ) != -1 )
767 sal_Int32 nBuilId
= lcl_getBuildIDFromGenerator( lcl_getGeneratorFromModel(xChartModel
) );
768 if( nBuilId
>0 && nBuilId
<9491 ) //9491 is build id of dev300m76
771 else if( aGenerator
.indexOf( "OpenOffice.org_project/310m" ) != -1 )
773 else if( aGenerator
.indexOf( "OpenOffice.org_project/320m" ) != -1 )
780 bool isDocumentGeneratedWithOpenOfficeOlderThan3_0( const uno::Reference
< frame::XModel
>& xChartModel
)
782 bool bResult
= isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel
);
785 OUString
aGenerator( lcl_getGeneratorFromModel(xChartModel
) );
786 if( aGenerator
.indexOf( "OpenOffice.org_project/680m" ) != -1 )
792 bool isDocumentGeneratedWithOpenOfficeOlderThan2_4( const uno::Reference
< frame::XModel
>& xChartModel
)
794 if( isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel
) )
797 if( isDocumentGeneratedWithOpenOfficeOlderThan3_0( xChartModel
) )
799 sal_Int32 nBuilId
= lcl_getBuildIDFromGenerator( lcl_getGeneratorFromModel(xChartModel
) );
800 if( nBuilId
>0 && nBuilId
<=9238 ) //9238 is build id of OpenOffice.org 2.3.1
806 bool isDocumentGeneratedWithOpenOfficeOlderThan2_3( const uno::Reference
< frame::XModel
>& xChartModel
)
808 bool bResult
= false;
809 OUString
aGenerator( lcl_getGeneratorFromModel(xChartModel
) );
810 //if there is a meta stream at the chart object it was not written with an older OpenOffice version < 2.3
811 if( aGenerator
.isEmpty() )
813 //if there is no meta stream at the chart object we need to check whether the parent document is OpenOffice at all
814 uno::Reference
< container::XChild
> xChild( xChartModel
, uno::UNO_QUERY
);
817 aGenerator
= lcl_getGeneratorFromModel( uno::Reference
< frame::XModel
>( xChild
->getParent(), uno::UNO_QUERY
) );
818 if( aGenerator
.indexOf( "OpenOffice.org_project" ) != -1 )
820 //the chart application has not created files without a meta stream since OOo 2.3 (OOo 2.3 has written a metastream already)
821 //only the report builder extension has created some files with OOo 3.1 that do not have a meta stream
822 if( aGenerator
.indexOf( "OpenOffice.org_project/31" ) != -1 )
823 bResult
= false;//#i100102# probably generated with OOo 3.1 by the report designer
825 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
827 else if( isDocumentGeneratedWithOpenOfficeOlderThan2_0(xChartModel
) )
834 bool isDocumentGeneratedWithOpenOfficeOlderThan2_0( const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XModel
>& xChartModel
)
836 bool bResult
= false;
837 OUString
aGenerator( lcl_getGeneratorFromModelOrItsParent(xChartModel
) );
838 if( ( aGenerator
.indexOf( "OpenOffice.org 1" ) == 0 )
839 || ( aGenerator
.indexOf( "StarOffice 6" ) == 0 )
840 || ( aGenerator
.indexOf( "StarOffice 7" ) == 0 )
841 || ( aGenerator
.indexOf( "StarSuite 6" ) == 0 )
842 || ( aGenerator
.indexOf( "StarSuite 7" ) == 0 )
848 Reference
< chart2::data::XDataProvider
> getDataProviderFromParent( const Reference
< chart2::XChartDocument
>& xChartDoc
)
850 Reference
< chart2::data::XDataProvider
> xRet
;
851 uno::Reference
< container::XChild
> xChild( xChartDoc
, uno::UNO_QUERY
);
854 Reference
< lang::XMultiServiceFactory
> xFact( xChild
->getParent(), uno::UNO_QUERY
);
857 const OUString
aDataProviderServiceName( "com.sun.star.chart2.data.DataProvider");
858 const uno::Sequence
< OUString
> aServiceNames( xFact
->getAvailableServiceNames());
859 const OUString
* pBegin
= aServiceNames
.getConstArray();
860 const OUString
* pEnd
= pBegin
+ aServiceNames
.getLength();
861 if( ::std::find( pBegin
, pEnd
, aDataProviderServiceName
) != pEnd
)
863 xRet
= Reference
< chart2::data::XDataProvider
>(
864 xFact
->createInstance( aDataProviderServiceName
), uno::UNO_QUERY
);
871 } // namespace SchXMLTools
873 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */