Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / xmloff / source / chart / SchXMLTools.cxx
blob34b1a3e6b3b597b7e092ca7ad3542fccabbc201d
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 <xmloff/xmluconv.hxx>
24 #include <xmloff/xmlement.hxx>
25 #include <xmloff/xmlimppr.hxx>
26 #include <xmloff/prstylei.hxx>
27 #include <xmloff/xmlprmap.hxx>
28 #include <xmloff/xmlexp.hxx>
29 #include <xmloff/xmlnmspe.hxx>
30 #include <xmloff/xmlmetai.hxx>
31 #include <xmloff/maptype.hxx>
33 #include <com/sun/star/beans/PropertyAttribute.hpp>
34 #include <com/sun/star/uno/XComponentContext.hpp>
35 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
36 #include <com/sun/star/chart2/data/XDataProvider.hpp>
37 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
38 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
39 #include <com/sun/star/chart2/XChartDocument.hpp>
40 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
41 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
42 #include <com/sun/star/container/XChild.hpp>
43 #include <com/sun/star/document/XDocumentProperties.hpp>
44 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <com/sun/star/lang/XServiceName.hpp>
48 #include <comphelper/processfactory.hxx>
49 #include <algorithm>
50 #include <map>
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 std::map< OUString, OUString > tMakeStringStringMap;
157 //static
158 const tMakeStringStringMap& lcl_getChartTypeNameMap()
160 //shape property -- chart model object property
161 static const tMakeStringStringMap g_aChartTypeNameMap{
162 {"com.sun.star.chart.LineDiagram",
163 "com.sun.star.chart2.LineChartType"},
164 {"com.sun.star.chart.AreaDiagram",
165 "com.sun.star.chart2.AreaChartType"},
166 {"com.sun.star.chart.BarDiagram",
167 "com.sun.star.chart2.ColumnChartType"},
168 {"com.sun.star.chart.PieDiagram",
169 "com.sun.star.chart2.PieChartType"},
170 {"com.sun.star.chart.DonutDiagram",
171 "com.sun.star.chart2.DonutChartType"},
172 {"com.sun.star.chart.XYDiagram",
173 "com.sun.star.chart2.ScatterChartType"},
174 {"com.sun.star.chart.NetDiagram",
175 "com.sun.star.chart2.NetChartType"},
176 {"com.sun.star.chart.FilledNetDiagram",
177 "com.sun.star.chart2.FilledNetChartType"},
178 {"com.sun.star.chart.StockDiagram",
179 "com.sun.star.chart2.CandleStickChartType"},
180 {"com.sun.star.chart.BubbleDiagram",
181 "com.sun.star.chart2.BubbleChartType"},
182 {"com.sun.star.chart.GL3DBarDiagram",
183 "com.sun.star.chart2.GL3DBarChartType"}};
184 return g_aChartTypeNameMap;
187 OUString GetNewChartTypeName( const OUString & rOldChartTypeName )
189 OUString aNew(rOldChartTypeName);
191 const tMakeStringStringMap& rMap = lcl_getChartTypeNameMap();
192 tMakeStringStringMap::const_iterator aIt( rMap.find( rOldChartTypeName ));
193 if( aIt != rMap.end())
195 aNew = aIt->second;
197 return aNew;
200 OUString GetChartTypeByClassName(
201 const OUString & rClassName, bool bUseOldNames )
203 OUStringBuffer aResultBuffer;
204 bool bInternalType = false;
206 if( bUseOldNames )
207 aResultBuffer.append( "com.sun.star.chart.");
208 else
209 aResultBuffer.append( "com.sun.star.chart2.");
211 bInternalType = true;
213 if( IsXMLToken( rClassName, XML_LINE ))
214 aResultBuffer.append("Line");
215 else if( IsXMLToken( rClassName, XML_AREA ))
216 aResultBuffer.append("Area");
217 else if( IsXMLToken( rClassName, XML_BAR ))
219 if( bUseOldNames )
220 aResultBuffer.append("Bar");
221 else
223 aResultBuffer.append("Column");
224 // @todo: might be Bar
227 else if( IsXMLToken( rClassName, XML_CIRCLE ))
228 aResultBuffer.append("Pie");
229 else if( IsXMLToken( rClassName, XML_RING ))
230 aResultBuffer.append("Donut");
231 else if( IsXMLToken( rClassName, XML_SCATTER ))
233 if( bUseOldNames )
234 aResultBuffer.append("XY");
235 else
236 aResultBuffer.append("Scatter");
239 else if( IsXMLToken( rClassName, XML_BUBBLE ))
240 aResultBuffer.append("Bubble");
241 else if( IsXMLToken( rClassName, XML_RADAR ))
242 aResultBuffer.append("Net");
243 else if( IsXMLToken( rClassName, XML_FILLED_RADAR ))
244 aResultBuffer.append("FilledNet");
245 else if( IsXMLToken( rClassName, XML_STOCK ))
247 if( bUseOldNames )
248 aResultBuffer.append("Stock");
249 else
250 aResultBuffer.append("CandleStick");
252 else if( IsXMLToken( rClassName, XML_SURFACE ))
254 //@todo change this if a surface chart is available
255 if( bUseOldNames )
256 aResultBuffer.append("Bar");
257 else
258 aResultBuffer.append("Column");
260 else if (IsXMLToken(rClassName, XML_GL3DBAR))
261 aResultBuffer.append("GL3DBar");
262 else
263 bInternalType = false;
265 if( ! bInternalType )
266 return OUString();
268 if( bUseOldNames )
269 aResultBuffer.append("Diagram");
270 else
271 aResultBuffer.append("ChartType");
273 return aResultBuffer.makeStringAndClear();
277 XMLTokenEnum getTokenByChartType(
278 const OUString & rChartTypeService, bool bUseOldNames )
280 XMLTokenEnum eResult = XML_TOKEN_INVALID;
281 OUString aPrefix, aPostfix;
283 if( bUseOldNames )
285 aPrefix = "com.sun.star.chart.";
286 aPostfix = "Diagram";
288 else
290 aPrefix = "com.sun.star.chart2.";
291 aPostfix = "ChartType";
294 if( rChartTypeService.match( aPrefix ))
296 sal_Int32 nSkip = aPrefix.getLength();
297 SAL_WARN_IF( rChartTypeService.getLength() < nSkip, "xmloff.chart", "ChartTypeService.getLength() < nSkip" );
298 sal_Int32 nTypeLength = rChartTypeService.getLength() - nSkip - aPostfix.getLength();
299 // if postfix matches and leaves a non-empty type
300 if( nTypeLength > 0 && rChartTypeService.match( aPostfix, nSkip + nTypeLength ))
302 OUString aServiceName( rChartTypeService.copy( nSkip, nTypeLength ));
304 if ( aServiceName == "Line" )
305 eResult = XML_LINE;
306 else if ( aServiceName == "Area" )
307 eResult = XML_AREA;
308 else if( aServiceName == "Bar" ||
309 (!bUseOldNames && aServiceName == "Column"))
310 eResult = XML_BAR;
311 else if ( aServiceName == "Pie" )
312 eResult = XML_CIRCLE;
313 else if ( aServiceName == "Donut" )
314 eResult = XML_RING;
315 else if( (bUseOldNames && aServiceName == "XY") ||
316 (!bUseOldNames && aServiceName == "Scatter"))
317 eResult = XML_SCATTER;
318 else if ( aServiceName == "Bubble" )
319 eResult = XML_BUBBLE;
320 else if ( aServiceName == "Net" )
321 eResult = XML_RADAR;
322 else if ( aServiceName == "FilledNet" )
323 eResult = XML_FILLED_RADAR;
324 else if( (bUseOldNames && aServiceName == "Stock") ||
325 (!bUseOldNames && aServiceName == "CandleStick"))
326 eResult = XML_STOCK;
327 else if (aServiceName == "GL3DBar")
328 eResult = XML_GL3DBAR;
332 if( eResult == XML_TOKEN_INVALID && !rChartTypeService.isEmpty() )
333 eResult = XML_ADD_IN;
335 return eResult;
338 Reference< chart2::data::XLabeledDataSequence2 > GetNewLabeledDataSequence()
340 Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
341 Reference< chart2::data::XLabeledDataSequence2 > xResult = chart2::data::LabeledDataSequence::create(xContext);
342 return xResult;
345 Reference< chart2::data::XDataSequence > CreateDataSequence(
346 const OUString & rRange,
347 const Reference< chart2::XChartDocument >& xChartDoc )
349 Reference< chart2::data::XDataSequence > xRet;
351 if( !xChartDoc.is() )
353 SAL_WARN("xmloff.chart", "need a chart document" );
354 return xRet;
357 Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
358 if( !xDataProvider.is() )
360 SAL_WARN("xmloff.chart", "need a data provider" );
361 return xRet;
364 bool bUseInternal = false;
365 uno::Reference<beans::XPropertySet> xPropSet(xDataProvider, uno::UNO_QUERY);
366 if (xPropSet.is())
370 bool bVal = false;
371 uno::Any any = xPropSet->getPropertyValue("UseInternalDataProvider");
372 if (any >>= bVal)
373 bUseInternal = static_cast<bool>(bVal);
375 catch (const beans::UnknownPropertyException&)
377 // Do nothing
381 if (!bUseInternal)
385 xRet.set( xDataProvider->createDataSequenceByRangeRepresentation( lcl_ConvertRange( rRange, xDataProvider )));
386 SchXMLTools::setXMLRangePropertyAtDataSequence( xRet, rRange );
388 catch( const lang::IllegalArgumentException & )
390 SAL_WARN("xmloff.chart", "could not create data sequence" );
394 if( !xRet.is() && !xChartDoc->hasInternalDataProvider() && !rRange.isEmpty() )
396 //#i103911# switch to internal data in case the parent cannot provide the requested data
397 xChartDoc->createInternalDataProvider( true /* bCloneExistingData */ );
398 xDataProvider = xChartDoc->getDataProvider();
401 xRet.set( xDataProvider->createDataSequenceByRangeRepresentation( lcl_ConvertRange( rRange, xDataProvider )));
402 SchXMLTools::setXMLRangePropertyAtDataSequence( xRet, rRange );
404 catch( const lang::IllegalArgumentException & )
406 SAL_WARN("xmloff.chart", "could not create data sequence" );
409 return xRet;
412 Reference< chart2::data::XDataSequence > CreateDataSequenceWithoutConvert(
413 const OUString & rRange,
414 const Reference< chart2::XChartDocument >& xChartDoc )
416 Reference< chart2::data::XDataSequence > xRet;
418 if( !xChartDoc.is() )
420 SAL_WARN("xmloff.chart", "need a chart document" );
421 return xRet;
424 Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
425 if( !xDataProvider.is() )
427 SAL_WARN("xmloff.chart", "need a data provider" );
428 return xRet;
433 xRet.set( xDataProvider->createDataSequenceByRangeRepresentation( rRange ) );
434 SchXMLTools::setXMLRangePropertyAtDataSequence( xRet, rRange );
436 catch( const lang::IllegalArgumentException & )
438 SAL_WARN("xmloff.chart", "could not create data sequence" );
441 return xRet;
444 void CreateCategories(
445 const uno::Reference< chart2::data::XDataProvider > & xDataProvider,
446 const uno::Reference< chart2::XChartDocument > & xNewDoc,
447 const OUString & rRangeAddress,
448 sal_Int32 nCooSysIndex,
449 sal_Int32 nDimensionIndex,
450 tSchXMLLSequencesPerIndex * pLSequencesPerIndex )
454 if( xNewDoc.is() && !rRangeAddress.isEmpty())
456 if( xDataProvider.is())
458 uno::Reference< chart2::XDiagram > xDia( xNewDoc->getFirstDiagram());
459 if( !xDia.is())
460 return;
462 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDia, uno::UNO_QUERY_THROW );
463 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > >
464 aCooSysSeq( xCooSysCnt->getCoordinateSystems());
465 if( nCooSysIndex < aCooSysSeq.getLength())
467 uno::Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIndex] );
468 SAL_WARN_IF( !xCooSys.is(), "xmloff.chart", "xCooSys is NULL");
469 if( nDimensionIndex < xCooSys->getDimension() )
471 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
472 for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
474 uno::Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nI ));
475 if( xAxis.is() )
477 chart2::ScaleData aData( xAxis->getScaleData());
478 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
479 GetNewLabeledDataSequence(), uno::UNO_QUERY_THROW);
482 OUString aConvertedRange( rRangeAddress );
483 bool bRangeConverted = false;
484 if( ! (xNewDoc->hasInternalDataProvider() && aConvertedRange == "categories"))
486 Reference< chart2::data::XRangeXMLConversion > xXMLConv( xDataProvider, uno::UNO_QUERY );
487 if( xXMLConv.is())
489 aConvertedRange = xXMLConv->convertRangeFromXML( rRangeAddress );
490 bRangeConverted = true;
493 Reference< chart2::data::XDataSequence > xSeq(
494 xDataProvider->createDataSequenceByRangeRepresentation( aConvertedRange ));
495 xLabeledSeq->setValues( xSeq );
496 if( bRangeConverted )
497 setXMLRangePropertyAtDataSequence( xSeq, rRangeAddress );
499 catch( const lang::IllegalArgumentException & ex )
501 SAL_WARN("xmloff.chart", "IllegalArgumentException caught, Message: " << ex.Message );
503 aData.Categories.set( xLabeledSeq );
504 if( pLSequencesPerIndex )
506 // register for setting local data if external data provider is not present
507 pLSequencesPerIndex->insert(
508 tSchXMLLSequencesPerIndex::value_type(
509 tSchXMLIndexWithPart( SCH_XML_CATEGORIES_INDEX, SCH_XML_PART_VALUES ), xLabeledSeq ));
511 xAxis->setScaleData( aData );
519 catch( uno::Exception & )
521 SAL_WARN("xmloff.chart", "Exception caught while creating Categories" );
525 uno::Any getPropertyFromContext( const OUString& rPropertyName, const XMLPropStyleContext* pPropStyleContext, const SvXMLStylesContext* pStylesCtxt )
527 uno::Any aRet;
528 if( !pPropStyleContext || !pStylesCtxt )
529 return aRet;
530 const ::std::vector< XMLPropertyState >& rProperties = pPropStyleContext->GetProperties();
531 const rtl::Reference< XMLPropertySetMapper >& rMapper = pStylesCtxt->GetImportPropertyMapper( pPropStyleContext->GetFamily()/*XML_STYLE_FAMILY_SCH_CHART_ID*/ )->getPropertySetMapper();
532 ::std::vector< XMLPropertyState >::const_iterator aEnd( rProperties.end() );
533 ::std::vector< XMLPropertyState >::const_iterator aPropIter( rProperties.begin() );
534 for( aPropIter = rProperties.begin(); aPropIter != aEnd; ++aPropIter )
536 sal_Int32 nIdx = aPropIter->mnIndex;
537 if( nIdx == -1 )
538 continue;
539 OUString aPropName = rMapper->GetEntryAPIName( nIdx );
540 if(rPropertyName.equals(aPropName))
541 return aPropIter->maValue;
543 return aRet;
546 void exportText( SvXMLExport& rExport, const OUString& rText, bool bConvertTabsLFs )
548 SvXMLElementExport aPara( rExport, XML_NAMESPACE_TEXT,
549 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_P ),
550 true, false );
552 if( bConvertTabsLFs )
554 sal_Int32 nStartPos = 0;
555 sal_Int32 nEndPos = rText.getLength();
556 sal_Unicode cChar;
558 for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
560 cChar = rText[ nPos ];
561 switch( cChar )
563 case 0x0009: // tabulator
565 if( nPos > nStartPos )
566 rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nPos - nStartPos)) );
567 nStartPos = nPos + 1;
569 SvXMLElementExport aElem( rExport, XML_NAMESPACE_TEXT,
570 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_TAB_STOP ),
571 false, false );
573 break;
575 case 0x000A: // linefeed
577 if( nPos > nStartPos )
578 rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nPos - nStartPos)) );
579 nStartPos = nPos + 1;
581 SvXMLElementExport aElem( rExport, XML_NAMESPACE_TEXT,
582 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_LINE_BREAK ),
583 false, false );
585 break;
588 if( nEndPos > nStartPos )
590 if( nStartPos == 0 )
591 rExport.GetDocHandler()->characters( rText );
592 else
593 rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nEndPos - nStartPos)) );
596 else // do not convert tabs and linefeeds (eg for numbers coming from unit converter)
598 rExport.GetDocHandler()->characters( rText );
602 void exportRangeToSomewhere( SvXMLExport& rExport, const OUString& rValue )
604 //with issue #i366# and CWS chart20 ranges for error bars were introduced
605 //to keep them during copy paste from calc to impress for example it
606 //was necessary to introduce a mapping between the used ranges within calc and the data written to the local table
607 //this is why we write this ranges here
609 //#i113950# first the range was exported to attribute text:id, but that attribute does not allow arbitrary strings anymore within ODF 1.2
610 //as an alternative the range info is now saved into the description at an empty group element (not very nice, but ODF conform)
612 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
613 if( nCurrentODFVersion == SvtSaveOptions::ODFVER_010 || nCurrentODFVersion == SvtSaveOptions::ODFVER_011 )
614 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
616 SvXMLElementExport aEmptyShapeGroup( rExport, XML_NAMESPACE_DRAW,
617 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_G ),
618 true, false );
619 SvXMLElementExport aDescription( rExport, XML_NAMESPACE_SVG,
620 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DESC ),
621 true, false );
622 rExport.GetDocHandler()->characters( rValue );
625 void setXMLRangePropertyAtDataSequence(
626 const Reference< chart2::data::XDataSequence > & xDataSequence,
627 const OUString & rXMLRange )
629 if( !xDataSequence.is())
630 return;
633 const OUString aXMLRangePropName( "CachedXMLRange" );
634 Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
635 Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
636 if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ))
637 xProp->setPropertyValue( aXMLRangePropName, uno::makeAny( rXMLRange ));
639 catch( const uno::Exception & ex )
641 SAL_WARN("xmloff.chart", "Exception caught, Message: " << ex.Message );
645 bool getXMLRangePropertyFromDataSequence(
646 const Reference< chart2::data::XDataSequence > & xDataSequence,
647 OUString & rOutXMLRange,
648 bool bClearProp /* = false */)
650 bool bResult = false;
651 if( xDataSequence.is())
655 const OUString aXMLRangePropName( "CachedXMLRange" );
656 Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
657 Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
658 bResult =
659 ( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ) &&
660 ( xProp->getPropertyValue( aXMLRangePropName ) >>= rOutXMLRange ) &&
661 !rOutXMLRange.isEmpty());
662 // clear the property after usage
663 if( bClearProp && bResult )
664 xProp->setPropertyValue( aXMLRangePropName, uno::Any( OUString()));
666 catch( const uno::Exception & ex )
668 SAL_WARN("xmloff.chart", "Exception caught, Message: " << ex.Message );
671 return bResult;
674 void copyProperties(
675 const Reference< beans::XPropertySet > & xSource,
676 const Reference< beans::XPropertySet > & xDestination )
678 if( ! (xSource.is() && xDestination.is()) )
679 return;
683 Reference< beans::XPropertySetInfo > xSrcInfo( xSource->getPropertySetInfo(), uno::UNO_QUERY_THROW );
684 Reference< beans::XPropertySetInfo > xDestInfo( xDestination->getPropertySetInfo(), uno::UNO_QUERY_THROW );
685 Sequence< beans::Property > aProperties( xSrcInfo->getProperties());
686 const sal_Int32 nLength = aProperties.getLength();
687 for( sal_Int32 i = 0; i < nLength; ++i )
689 OUString aName( aProperties[i].Name);
690 if( xDestInfo->hasPropertyByName( aName ))
692 beans::Property aProp( xDestInfo->getPropertyByName( aName ));
693 if( (aProp.Attributes & beans::PropertyAttribute::READONLY) == 0 )
694 xDestination->setPropertyValue(
695 aName, xSource->getPropertyValue( aName ));
699 catch( const uno::Exception & )
701 SAL_WARN("xmloff.chart", "Copying property sets failed!" );
705 bool switchBackToDataProviderFromParent( const Reference< chart2::XChartDocument >& xChartDoc, const tSchXMLLSequencesPerIndex & rLSequencesPerIndex )
707 //return whether the switch is successful
708 if( !xChartDoc.is() || !xChartDoc->hasInternalDataProvider() )
709 return false;
710 Reference< chart2::data::XDataProvider > xDataProviderFromParent( SchXMLTools::getDataProviderFromParent( xChartDoc ) );
711 if( !xDataProviderFromParent.is() )
712 return false;
713 uno::Reference< chart2::data::XDataReceiver > xDataReceiver( xChartDoc, uno::UNO_QUERY );
714 if( !xDataReceiver.is() )
715 return false;
717 xDataReceiver->attachDataProvider( xDataProviderFromParent );
719 for( tSchXMLLSequencesPerIndex::const_iterator aLSeqIt( rLSequencesPerIndex.begin() );
720 aLSeqIt != rLSequencesPerIndex.end(); ++aLSeqIt )
722 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( aLSeqIt->second );
723 if( !xLabeledSeq.is() )
724 continue;
725 Reference< chart2::data::XDataSequence > xNewSeq;
726 xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getValues(), xDataProviderFromParent );
727 if( xNewSeq.is() )
728 xLabeledSeq->setValues( xNewSeq );
729 xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getLabel(), xDataProviderFromParent );
730 if( xNewSeq.is() )
731 xLabeledSeq->setLabel( xNewSeq );
733 return true;
736 void setBuildIDAtImportInfo( const uno::Reference< frame::XModel >& xModel, const Reference< beans::XPropertySet >& xImportInfo )
738 OUString aGenerator( lcl_getGeneratorFromModelOrItsParent(xModel) );
739 if( !aGenerator.isEmpty() )
740 SvXMLMetaDocumentContext::setBuildId( aGenerator, xImportInfo );
743 bool isDocumentGeneratedWithOpenOfficeOlderThan3_3( const uno::Reference< frame::XModel >& xChartModel )
745 bool bResult = isDocumentGeneratedWithOpenOfficeOlderThan3_0( xChartModel );
746 if( !bResult )
748 OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
749 if( aGenerator.indexOf( "OpenOffice.org_project/3" ) != -1 )
751 if( aGenerator.indexOf( "OpenOffice.org_project/300m" ) != -1 )
753 sal_Int32 nBuilId = lcl_getBuildIDFromGenerator( lcl_getGeneratorFromModel(xChartModel) );
754 if( nBuilId>0 && nBuilId<9491 ) //9491 is build id of dev300m76
755 bResult= true;
757 else if( aGenerator.indexOf( "OpenOffice.org_project/310m" ) != -1 )
758 bResult= true;
759 else if( aGenerator.indexOf( "OpenOffice.org_project/320m" ) != -1 )
760 bResult= true;
763 return bResult;
766 bool isDocumentGeneratedWithOpenOfficeOlderThan3_0( const uno::Reference< frame::XModel >& xChartModel )
768 bool bResult = isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel );
769 if( !bResult )
771 OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
772 if( aGenerator.indexOf( "OpenOffice.org_project/680m" ) != -1 )
773 bResult= true;
775 return bResult;
778 bool isDocumentGeneratedWithOpenOfficeOlderThan2_4( const uno::Reference< frame::XModel >& xChartModel )
780 if( isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel ) )
781 return true;
783 if( isDocumentGeneratedWithOpenOfficeOlderThan3_0( xChartModel ) )
785 sal_Int32 nBuilId = lcl_getBuildIDFromGenerator( lcl_getGeneratorFromModel(xChartModel) );
786 if( nBuilId>0 && nBuilId<=9238 ) //9238 is build id of OpenOffice.org 2.3.1
787 return true;
789 return false;
792 bool isDocumentGeneratedWithOpenOfficeOlderThan2_3( const uno::Reference< frame::XModel >& xChartModel )
794 bool bResult = false;
795 OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
796 //if there is a meta stream at the chart object it was not written with an older OpenOffice version < 2.3
797 if( aGenerator.isEmpty() )
799 //if there is no meta stream at the chart object we need to check whether the parent document is OpenOffice at all
800 uno::Reference< container::XChild > xChild( xChartModel, uno::UNO_QUERY );
801 if( xChild.is() )
803 aGenerator = lcl_getGeneratorFromModel( uno::Reference< frame::XModel >( xChild->getParent(), uno::UNO_QUERY) );
804 if( aGenerator.indexOf( "OpenOffice.org_project" ) != -1 )
806 //the chart application has not created files without a meta stream since OOo 2.3 (OOo 2.3 has written a metastream already)
807 //only the report builder extension has created some files with OOo 3.1 that do not have a meta stream
808 if( aGenerator.indexOf( "OpenOffice.org_project/31" ) != -1 )
809 bResult = false;//#i100102# probably generated with OOo 3.1 by the report designer
810 else
811 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
813 else if( isDocumentGeneratedWithOpenOfficeOlderThan2_0(xChartModel) )
814 bResult= true;
817 return bResult;
820 bool isDocumentGeneratedWithOpenOfficeOlderThan2_0( const css::uno::Reference< css::frame::XModel >& xChartModel)
822 bool bResult = false;
823 OUString aGenerator( lcl_getGeneratorFromModelOrItsParent(xChartModel) );
824 if( aGenerator.startsWith( "OpenOffice.org 1" )
825 || aGenerator.startsWith( "StarOffice 6" )
826 || aGenerator.startsWith( "StarOffice 7" )
827 || aGenerator.startsWith( "StarSuite 6" )
828 || aGenerator.startsWith( "StarSuite 7" )
830 bResult= true;
831 return bResult;
834 Reference< chart2::data::XDataProvider > getDataProviderFromParent( const Reference< chart2::XChartDocument >& xChartDoc )
836 Reference< chart2::data::XDataProvider > xRet;
837 uno::Reference< container::XChild > xChild( xChartDoc, uno::UNO_QUERY );
838 if( xChild.is() )
840 Reference< lang::XMultiServiceFactory > xFact( xChild->getParent(), uno::UNO_QUERY );
841 if( xFact.is() )
843 const OUString aDataProviderServiceName( "com.sun.star.chart2.data.DataProvider");
844 const uno::Sequence< OUString > aServiceNames( xFact->getAvailableServiceNames());
845 const OUString * pBegin = aServiceNames.getConstArray();
846 const OUString * pEnd = pBegin + aServiceNames.getLength();
847 if( ::std::find( pBegin, pEnd, aDataProviderServiceName ) != pEnd )
849 xRet.set( xFact->createInstance( aDataProviderServiceName ), uno::UNO_QUERY );
853 return xRet;
856 } // namespace SchXMLTools
858 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */