fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / xmloff / source / chart / SchXMLTools.cxx
blobcc6a796b340fbe04e172d8e6807de9151db4f5cb
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 .
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;
63 namespace
66 OUString lcl_getGeneratorFromModel( const uno::Reference< frame::XModel >& xChartModel )
68 OUString aGenerator;
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();
77 return aGenerator;
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 );
86 if( xChild.is() )
87 aGenerator = lcl_getGeneratorFromModel( uno::Reference< frame::XModel >( xChild->getParent(), uno::UNO_QUERY) );
89 return aGenerator;
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 );
98 if( nBegin >= 0 )
100 OUString sBuildId( rGenerator.copy( nBegin + sBuildCompare.getLength() ) );
101 nBuildId = sBuildId.toInt32();
103 return nBuildId;
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 );
112 return aResult;
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;
118 OUString aRange;
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 ));
126 return xRet;
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;
163 //static
164 const tMakeStringStringMap& lcl_getChartTypeNameMap()
166 //shape property -- chart model object property
167 static tMakeStringStringMap g_aChartTypeNameMap =
168 tMakeStringStringMap
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())
212 aNew = aIt->second;
214 return aNew;
217 OUString GetChartTypeByClassName(
218 const OUString & rClassName, bool bUseOldNames )
220 OUStringBuffer aResultBuffer;
221 bool bInternalType = false;
223 if( bUseOldNames )
224 aResultBuffer.append( "com.sun.star.chart.");
225 else
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 ))
236 if( bUseOldNames )
237 aResultBuffer.append("Bar");
238 else
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 ))
250 if( bUseOldNames )
251 aResultBuffer.append("XY");
252 else
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 ))
264 if( bUseOldNames )
265 aResultBuffer.append("Stock");
266 else
267 aResultBuffer.append("CandleStick");
269 else if( IsXMLToken( rClassName, XML_SURFACE ))
271 //@todo change this if a surface chart is available
272 if( bUseOldNames )
273 aResultBuffer.append("Bar");
274 else
275 aResultBuffer.append("Column");
277 else
278 bInternalType = false;
280 if( ! bInternalType )
281 return OUString();
283 if( bUseOldNames )
284 aResultBuffer.append("Diagram");
285 else
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;
298 if( bUseOldNames )
300 aPrefix = OUString( "com.sun.star.chart.");
301 aPostfix = OUString( "Diagram");
303 else
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" )
320 eResult = XML_LINE;
321 else if ( aServiceName == "Area" )
322 eResult = XML_AREA;
323 else if( aServiceName == "Bar" ||
324 (!bUseOldNames && aServiceName == "Column"))
325 eResult = XML_BAR;
326 else if ( aServiceName == "Pie" )
327 eResult = XML_CIRCLE;
328 else if ( aServiceName == "Donut" )
329 eResult = XML_RING;
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" )
336 eResult = XML_RADAR;
337 else if ( aServiceName == "FilledNet" )
338 eResult = XML_FILLED_RADAR;
339 else if( (bUseOldNames && aServiceName == "Stock") ||
340 (!bUseOldNames && aServiceName == "CandleStick"))
341 eResult = XML_STOCK;
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 sal_Bool bVal = sal_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 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());
440 if( !xDia.is())
441 return;
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 ));
456 if( xAxis.is() )
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 );
468 if( xXMLConv.is())
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 )
509 uno::Any aRet;
510 if( !pPropStyleContext || !pStylesCtxt )
511 return aRet;
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;
519 if( nIdx == -1 )
520 continue;
521 OUString aPropName = rMapper->GetEntryAPIName( nIdx );
522 if(rPropertyName.equals(aPropName))
523 return aPropIter->maValue;
525 return aRet;
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();
538 sal_Unicode cChar;
540 for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
542 cChar = rText[ nPos ];
543 switch( cChar )
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 );
555 break;
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 );
567 break;
570 if( nEndPos > nStartPos )
572 if( nStartPos == 0 )
573 rExport.GetDocHandler()->characters( rText );
574 else
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" )
626 continue;
628 // take first non-empty curve
629 if( aCurveSeq[nI].is())
631 xResult.set( aCurveSeq[nI] );
632 break;
636 return xResult;
639 void setXMLRangePropertyAtDataSequence(
640 const Reference< chart2::data::XDataSequence > & xDataSequence,
641 const OUString & rXMLRange )
643 if( !xDataSequence.is())
644 return;
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());
672 bResult =
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 );
685 return bResult;
688 void copyProperties(
689 const Reference< beans::XPropertySet > & xSource,
690 const Reference< beans::XPropertySet > & xDestination )
692 if( ! (xSource.is() && xDestination.is()) )
693 return;
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() )
723 return false;
724 Reference< chart2::data::XDataProvider > xDataProviderFromParent( SchXMLTools::getDataProviderFromParent( xChartDoc ) );
725 if( !xDataProviderFromParent.is() )
726 return false;
727 uno::Reference< chart2::data::XDataReceiver > xDataReceiver( xChartDoc, uno::UNO_QUERY );
728 if( !xDataReceiver.is() )
729 return false;
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() )
738 continue;
739 Reference< chart2::data::XDataSequence > xNewSeq;
740 xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getValues(), xDataProviderFromParent );
741 if( xNewSeq.is() )
742 xLabeledSeq->setValues( xNewSeq );
743 xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getLabel(), xDataProviderFromParent );
744 if( xNewSeq.is() )
745 xLabeledSeq->setLabel( xNewSeq );
747 return true;
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 );
760 if( !bResult )
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
769 bResult= true;
771 else if( aGenerator.indexOf( "OpenOffice.org_project/310m" ) != -1 )
772 bResult= true;
773 else if( aGenerator.indexOf( "OpenOffice.org_project/320m" ) != -1 )
774 bResult= true;
777 return bResult;
780 bool isDocumentGeneratedWithOpenOfficeOlderThan3_0( const uno::Reference< frame::XModel >& xChartModel )
782 bool bResult = isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel );
783 if( !bResult )
785 OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) );
786 if( aGenerator.indexOf( "OpenOffice.org_project/680m" ) != -1 )
787 bResult= true;
789 return bResult;
792 bool isDocumentGeneratedWithOpenOfficeOlderThan2_4( const uno::Reference< frame::XModel >& xChartModel )
794 if( isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel ) )
795 return true;
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
801 return true;
803 return false;
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 );
815 if( xChild.is() )
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
824 else
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) )
828 bResult= true;
831 return bResult;
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 )
844 bResult= true;
845 return bResult;
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 );
852 if( xChild.is() )
854 Reference< lang::XMultiServiceFactory > xFact( xChild->getParent(), uno::UNO_QUERY );
855 if( xFact.is() )
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 );
868 return xRet;
871 } // namespace SchXMLTools
873 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */