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 .
20 #include "SchXMLTools.hxx"
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>
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>
49 #include <comphelper/processfactory.hxx>
52 using namespace com::sun::star
;
53 using namespace ::xmloff::token
;
55 using ::com::sun::star::uno::Reference
;
56 using ::com::sun::star::uno::Sequence
;
61 OUString
lcl_getGeneratorFromModel( const uno::Reference
< frame::XModel
>& xChartModel
)
64 uno::Reference
< document::XDocumentPropertiesSupplier
> xChartDocumentPropertiesSupplier( xChartModel
, uno::UNO_QUERY
);
65 if( xChartDocumentPropertiesSupplier
.is() )
67 uno::Reference
< document::XDocumentProperties
> xChartDocumentProperties(
68 xChartDocumentPropertiesSupplier
->getDocumentProperties());
69 if( xChartDocumentProperties
.is() )
70 aGenerator
= xChartDocumentProperties
->getGenerator();
75 OUString
lcl_getGeneratorFromModelOrItsParent( const uno::Reference
< frame::XModel
>& xChartModel
)
77 OUString
aGenerator( lcl_getGeneratorFromModel(xChartModel
) );
78 if( aGenerator
.isEmpty() ) //try to get the missing info from the parent document
80 uno::Reference
< container::XChild
> xChild( xChartModel
, uno::UNO_QUERY
);
82 aGenerator
= lcl_getGeneratorFromModel( uno::Reference
< frame::XModel
>( xChild
->getParent(), uno::UNO_QUERY
) );
87 sal_Int32
lcl_getBuildIDFromGenerator( const OUString
& rGenerator
)
89 //returns -1 if nothing found
90 sal_Int32 nBuildId
= -1;
91 const OUString
sBuildCompare( "$Build-" );
92 sal_Int32 nBegin
= rGenerator
.indexOf( sBuildCompare
);
95 OUString
sBuildId( rGenerator
.copy( nBegin
+ sBuildCompare
.getLength() ) );
96 nBuildId
= sBuildId
.toInt32();
101 OUString
lcl_ConvertRange( const OUString
& rRange
, const Reference
< chart2::data::XDataProvider
>& xDataProvider
)
103 OUString aResult
= rRange
;
104 Reference
< chart2::data::XRangeXMLConversion
> xRangeConversion( xDataProvider
, uno::UNO_QUERY
);
105 if( xRangeConversion
.is())
106 aResult
= xRangeConversion
->convertRangeFromXML( rRange
);
110 Reference
< chart2::data::XDataSequence
> lcl_createNewSequenceFromCachedXMLRange( const Reference
< chart2::data::XDataSequence
>& xSeq
, const Reference
< chart2::data::XDataProvider
>& xDataProvider
)
112 Reference
< chart2::data::XDataSequence
> xRet
;
114 if( xSeq
.is() && SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq
, aRange
, /* bClearProp = */ true ) )
116 xRet
.set( xDataProvider
->createDataSequenceByRangeRepresentation(
117 lcl_ConvertRange( aRange
, xDataProvider
)) );
118 SchXMLTools::copyProperties( Reference
< beans::XPropertySet
>( xSeq
, uno::UNO_QUERY
),
119 Reference
< beans::XPropertySet
>( xRet
, uno::UNO_QUERY
));
124 } // anonymous namespace
126 namespace SchXMLTools
129 static const SvXMLEnumMapEntry aXMLChartClassMap
[] =
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
}
147 SchXMLChartTypeEnum
GetChartTypeEnum( const OUString
& rClassName
)
149 sal_uInt16 nEnumVal
= XML_CHART_CLASS_UNKNOWN
;
150 if( !SvXMLUnitConverter::convertEnum(
151 nEnumVal
, rClassName
, aXMLChartClassMap
) )
152 nEnumVal
= XML_CHART_CLASS_UNKNOWN
;
153 return SchXMLChartTypeEnum(nEnumVal
);
156 typedef ::comphelper::MakeMap
< OUString
, OUString
> tMakeStringStringMap
;
158 const tMakeStringStringMap
& lcl_getChartTypeNameMap()
160 //shape property -- chart model object property
161 static const tMakeStringStringMap g_aChartTypeNameMap
=
163 ( OUString( "com.sun.star.chart.LineDiagram" )
164 , OUString( "com.sun.star.chart2.LineChartType" ) )
166 ( OUString( "com.sun.star.chart.AreaDiagram" )
167 , OUString( "com.sun.star.chart2.AreaChartType" ) )
169 ( OUString( "com.sun.star.chart.BarDiagram" )
170 , OUString( "com.sun.star.chart2.ColumnChartType" ) )
172 ( OUString( "com.sun.star.chart.PieDiagram" )
173 , OUString( "com.sun.star.chart2.PieChartType" ) )
175 ( OUString( "com.sun.star.chart.DonutDiagram" )
176 , OUString( "com.sun.star.chart2.DonutChartType" ) )
178 ( OUString( "com.sun.star.chart.XYDiagram" )
179 , OUString( "com.sun.star.chart2.ScatterChartType" ) )
181 ( OUString( "com.sun.star.chart.NetDiagram" )
182 , OUString( "com.sun.star.chart2.NetChartType" ) )
184 ( OUString( "com.sun.star.chart.FilledNetDiagram" )
185 , OUString( "com.sun.star.chart2.FilledNetChartType" ) )
187 ( OUString( "com.sun.star.chart.StockDiagram" )
188 , OUString( "com.sun.star.chart2.CandleStickChartType" ) )
190 ( OUString( "com.sun.star.chart.BubbleDiagram" )
191 , OUString( "com.sun.star.chart2.BubbleChartType" ) )
193 ( OUString( "com.sun.star.chart.GL3DBarDiagram" )
194 , OUString( "com.sun.star.chart2.GL3DBarChartType" ) )
197 return g_aChartTypeNameMap
;
200 OUString
GetNewChartTypeName( const OUString
& rOldChartTypeName
)
202 OUString
aNew(rOldChartTypeName
);
204 const tMakeStringStringMap
& rMap
= lcl_getChartTypeNameMap();
205 tMakeStringStringMap::const_iterator
aIt( rMap
.find( rOldChartTypeName
));
206 if( aIt
!= rMap
.end())
213 OUString
GetChartTypeByClassName(
214 const OUString
& rClassName
, bool bUseOldNames
)
216 OUStringBuffer aResultBuffer
;
217 bool bInternalType
= false;
220 aResultBuffer
.append( "com.sun.star.chart.");
222 aResultBuffer
.append( "com.sun.star.chart2.");
224 bInternalType
= true;
226 if( IsXMLToken( rClassName
, XML_LINE
))
227 aResultBuffer
.append("Line");
228 else if( IsXMLToken( rClassName
, XML_AREA
))
229 aResultBuffer
.append("Area");
230 else if( IsXMLToken( rClassName
, XML_BAR
))
233 aResultBuffer
.append("Bar");
236 aResultBuffer
.append("Column");
237 // @todo: might be Bar
240 else if( IsXMLToken( rClassName
, XML_CIRCLE
))
241 aResultBuffer
.append("Pie");
242 else if( IsXMLToken( rClassName
, XML_RING
))
243 aResultBuffer
.append("Donut");
244 else if( IsXMLToken( rClassName
, XML_SCATTER
))
247 aResultBuffer
.append("XY");
249 aResultBuffer
.append("Scatter");
252 else if( IsXMLToken( rClassName
, XML_BUBBLE
))
253 aResultBuffer
.append("Bubble");
254 else if( IsXMLToken( rClassName
, XML_RADAR
))
255 aResultBuffer
.append("Net");
256 else if( IsXMLToken( rClassName
, XML_FILLED_RADAR
))
257 aResultBuffer
.append("FilledNet");
258 else if( IsXMLToken( rClassName
, XML_STOCK
))
261 aResultBuffer
.append("Stock");
263 aResultBuffer
.append("CandleStick");
265 else if( IsXMLToken( rClassName
, XML_SURFACE
))
267 //@todo change this if a surface chart is available
269 aResultBuffer
.append("Bar");
271 aResultBuffer
.append("Column");
273 else if (IsXMLToken(rClassName
, XML_GL3DBAR
))
274 aResultBuffer
.append("GL3DBar");
276 bInternalType
= false;
278 if( ! bInternalType
)
282 aResultBuffer
.append("Diagram");
284 aResultBuffer
.append("ChartType");
286 return aResultBuffer
.makeStringAndClear();
290 XMLTokenEnum
getTokenByChartType(
291 const OUString
& rChartTypeService
, bool bUseOldNames
)
293 XMLTokenEnum eResult
= XML_TOKEN_INVALID
;
294 OUString aPrefix
, aPostfix
;
298 aPrefix
= "com.sun.star.chart.";
299 aPostfix
= "Diagram";
303 aPrefix
= "com.sun.star.chart2.";
304 aPostfix
= "ChartType";
307 if( rChartTypeService
.match( aPrefix
))
309 sal_Int32 nSkip
= aPrefix
.getLength();
310 SAL_WARN_IF( rChartTypeService
.getLength() < nSkip
, "xmloff.chart", "ChartTypeService.getLength() < nSkip" );
311 sal_Int32 nTypeLength
= rChartTypeService
.getLength() - nSkip
- aPostfix
.getLength();
312 // if postfix matches and leaves a non-empty type
313 if( nTypeLength
> 0 && rChartTypeService
.match( aPostfix
, nSkip
+ nTypeLength
))
315 OUString
aServiceName( rChartTypeService
.copy( nSkip
, nTypeLength
));
317 if ( aServiceName
== "Line" )
319 else if ( aServiceName
== "Area" )
321 else if( aServiceName
== "Bar" ||
322 (!bUseOldNames
&& aServiceName
== "Column"))
324 else if ( aServiceName
== "Pie" )
325 eResult
= XML_CIRCLE
;
326 else if ( aServiceName
== "Donut" )
328 else if( (bUseOldNames
&& aServiceName
== "XY") ||
329 (!bUseOldNames
&& aServiceName
== "Scatter"))
330 eResult
= XML_SCATTER
;
331 else if ( aServiceName
== "Bubble" )
332 eResult
= XML_BUBBLE
;
333 else if ( aServiceName
== "Net" )
335 else if ( aServiceName
== "FilledNet" )
336 eResult
= XML_FILLED_RADAR
;
337 else if( (bUseOldNames
&& aServiceName
== "Stock") ||
338 (!bUseOldNames
&& aServiceName
== "CandleStick"))
340 else if (aServiceName
== "GL3DBar")
341 eResult
= XML_GL3DBAR
;
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
);
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 Reference
< chart2::data::XDataSequence
> CreateDataSequenceWithoutConvert(
426 const OUString
& rRange
,
427 const Reference
< chart2::XChartDocument
>& xChartDoc
)
429 Reference
< chart2::data::XDataSequence
> xRet
;
431 if( !xChartDoc
.is() )
433 SAL_WARN("xmloff.chart", "need a chart document" );
437 Reference
< chart2::data::XDataProvider
> xDataProvider( xChartDoc
->getDataProvider() );
438 if( !xDataProvider
.is() )
440 SAL_WARN("xmloff.chart", "need a data provider" );
446 xRet
.set( xDataProvider
->createDataSequenceByRangeRepresentation( rRange
) );
447 SchXMLTools::setXMLRangePropertyAtDataSequence( xRet
, rRange
);
449 catch( const lang::IllegalArgumentException
& )
451 SAL_WARN("xmloff.chart", "could not create data sequence" );
457 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
)
467 if( xNewDoc
.is() && !rRangeAddress
.isEmpty())
469 if( xDataProvider
.is())
471 uno::Reference
< chart2::XDiagram
> xDia( xNewDoc
->getFirstDiagram());
475 uno::Reference
< chart2::XCoordinateSystemContainer
> xCooSysCnt( xDia
, uno::UNO_QUERY_THROW
);
476 uno::Sequence
< uno::Reference
< chart2::XCoordinateSystem
> >
477 aCooSysSeq( xCooSysCnt
->getCoordinateSystems());
478 if( nCooSysIndex
< aCooSysSeq
.getLength())
480 uno::Reference
< chart2::XCoordinateSystem
> xCooSys( aCooSysSeq
[nCooSysIndex
] );
481 SAL_WARN_IF( !xCooSys
.is(), "xmloff.chart", "xCooSys is NULL");
482 if( nDimensionIndex
< xCooSys
->getDimension() )
484 const sal_Int32 nMaxAxisIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimensionIndex
);
485 for(sal_Int32 nI
=0; nI
<=nMaxAxisIndex
; ++nI
)
487 uno::Reference
< chart2::XAxis
> xAxis( xCooSys
->getAxisByDimension( nDimensionIndex
, nI
));
490 chart2::ScaleData
aData( xAxis
->getScaleData());
491 uno::Reference
< chart2::data::XLabeledDataSequence
> xLabeledSeq(
492 GetNewLabeledDataSequence(), uno::UNO_QUERY_THROW
);
495 OUString
aConvertedRange( rRangeAddress
);
496 bool bRangeConverted
= false;
497 if( ! (xNewDoc
->hasInternalDataProvider() && aConvertedRange
== "categories"))
499 Reference
< chart2::data::XRangeXMLConversion
> xXMLConv( xDataProvider
, uno::UNO_QUERY
);
502 aConvertedRange
= xXMLConv
->convertRangeFromXML( rRangeAddress
);
503 bRangeConverted
= true;
506 Reference
< chart2::data::XDataSequence
> xSeq(
507 xDataProvider
->createDataSequenceByRangeRepresentation( aConvertedRange
));
508 xLabeledSeq
->setValues( xSeq
);
509 if( bRangeConverted
)
510 setXMLRangePropertyAtDataSequence( xSeq
, rRangeAddress
);
512 catch( const lang::IllegalArgumentException
& ex
)
514 SAL_WARN("xmloff.chart", "IllegalArgumentException caught, Message: " << ex
.Message
);
516 aData
.Categories
.set( xLabeledSeq
);
517 if( pLSequencesPerIndex
)
519 // register for setting local data if external data provider is not present
520 pLSequencesPerIndex
->insert(
521 tSchXMLLSequencesPerIndex::value_type(
522 tSchXMLIndexWithPart( SCH_XML_CATEGORIES_INDEX
, SCH_XML_PART_VALUES
), xLabeledSeq
));
524 xAxis
->setScaleData( aData
);
532 catch( uno::Exception
& )
534 SAL_WARN("xmloff.chart", "Exception caught while creating Categories" );
538 uno::Any
getPropertyFromContext( const OUString
& rPropertyName
, const XMLPropStyleContext
* pPropStyleContext
, const SvXMLStylesContext
* pStylesCtxt
)
541 if( !pPropStyleContext
|| !pStylesCtxt
)
543 const ::std::vector
< XMLPropertyState
>& rProperties
= pPropStyleContext
->GetProperties();
544 const rtl::Reference
< XMLPropertySetMapper
>& rMapper
= pStylesCtxt
->GetImportPropertyMapper( pPropStyleContext
->GetFamily()/*XML_STYLE_FAMILY_SCH_CHART_ID*/ )->getPropertySetMapper();
545 ::std::vector
< XMLPropertyState
>::const_iterator
aEnd( rProperties
.end() );
546 ::std::vector
< XMLPropertyState
>::const_iterator
aPropIter( rProperties
.begin() );
547 for( aPropIter
= rProperties
.begin(); aPropIter
!= aEnd
; ++aPropIter
)
549 sal_Int32 nIdx
= aPropIter
->mnIndex
;
552 OUString aPropName
= rMapper
->GetEntryAPIName( nIdx
);
553 if(rPropertyName
.equals(aPropName
))
554 return aPropIter
->maValue
;
559 void exportText( SvXMLExport
& rExport
, const OUString
& rText
, bool bConvertTabsLFs
)
561 SvXMLElementExport
aPara( rExport
, XML_NAMESPACE_TEXT
,
562 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_P
),
565 if( bConvertTabsLFs
)
567 sal_Int32 nStartPos
= 0;
568 sal_Int32 nEndPos
= rText
.getLength();
571 for( sal_Int32 nPos
= 0; nPos
< nEndPos
; nPos
++ )
573 cChar
= rText
[ nPos
];
576 case 0x0009: // tabulator
578 if( nPos
> nStartPos
)
579 rExport
.GetDocHandler()->characters( rText
.copy( nStartPos
, (nPos
- nStartPos
)) );
580 nStartPos
= nPos
+ 1;
582 SvXMLElementExport
aElem( rExport
, XML_NAMESPACE_TEXT
,
583 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_TAB_STOP
),
588 case 0x000A: // linefeed
590 if( nPos
> nStartPos
)
591 rExport
.GetDocHandler()->characters( rText
.copy( nStartPos
, (nPos
- nStartPos
)) );
592 nStartPos
= nPos
+ 1;
594 SvXMLElementExport
aElem( rExport
, XML_NAMESPACE_TEXT
,
595 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_LINE_BREAK
),
601 if( nEndPos
> nStartPos
)
604 rExport
.GetDocHandler()->characters( rText
);
606 rExport
.GetDocHandler()->characters( rText
.copy( nStartPos
, (nEndPos
- nStartPos
)) );
609 else // do not convert tabs and linefeeds (eg for numbers coming from unit converter)
611 rExport
.GetDocHandler()->characters( rText
);
615 void exportRangeToSomewhere( SvXMLExport
& rExport
, const OUString
& rValue
)
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
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)
625 const SvtSaveOptions::ODFDefaultVersion
nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
626 if( nCurrentODFVersion
== SvtSaveOptions::ODFVER_010
|| nCurrentODFVersion
== SvtSaveOptions::ODFVER_011
)
627 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
629 SvXMLElementExport
aEmptyShapeGroup( rExport
, XML_NAMESPACE_DRAW
,
630 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_G
),
632 SvXMLElementExport
aDescription( rExport
, XML_NAMESPACE_SVG
,
633 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DESC
),
635 rExport
.GetDocHandler()->characters( rValue
);
638 void setXMLRangePropertyAtDataSequence(
639 const Reference
< chart2::data::XDataSequence
> & xDataSequence
,
640 const OUString
& rXMLRange
)
642 if( !xDataSequence
.is())
646 const OUString
aXMLRangePropName( "CachedXMLRange" );
647 Reference
< beans::XPropertySet
> xProp( xDataSequence
, uno::UNO_QUERY_THROW
);
648 Reference
< beans::XPropertySetInfo
> xInfo( xProp
->getPropertySetInfo());
649 if( xInfo
.is() && xInfo
->hasPropertyByName( aXMLRangePropName
))
650 xProp
->setPropertyValue( aXMLRangePropName
, uno::makeAny( rXMLRange
));
652 catch( const uno::Exception
& ex
)
654 SAL_WARN("xmloff.chart", "Exception caught, Message: " << ex
.Message
);
658 bool getXMLRangePropertyFromDataSequence(
659 const Reference
< chart2::data::XDataSequence
> & xDataSequence
,
660 OUString
& rOutXMLRange
,
661 bool bClearProp
/* = false */)
663 bool bResult
= false;
664 if( xDataSequence
.is())
668 const OUString
aXMLRangePropName( "CachedXMLRange" );
669 Reference
< beans::XPropertySet
> xProp( xDataSequence
, uno::UNO_QUERY_THROW
);
670 Reference
< beans::XPropertySetInfo
> xInfo( xProp
->getPropertySetInfo());
672 ( xInfo
.is() && xInfo
->hasPropertyByName( aXMLRangePropName
) &&
673 ( xProp
->getPropertyValue( aXMLRangePropName
) >>= rOutXMLRange
) &&
674 !rOutXMLRange
.isEmpty());
675 // clear the property after usage
676 if( bClearProp
&& bResult
)
677 xProp
->setPropertyValue( aXMLRangePropName
, uno::Any( OUString()));
679 catch( const uno::Exception
& ex
)
681 SAL_WARN("xmloff.chart", "Exception caught, Message: " << ex
.Message
);
688 const Reference
< beans::XPropertySet
> & xSource
,
689 const Reference
< beans::XPropertySet
> & xDestination
)
691 if( ! (xSource
.is() && xDestination
.is()) )
696 Reference
< beans::XPropertySetInfo
> xSrcInfo( xSource
->getPropertySetInfo(), uno::UNO_QUERY_THROW
);
697 Reference
< beans::XPropertySetInfo
> xDestInfo( xDestination
->getPropertySetInfo(), uno::UNO_QUERY_THROW
);
698 Sequence
< beans::Property
> aProperties( xSrcInfo
->getProperties());
699 const sal_Int32 nLength
= aProperties
.getLength();
700 for( sal_Int32 i
= 0; i
< nLength
; ++i
)
702 OUString
aName( aProperties
[i
].Name
);
703 if( xDestInfo
->hasPropertyByName( aName
))
705 beans::Property
aProp( xDestInfo
->getPropertyByName( aName
));
706 if( (aProp
.Attributes
& beans::PropertyAttribute::READONLY
) == 0 )
707 xDestination
->setPropertyValue(
708 aName
, xSource
->getPropertyValue( aName
));
712 catch( const uno::Exception
& )
714 SAL_WARN("xmloff.chart", "Copying property sets failed!" );
718 bool switchBackToDataProviderFromParent( const Reference
< chart2::XChartDocument
>& xChartDoc
, const tSchXMLLSequencesPerIndex
& rLSequencesPerIndex
)
720 //return whether the switch is successful
721 if( !xChartDoc
.is() || !xChartDoc
->hasInternalDataProvider() )
723 Reference
< chart2::data::XDataProvider
> xDataProviderFromParent( SchXMLTools::getDataProviderFromParent( xChartDoc
) );
724 if( !xDataProviderFromParent
.is() )
726 uno::Reference
< chart2::data::XDataReceiver
> xDataReceiver( xChartDoc
, uno::UNO_QUERY
);
727 if( !xDataReceiver
.is() )
730 xDataReceiver
->attachDataProvider( xDataProviderFromParent
);
732 for( tSchXMLLSequencesPerIndex::const_iterator
aLSeqIt( rLSequencesPerIndex
.begin() );
733 aLSeqIt
!= rLSequencesPerIndex
.end(); ++aLSeqIt
)
735 Reference
< chart2::data::XLabeledDataSequence
> xLabeledSeq( aLSeqIt
->second
);
736 if( !xLabeledSeq
.is() )
738 Reference
< chart2::data::XDataSequence
> xNewSeq
;
739 xNewSeq
= lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq
->getValues(), xDataProviderFromParent
);
741 xLabeledSeq
->setValues( xNewSeq
);
742 xNewSeq
= lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq
->getLabel(), xDataProviderFromParent
);
744 xLabeledSeq
->setLabel( xNewSeq
);
749 void setBuildIDAtImportInfo( uno::Reference
< frame::XModel
> xModel
, Reference
< beans::XPropertySet
> xImportInfo
)
751 OUString
aGenerator( lcl_getGeneratorFromModelOrItsParent(xModel
) );
752 if( !aGenerator
.isEmpty() )
753 SvXMLMetaDocumentContext::setBuildId( aGenerator
, xImportInfo
);
756 bool isDocumentGeneratedWithOpenOfficeOlderThan3_3( const uno::Reference
< frame::XModel
>& xChartModel
)
758 bool bResult
= isDocumentGeneratedWithOpenOfficeOlderThan3_0( xChartModel
);
761 OUString
aGenerator( lcl_getGeneratorFromModel(xChartModel
) );
762 if( aGenerator
.indexOf( "OpenOffice.org_project/3" ) != -1 )
764 if( aGenerator
.indexOf( "OpenOffice.org_project/300m" ) != -1 )
766 sal_Int32 nBuilId
= lcl_getBuildIDFromGenerator( lcl_getGeneratorFromModel(xChartModel
) );
767 if( nBuilId
>0 && nBuilId
<9491 ) //9491 is build id of dev300m76
770 else if( aGenerator
.indexOf( "OpenOffice.org_project/310m" ) != -1 )
772 else if( aGenerator
.indexOf( "OpenOffice.org_project/320m" ) != -1 )
779 bool isDocumentGeneratedWithOpenOfficeOlderThan3_0( const uno::Reference
< frame::XModel
>& xChartModel
)
781 bool bResult
= isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel
);
784 OUString
aGenerator( lcl_getGeneratorFromModel(xChartModel
) );
785 if( aGenerator
.indexOf( "OpenOffice.org_project/680m" ) != -1 )
791 bool isDocumentGeneratedWithOpenOfficeOlderThan2_4( const uno::Reference
< frame::XModel
>& xChartModel
)
793 if( isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel
) )
796 if( isDocumentGeneratedWithOpenOfficeOlderThan3_0( xChartModel
) )
798 sal_Int32 nBuilId
= lcl_getBuildIDFromGenerator( lcl_getGeneratorFromModel(xChartModel
) );
799 if( nBuilId
>0 && nBuilId
<=9238 ) //9238 is build id of OpenOffice.org 2.3.1
805 bool isDocumentGeneratedWithOpenOfficeOlderThan2_3( const uno::Reference
< frame::XModel
>& xChartModel
)
807 bool bResult
= false;
808 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 if( aGenerator
.isEmpty() )
812 //if there is no meta stream at the chart object we need to check whether the parent document is OpenOffice at all
813 uno::Reference
< container::XChild
> xChild( xChartModel
, uno::UNO_QUERY
);
816 aGenerator
= lcl_getGeneratorFromModel( uno::Reference
< frame::XModel
>( xChild
->getParent(), uno::UNO_QUERY
) );
817 if( aGenerator
.indexOf( "OpenOffice.org_project" ) != -1 )
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 if( aGenerator
.indexOf( "OpenOffice.org_project/31" ) != -1 )
822 bResult
= false;//#i100102# probably generated with OOo 3.1 by the report designer
824 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
826 else if( isDocumentGeneratedWithOpenOfficeOlderThan2_0(xChartModel
) )
833 bool isDocumentGeneratedWithOpenOfficeOlderThan2_0( const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XModel
>& xChartModel
)
835 bool bResult
= false;
836 OUString
aGenerator( lcl_getGeneratorFromModelOrItsParent(xChartModel
) );
837 if( aGenerator
.startsWith( "OpenOffice.org 1" )
838 || aGenerator
.startsWith( "StarOffice 6" )
839 || aGenerator
.startsWith( "StarOffice 7" )
840 || aGenerator
.startsWith( "StarSuite 6" )
841 || aGenerator
.startsWith( "StarSuite 7" )
847 Reference
< chart2::data::XDataProvider
> getDataProviderFromParent( const Reference
< chart2::XChartDocument
>& xChartDoc
)
849 Reference
< chart2::data::XDataProvider
> xRet
;
850 uno::Reference
< container::XChild
> xChild( xChartDoc
, uno::UNO_QUERY
);
853 Reference
< lang::XMultiServiceFactory
> xFact( xChild
->getParent(), uno::UNO_QUERY
);
856 const OUString
aDataProviderServiceName( "com.sun.star.chart2.data.DataProvider");
857 const uno::Sequence
< OUString
> aServiceNames( xFact
->getAvailableServiceNames());
858 const OUString
* pBegin
= aServiceNames
.getConstArray();
859 const OUString
* pEnd
= pBegin
+ aServiceNames
.getLength();
860 if( ::std::find( pBegin
, pEnd
, aDataProviderServiceName
) != pEnd
)
862 xRet
= Reference
< chart2::data::XDataProvider
>(
863 xFact
->createInstance( aDataProviderServiceName
), uno::UNO_QUERY
);
870 } // namespace SchXMLTools
872 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */