bump product version to 5.0.4.1
[LibreOffice.git] / xmloff / source / chart / SchXMLTools.cxx
blob64304271ca044cc274537ad7fc4d621ff17c9aea
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
50 #include <algorithm>
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;
58 namespace
61 OUString lcl_getGeneratorFromModel( const uno::Reference< frame::XModel >& xChartModel )
63 OUString aGenerator;
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();
72 return aGenerator;
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 );
81 if( xChild.is() )
82 aGenerator = lcl_getGeneratorFromModel( uno::Reference< frame::XModel >( xChild->getParent(), uno::UNO_QUERY) );
84 return aGenerator;
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 );
93 if( nBegin >= 0 )
95 OUString sBuildId( rGenerator.copy( nBegin + sBuildCompare.getLength() ) );
96 nBuildId = sBuildId.toInt32();
98 return nBuildId;
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 );
107 return aResult;
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;
113 OUString aRange;
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 ));
121 return xRet;
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;
157 //static
158 const tMakeStringStringMap& lcl_getChartTypeNameMap()
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" ) )
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())
208 aNew = aIt->second;
210 return aNew;
213 OUString GetChartTypeByClassName(
214 const OUString & rClassName, bool bUseOldNames )
216 OUStringBuffer aResultBuffer;
217 bool bInternalType = false;
219 if( bUseOldNames )
220 aResultBuffer.append( "com.sun.star.chart.");
221 else
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 ))
232 if( bUseOldNames )
233 aResultBuffer.append("Bar");
234 else
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 ))
246 if( bUseOldNames )
247 aResultBuffer.append("XY");
248 else
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 ))
260 if( bUseOldNames )
261 aResultBuffer.append("Stock");
262 else
263 aResultBuffer.append("CandleStick");
265 else if( IsXMLToken( rClassName, XML_SURFACE ))
267 //@todo change this if a surface chart is available
268 if( bUseOldNames )
269 aResultBuffer.append("Bar");
270 else
271 aResultBuffer.append("Column");
273 else if (IsXMLToken(rClassName, XML_GL3DBAR))
274 aResultBuffer.append("GL3DBar");
275 else
276 bInternalType = false;
278 if( ! bInternalType )
279 return OUString();
281 if( bUseOldNames )
282 aResultBuffer.append("Diagram");
283 else
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;
296 if( bUseOldNames )
298 aPrefix = "com.sun.star.chart.";
299 aPostfix = "Diagram";
301 else
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" )
318 eResult = XML_LINE;
319 else if ( aServiceName == "Area" )
320 eResult = XML_AREA;
321 else if( aServiceName == "Bar" ||
322 (!bUseOldNames && aServiceName == "Column"))
323 eResult = XML_BAR;
324 else if ( aServiceName == "Pie" )
325 eResult = XML_CIRCLE;
326 else if ( aServiceName == "Donut" )
327 eResult = XML_RING;
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" )
334 eResult = XML_RADAR;
335 else if ( aServiceName == "FilledNet" )
336 eResult = XML_FILLED_RADAR;
337 else if( (bUseOldNames && aServiceName == "Stock") ||
338 (!bUseOldNames && aServiceName == "CandleStick"))
339 eResult = XML_STOCK;
340 else if (aServiceName == "GL3DBar")
341 eResult = XML_GL3DBAR;
345 if( eResult == XML_TOKEN_INVALID && !rChartTypeService.isEmpty() )
346 eResult = XML_ADD_IN;
348 return eResult;
351 Reference< chart2::data::XLabeledDataSequence2 > GetNewLabeledDataSequence()
353 Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
354 Reference< chart2::data::XLabeledDataSequence2 > xResult = chart2::data::LabeledDataSequence::create(xContext);
355 return xResult;
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" );
367 return xRet;
370 Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
371 if( !xDataProvider.is() )
373 SAL_WARN("xmloff.chart", "need a data provider" );
374 return xRet;
377 bool bUseInternal = false;
378 uno::Reference<beans::XPropertySet> xPropSet(xDataProvider, uno::UNO_QUERY);
379 if (xPropSet.is())
383 bool bVal = false;
384 uno::Any any = xPropSet->getPropertyValue("UseInternalDataProvider");
385 if (any >>= bVal)
386 bUseInternal = static_cast<bool>(bVal);
388 catch (const beans::UnknownPropertyException&)
390 // Do nothing
394 if (!bUseInternal)
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" );
422 return xRet;
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" );
434 return xRet;
437 Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
438 if( !xDataProvider.is() )
440 SAL_WARN("xmloff.chart", "need a data provider" );
441 return xRet;
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" );
454 return xRet;
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());
472 if( !xDia.is())
473 return;
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 ));
488 if( xAxis.is() )
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 );
500 if( xXMLConv.is())
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 )
540 uno::Any aRet;
541 if( !pPropStyleContext || !pStylesCtxt )
542 return aRet;
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;
550 if( nIdx == -1 )
551 continue;
552 OUString aPropName = rMapper->GetEntryAPIName( nIdx );
553 if(rPropertyName.equals(aPropName))
554 return aPropIter->maValue;
556 return aRet;
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 ),
563 true, false );
565 if( bConvertTabsLFs )
567 sal_Int32 nStartPos = 0;
568 sal_Int32 nEndPos = rText.getLength();
569 sal_Unicode cChar;
571 for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
573 cChar = rText[ nPos ];
574 switch( cChar )
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 ),
584 false, false );
586 break;
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 ),
596 false, false );
598 break;
601 if( nEndPos > nStartPos )
603 if( nStartPos == 0 )
604 rExport.GetDocHandler()->characters( rText );
605 else
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 ),
631 true, false );
632 SvXMLElementExport aDescription( rExport, XML_NAMESPACE_SVG,
633 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DESC ),
634 true, false );
635 rExport.GetDocHandler()->characters( rValue );
638 void setXMLRangePropertyAtDataSequence(
639 const Reference< chart2::data::XDataSequence > & xDataSequence,
640 const OUString & rXMLRange )
642 if( !xDataSequence.is())
643 return;
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());
671 bResult =
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 );
684 return bResult;
687 void copyProperties(
688 const Reference< beans::XPropertySet > & xSource,
689 const Reference< beans::XPropertySet > & xDestination )
691 if( ! (xSource.is() && xDestination.is()) )
692 return;
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() )
722 return false;
723 Reference< chart2::data::XDataProvider > xDataProviderFromParent( SchXMLTools::getDataProviderFromParent( xChartDoc ) );
724 if( !xDataProviderFromParent.is() )
725 return false;
726 uno::Reference< chart2::data::XDataReceiver > xDataReceiver( xChartDoc, uno::UNO_QUERY );
727 if( !xDataReceiver.is() )
728 return false;
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() )
737 continue;
738 Reference< chart2::data::XDataSequence > xNewSeq;
739 xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getValues(), xDataProviderFromParent );
740 if( xNewSeq.is() )
741 xLabeledSeq->setValues( xNewSeq );
742 xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getLabel(), xDataProviderFromParent );
743 if( xNewSeq.is() )
744 xLabeledSeq->setLabel( xNewSeq );
746 return true;
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 );
759 if( !bResult )
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
768 bResult= true;
770 else if( aGenerator.indexOf( "OpenOffice.org_project/310m" ) != -1 )
771 bResult= true;
772 else if( aGenerator.indexOf( "OpenOffice.org_project/320m" ) != -1 )
773 bResult= true;
776 return bResult;
779 bool isDocumentGeneratedWithOpenOfficeOlderThan3_0( const uno::Reference< frame::XModel >& xChartModel )
781 bool bResult = isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel );
782 if( !bResult )
784 OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
785 if( aGenerator.indexOf( "OpenOffice.org_project/680m" ) != -1 )
786 bResult= true;
788 return bResult;
791 bool isDocumentGeneratedWithOpenOfficeOlderThan2_4( const uno::Reference< frame::XModel >& xChartModel )
793 if( isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel ) )
794 return true;
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
800 return true;
802 return false;
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 );
814 if( xChild.is() )
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
823 else
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) )
827 bResult= true;
830 return bResult;
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" )
843 bResult= true;
844 return bResult;
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 );
851 if( xChild.is() )
853 Reference< lang::XMultiServiceFactory > xFact( xChild->getParent(), uno::UNO_QUERY );
854 if( xFact.is() )
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 );
867 return xRet;
870 } // namespace SchXMLTools
872 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */