1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_xmloff.hxx" 26 27 #include "SchXMLTools.hxx" 28 29 /* 30 #include <tools/debug.hxx> 31 */ 32 #include <rtl/ustrbuf.hxx> 33 #include <comphelper/InlineContainer.hxx> 34 // header for class SvXMLUnitConverter 35 #include <xmloff/xmluconv.hxx> 36 // header for struct SvXMLEnumMapEntry 37 #include <xmloff/xmlement.hxx> 38 // header for define __FAR_DATA 39 #include <tools/solar.h> 40 41 // header for class SvXMLImportPropertyMapper 42 #include <xmloff/xmlimppr.hxx> 43 // header for class XMLPropStyleContext 44 #include <xmloff/prstylei.hxx> 45 // header for class XMLPropertySetMapper 46 #include <xmloff/xmlprmap.hxx> 47 #include <xmloff/xmlexp.hxx> 48 #include "xmloff/xmlnmspe.hxx" 49 #include <xmloff/xmlmetai.hxx> 50 51 #include <com/sun/star/beans/PropertyAttribute.hpp> 52 #include <com/sun/star/uno/XComponentContext.hpp> 53 #include <com/sun/star/chart2/data/XDataProvider.hpp> 54 #include <com/sun/star/chart2/data/XDataReceiver.hpp> 55 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp> 56 #include <com/sun/star/chart2/XChartDocument.hpp> 57 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> 58 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp> 59 #include <com/sun/star/container/XChild.hpp> 60 #include <com/sun/star/document/XDocumentProperties.hpp> 61 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> 62 #include <com/sun/star/lang/XServiceName.hpp> 63 64 #include <comphelper/processfactory.hxx> 65 66 using namespace com::sun::star; 67 using namespace ::xmloff::token; 68 69 using ::rtl::OUString; 70 using ::rtl::OUStringBuffer; 71 using ::com::sun::star::uno::Reference; 72 using ::com::sun::star::uno::Sequence; 73 74 namespace 75 { 76 Reference< uno::XComponentContext > lcl_getComponentContext() 77 { 78 Reference< uno::XComponentContext > xContext; 79 try 80 { 81 Reference< beans::XPropertySet > xFactProp( comphelper::getProcessServiceFactory(), uno::UNO_QUERY ); 82 if( xFactProp.is()) 83 xFactProp->getPropertyValue(OUString::createFromAscii("DefaultContext")) >>= xContext; 84 } 85 catch( uno::Exception& ) 86 {} 87 88 return xContext; 89 } 90 91 rtl::OUString lcl_getGeneratorFromModel( const uno::Reference< frame::XModel >& xChartModel ) 92 { 93 ::rtl::OUString aGenerator; 94 uno::Reference< document::XDocumentPropertiesSupplier> xChartDocumentPropertiesSupplier( xChartModel, uno::UNO_QUERY ); 95 if( xChartDocumentPropertiesSupplier.is() ) 96 { 97 uno::Reference< document::XDocumentProperties > xChartDocumentProperties( 98 xChartDocumentPropertiesSupplier->getDocumentProperties()); 99 if( xChartDocumentProperties.is() ) 100 aGenerator = xChartDocumentProperties->getGenerator(); 101 } 102 return aGenerator; 103 } 104 105 rtl::OUString lcl_getGeneratorFromModelOrItsParent( const uno::Reference< frame::XModel >& xChartModel ) 106 { 107 ::rtl::OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) ); 108 if( !aGenerator.getLength() ) //try to get the missing info from the parent document 109 { 110 uno::Reference< container::XChild > xChild( xChartModel, uno::UNO_QUERY ); 111 if( xChild.is() ) 112 aGenerator = lcl_getGeneratorFromModel( uno::Reference< frame::XModel >( xChild->getParent(), uno::UNO_QUERY) ); 113 } 114 return aGenerator; 115 } 116 117 sal_Int32 lcl_getBuildIDFromGenerator( const ::rtl::OUString& rGenerator ) 118 { 119 //returns -1 if nothing found 120 sal_Int32 nBuildId = -1; 121 const OUString sBuildCompare( RTL_CONSTASCII_USTRINGPARAM( "$Build-" ) ); 122 sal_Int32 nEnd = -1; 123 sal_Int32 nBegin = rGenerator.indexOf( sBuildCompare, nEnd ); 124 if( nBegin != -1 ) 125 { 126 OUString sBuildId( rGenerator.copy( nBegin + sBuildCompare.getLength() ) ); 127 nBuildId = sBuildId.toInt32(); 128 } 129 return nBuildId; 130 } 131 132 OUString lcl_ConvertRange( const ::rtl::OUString & rRange, const Reference< chart2::data::XDataProvider >& xDataProvider ) 133 { 134 OUString aResult = rRange; 135 Reference< chart2::data::XRangeXMLConversion > xRangeConversion( xDataProvider, uno::UNO_QUERY ); 136 if( xRangeConversion.is()) 137 aResult = xRangeConversion->convertRangeFromXML( rRange ); 138 return aResult; 139 } 140 141 Reference< chart2::data::XDataSequence > lcl_createNewSequenceFromCachedXMLRange( const Reference< chart2::data::XDataSequence >& xSeq, const Reference< chart2::data::XDataProvider >& xDataProvider ) 142 { 143 Reference< chart2::data::XDataSequence > xRet; 144 OUString aRange; 145 if( xSeq.is() && SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq, aRange, /* bClearProp = */ true ) ) 146 { 147 xRet.set( xDataProvider->createDataSequenceByRangeRepresentation( 148 lcl_ConvertRange( aRange, xDataProvider )) ); 149 SchXMLTools::copyProperties( Reference< beans::XPropertySet >( xSeq, uno::UNO_QUERY ), 150 Reference< beans::XPropertySet >( xRet, uno::UNO_QUERY )); 151 } 152 return xRet; 153 } 154 155 } // anonymous namespace 156 157 // ---------------------------------------- 158 159 namespace SchXMLTools 160 { 161 162 static __FAR_DATA SvXMLEnumMapEntry aXMLChartClassMap[] = 163 { 164 { XML_LINE, XML_CHART_CLASS_LINE }, 165 { XML_AREA, XML_CHART_CLASS_AREA }, 166 { XML_CIRCLE, XML_CHART_CLASS_CIRCLE }, 167 { XML_RING, XML_CHART_CLASS_RING }, 168 { XML_SCATTER, XML_CHART_CLASS_SCATTER }, 169 { XML_RADAR, XML_CHART_CLASS_RADAR }, 170 { XML_FILLED_RADAR, XML_CHART_CLASS_FILLED_RADAR }, 171 { XML_BAR, XML_CHART_CLASS_BAR }, 172 { XML_STOCK, XML_CHART_CLASS_STOCK }, 173 { XML_BUBBLE, XML_CHART_CLASS_BUBBLE }, 174 { XML_SURFACE, XML_CHART_CLASS_BAR }, //@todo change this if a surface chart is available 175 { XML_ADD_IN, XML_CHART_CLASS_ADDIN }, 176 { XML_TOKEN_INVALID, XML_CHART_CLASS_UNKNOWN } 177 }; 178 179 SchXMLChartTypeEnum GetChartTypeEnum( const OUString& rClassName ) 180 { 181 sal_uInt16 nEnumVal = XML_CHART_CLASS_UNKNOWN; 182 if( !SvXMLUnitConverter::convertEnum( 183 nEnumVal, rClassName, aXMLChartClassMap ) ) 184 nEnumVal = XML_CHART_CLASS_UNKNOWN; 185 return SchXMLChartTypeEnum(nEnumVal); 186 } 187 188 typedef ::comphelper::MakeMap< ::rtl::OUString, ::rtl::OUString > tMakeStringStringMap; 189 //static 190 const tMakeStringStringMap& lcl_getChartTypeNameMap() 191 { 192 //shape property -- chart model object property 193 static tMakeStringStringMap g_aChartTypeNameMap = 194 tMakeStringStringMap 195 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.LineDiagram" ) 196 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.LineChartType" ) ) 197 198 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.AreaDiagram" ) 199 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.AreaChartType" ) ) 200 201 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.BarDiagram" ) 202 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.ColumnChartType" ) ) 203 204 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.PieDiagram" ) 205 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.PieChartType" ) ) 206 207 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.DonutDiagram" ) 208 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.DonutChartType" ) ) 209 210 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.XYDiagram" ) 211 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.ScatterChartType" ) ) 212 213 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.NetDiagram" ) 214 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.NetChartType" ) ) 215 216 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.FilledNetDiagram" ) 217 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.FilledNetChartType" ) ) 218 219 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.StockDiagram" ) 220 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.CandleStickChartType" ) ) 221 222 ( ::rtl::OUString::createFromAscii( "com.sun.star.chart.BubbleDiagram" ) 223 , ::rtl::OUString::createFromAscii( "com.sun.star.chart2.BubbleChartType" ) ) 224 225 ; 226 return g_aChartTypeNameMap; 227 } 228 229 230 OUString GetNewChartTypeName( const OUString & rOldChartTypeName ) 231 { 232 OUString aNew(rOldChartTypeName); 233 234 const tMakeStringStringMap& rMap = lcl_getChartTypeNameMap(); 235 tMakeStringStringMap::const_iterator aIt( rMap.find( rOldChartTypeName )); 236 if( aIt != rMap.end()) 237 { 238 aNew = aIt->second; 239 } 240 return aNew; 241 } 242 243 OUString GetChartTypeByClassName( 244 const OUString & rClassName, bool bUseOldNames ) 245 { 246 OUStringBuffer aResultBuffer; 247 bool bInternalType = false; 248 249 if( bUseOldNames ) 250 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart.")); 251 else 252 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.")); 253 254 bInternalType = true; 255 256 if( IsXMLToken( rClassName, XML_LINE )) 257 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Line")); 258 else if( IsXMLToken( rClassName, XML_AREA )) 259 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Area")); 260 else if( IsXMLToken( rClassName, XML_BAR )) 261 { 262 if( bUseOldNames ) 263 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Bar")); 264 else 265 { 266 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Column")); 267 // @todo: might be Bar 268 } 269 } 270 else if( IsXMLToken( rClassName, XML_CIRCLE )) 271 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Pie")); 272 else if( IsXMLToken( rClassName, XML_RING )) 273 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Donut")); 274 else if( IsXMLToken( rClassName, XML_SCATTER )) 275 { 276 if( bUseOldNames ) 277 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("XY")); 278 else 279 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Scatter")); 280 } 281 282 else if( IsXMLToken( rClassName, XML_BUBBLE )) 283 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Bubble")); 284 else if( IsXMLToken( rClassName, XML_RADAR )) 285 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Net")); 286 else if( IsXMLToken( rClassName, XML_FILLED_RADAR )) 287 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("FilledNet")); 288 else if( IsXMLToken( rClassName, XML_STOCK )) 289 { 290 if( bUseOldNames ) 291 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Stock")); 292 else 293 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("CandleStick")); 294 } 295 else if( IsXMLToken( rClassName, XML_SURFACE )) 296 { 297 //@todo change this if a surface chart is available 298 if( bUseOldNames ) 299 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Bar")); 300 else 301 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Column")); 302 } 303 else 304 bInternalType = false; 305 306 if( ! bInternalType ) 307 return OUString(); 308 309 if( bUseOldNames ) 310 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("Diagram")); 311 else 312 aResultBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM("ChartType")); 313 314 return aResultBuffer.makeStringAndClear(); 315 316 } 317 318 XMLTokenEnum getTokenByChartType( 319 const OUString & rChartTypeService, bool bUseOldNames ) 320 { 321 XMLTokenEnum eResult = XML_TOKEN_INVALID; 322 OUString aPrefix, aPostfix; 323 324 if( bUseOldNames ) 325 { 326 aPrefix = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.chart.")); 327 aPostfix = OUString( RTL_CONSTASCII_USTRINGPARAM("Diagram")); 328 } 329 else 330 { 331 aPrefix = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.chart2.")); 332 aPostfix = OUString( RTL_CONSTASCII_USTRINGPARAM("ChartType")); 333 } 334 335 if( rChartTypeService.match( aPrefix )) 336 { 337 sal_Int32 nSkip = aPrefix.getLength(); 338 OSL_ASSERT( rChartTypeService.getLength() >= nSkip ); 339 sal_Int32 nTypeLength = rChartTypeService.getLength() - nSkip - aPostfix.getLength(); 340 // if postfix matches and leaves a non-empty type 341 if( nTypeLength > 0 && rChartTypeService.match( aPostfix, nSkip + nTypeLength )) 342 { 343 OUString aServiceName( rChartTypeService.copy( nSkip, nTypeLength )); 344 345 if( aServiceName.equalsAscii("Line")) 346 eResult = XML_LINE; 347 else if( aServiceName.equalsAscii("Area")) 348 eResult = XML_AREA; 349 else if( aServiceName.equalsAscii("Bar") || 350 (!bUseOldNames && aServiceName.equalsAscii("Column"))) 351 eResult = XML_BAR; 352 else if( aServiceName.equalsAscii("Pie")) 353 eResult = XML_CIRCLE; 354 else if( aServiceName.equalsAscii("Donut")) 355 eResult = XML_RING; 356 else if( (bUseOldNames && aServiceName.equalsAscii("XY")) || 357 (!bUseOldNames && aServiceName.equalsAscii("Scatter"))) 358 eResult = XML_SCATTER; 359 else if( aServiceName.equalsAscii("Bubble")) 360 eResult = XML_BUBBLE; 361 else if( aServiceName.equalsAscii("Net")) 362 eResult = XML_RADAR; 363 else if( aServiceName.equalsAscii("FilledNet")) 364 eResult = XML_FILLED_RADAR; 365 else if( (bUseOldNames && aServiceName.equalsAscii("Stock")) || 366 (!bUseOldNames && aServiceName.equalsAscii("CandleStick"))) 367 eResult = XML_STOCK; 368 } 369 } 370 371 if( eResult == XML_TOKEN_INVALID && rChartTypeService.getLength() > 0 ) 372 eResult = XML_ADD_IN; 373 374 return eResult; 375 } 376 377 Reference< chart2::data::XLabeledDataSequence > GetNewLabeledDataSequence() 378 { 379 Reference< chart2::data::XLabeledDataSequence > xResult; 380 Reference< uno::XComponentContext > xContext( lcl_getComponentContext()); 381 if( xContext.is() ) 382 xResult.set( 383 xContext->getServiceManager()->createInstanceWithContext( 384 OUString::createFromAscii("com.sun.star.chart2.data.LabeledDataSequence"), 385 xContext ), uno::UNO_QUERY_THROW ); 386 return xResult; 387 } 388 389 Reference< chart2::data::XDataSequence > CreateDataSequence( 390 const OUString & rRange, 391 const Reference< chart2::XChartDocument >& xChartDoc ) 392 { 393 Reference< chart2::data::XDataSequence > xRet; 394 395 if( !xChartDoc.is() ) 396 { 397 DBG_ERROR( "need a chart document" ); 398 return xRet; 399 } 400 401 Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() ); 402 if( !xDataProvider.is() ) 403 { 404 DBG_ERROR( "need a data provider" ); 405 return xRet; 406 } 407 408 try 409 { 410 xRet.set( xDataProvider->createDataSequenceByRangeRepresentation( lcl_ConvertRange( rRange, xDataProvider ))); 411 SchXMLTools::setXMLRangePropertyAtDataSequence( xRet, rRange ); 412 } 413 catch( const lang::IllegalArgumentException & ) 414 { 415 DBG_ERROR( "could not create data sequence" ); 416 } 417 418 if( !xRet.is() && !xChartDoc->hasInternalDataProvider() && rRange.getLength() ) 419 { 420 //#i103911# switch to internal data in case the parent cannot provide the requested data 421 xChartDoc->createInternalDataProvider( sal_True /* bCloneExistingData */ ); 422 xDataProvider = xChartDoc->getDataProvider(); 423 try 424 { 425 xRet.set( xDataProvider->createDataSequenceByRangeRepresentation( lcl_ConvertRange( rRange, xDataProvider ))); 426 SchXMLTools::setXMLRangePropertyAtDataSequence( xRet, rRange ); 427 } 428 catch( const lang::IllegalArgumentException & ) 429 { 430 DBG_ERROR( "could not create data sequence" ); 431 } 432 } 433 return xRet; 434 } 435 436 void CreateCategories( 437 const uno::Reference< chart2::data::XDataProvider > & xDataProvider, 438 const uno::Reference< chart2::XChartDocument > & xNewDoc, 439 const OUString & rRangeAddress, 440 sal_Int32 nCooSysIndex, 441 sal_Int32 nDimensionIndex, 442 tSchXMLLSequencesPerIndex * pLSequencesPerIndex ) 443 { 444 try 445 { 446 if( xNewDoc.is() && rRangeAddress.getLength()) 447 { 448 if( xDataProvider.is()) 449 { 450 uno::Reference< chart2::XDiagram > xDia( xNewDoc->getFirstDiagram()); 451 if( !xDia.is()) 452 return; 453 454 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDia, uno::UNO_QUERY_THROW ); 455 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > 456 aCooSysSeq( xCooSysCnt->getCoordinateSystems()); 457 if( nCooSysIndex < aCooSysSeq.getLength()) 458 { 459 uno::Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIndex] ); 460 OSL_ASSERT( xCooSys.is()); 461 if( nDimensionIndex < xCooSys->getDimension() ) 462 { 463 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex); 464 for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI) 465 { 466 uno::Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nI )); 467 if( xAxis.is() ) 468 { 469 chart2::ScaleData aData( xAxis->getScaleData()); 470 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( 471 GetNewLabeledDataSequence()); 472 try 473 { 474 OUString aConvertedRange( rRangeAddress ); 475 bool bRangeConverted = false; 476 if( ! (xNewDoc->hasInternalDataProvider() && 477 aConvertedRange.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("categories")))) 478 { 479 Reference< chart2::data::XRangeXMLConversion > xXMLConv( xDataProvider, uno::UNO_QUERY ); 480 if( xXMLConv.is()) 481 { 482 aConvertedRange = xXMLConv->convertRangeFromXML( rRangeAddress ); 483 bRangeConverted = true; 484 } 485 } 486 Reference< chart2::data::XDataSequence > xSeq( 487 xDataProvider->createDataSequenceByRangeRepresentation( aConvertedRange )); 488 xLabeledSeq->setValues( xSeq ); 489 if( bRangeConverted ) 490 setXMLRangePropertyAtDataSequence( xSeq, rRangeAddress ); 491 } 492 catch( const lang::IllegalArgumentException & ex ) 493 { 494 (void)ex; // avoid warning for pro build 495 OSL_ENSURE( false, ::rtl::OUStringToOString( 496 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IllegalArgumentException caught, Message: " )) + 497 ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr()); 498 } 499 aData.Categories.set( xLabeledSeq ); 500 if( pLSequencesPerIndex ) 501 { 502 // register for setting local data if external data provider is not present 503 pLSequencesPerIndex->insert( 504 tSchXMLLSequencesPerIndex::value_type( 505 tSchXMLIndexWithPart( SCH_XML_CATEGORIES_INDEX, SCH_XML_PART_VALUES ), xLabeledSeq )); 506 } 507 xAxis->setScaleData( aData ); 508 } 509 } 510 } 511 } 512 } 513 } 514 } 515 catch( uno::Exception & ) 516 { 517 OSL_ENSURE( false, "Exception caught while creating Categories" ); 518 } 519 } 520 521 522 uno::Any getPropertyFromContext( const rtl::OUString& rPropertyName, const XMLPropStyleContext* pPropStyleContext, const SvXMLStylesContext* pStylesCtxt ) 523 { 524 uno::Any aRet; 525 if( !pPropStyleContext || !pStylesCtxt ) 526 return aRet; 527 const ::std::vector< XMLPropertyState >& rProperties = pPropStyleContext->GetProperties(); 528 const UniReference< XMLPropertySetMapper >& rMapper = pStylesCtxt->GetImportPropertyMapper( pPropStyleContext->GetFamily()/*XML_STYLE_FAMILY_SCH_CHART_ID*/ )->getPropertySetMapper(); 529 ::std::vector< XMLPropertyState >::const_iterator aEnd( rProperties.end() ); 530 ::std::vector< XMLPropertyState >::const_iterator aPropIter( rProperties.begin() ); 531 for( aPropIter = rProperties.begin(); aPropIter != aEnd; ++aPropIter ) 532 { 533 sal_Int32 nIdx = aPropIter->mnIndex; 534 if( nIdx == -1 ) 535 continue; 536 OUString aPropName = rMapper->GetEntryAPIName( nIdx ); 537 if(rPropertyName.equals(aPropName)) 538 return aPropIter->maValue; 539 } 540 return aRet; 541 } 542 543 void exportText( SvXMLExport& rExport, const OUString& rText, bool bConvertTabsLFs ) 544 { 545 SvXMLElementExport aPara( rExport, XML_NAMESPACE_TEXT, 546 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_P ), 547 sal_True, sal_False ); 548 549 if( bConvertTabsLFs ) 550 { 551 sal_Int32 nStartPos = 0; 552 sal_Int32 nEndPos = rText.getLength(); 553 sal_Unicode cChar; 554 555 for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ ) 556 { 557 cChar = rText[ nPos ]; 558 switch( cChar ) 559 { 560 case 0x0009: // tabulator 561 { 562 if( nPos > nStartPos ) 563 rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nPos - nStartPos)) ); 564 nStartPos = nPos + 1; 565 566 SvXMLElementExport aElem( rExport, XML_NAMESPACE_TEXT, 567 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_TAB_STOP ), 568 sal_False, sal_False ); 569 } 570 break; 571 572 case 0x000A: // linefeed 573 { 574 if( nPos > nStartPos ) 575 rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nPos - nStartPos)) ); 576 nStartPos = nPos + 1; 577 578 SvXMLElementExport aElem( rExport, XML_NAMESPACE_TEXT, 579 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_LINE_BREAK ), 580 sal_False, sal_False ); 581 } 582 break; 583 } 584 } 585 if( nEndPos > nStartPos ) 586 { 587 if( nStartPos == 0 ) 588 rExport.GetDocHandler()->characters( rText ); 589 else 590 rExport.GetDocHandler()->characters( rText.copy( nStartPos, (nEndPos - nStartPos)) ); 591 } 592 } 593 else // do not convert tabs and linefeeds (eg for numbers coming from unit converter) 594 { 595 rExport.GetDocHandler()->characters( rText ); 596 } 597 } 598 599 void exportRangeToSomewhere( SvXMLExport& rExport, const ::rtl::OUString& rValue ) 600 { 601 //with issue #i366# and CWS chart20 ranges for error bars were introduced 602 //to keep them during copy paste from calc to impress for example it 603 //was necessary to introduce a mapping between the used ranges within calc and the data written to the local table 604 //this is why we write this ranges here 605 606 //#i113950# first the range was exported to attribute text:id, but that attribute does not allow arbitrary strings anymore within ODF 1.2 607 //as an alternative the range info is now saved into the description at an empty group element (not very nice, but ODF conform) 608 609 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() ); 610 if( nCurrentODFVersion == SvtSaveOptions::ODFVER_010 || nCurrentODFVersion == SvtSaveOptions::ODFVER_011 ) 611 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 612 613 SvXMLElementExport aEmptyShapeGroup( rExport, XML_NAMESPACE_DRAW, 614 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_G ), 615 sal_True, sal_False ); 616 SvXMLElementExport aDescription( rExport, XML_NAMESPACE_SVG, 617 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DESC ), 618 sal_True, sal_False ); 619 rExport.GetDocHandler()->characters( rValue ); 620 } 621 622 Reference< chart2::XRegressionCurve > getRegressionCurve( 623 const Reference< chart2::XDataSeries > & xDataSeries ) 624 { 625 Reference< chart2::XRegressionCurve > xResult; 626 627 Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( xDataSeries, uno::UNO_QUERY ); 628 if( xRegCurveCnt.is()) 629 { 630 // find equation properties of first regression curve 631 Sequence< Reference< chart2::XRegressionCurve > > aCurveSeq( 632 xRegCurveCnt->getRegressionCurves() ); 633 for( sal_Int32 nI=0; nI<aCurveSeq.getLength(); ++nI ) 634 { 635 // skip mean-value line 636 Reference< lang::XServiceName > xServiceName( aCurveSeq[nI], uno::UNO_QUERY ); 637 if( xServiceName.is()) 638 { 639 OUString aServiceName( xServiceName->getServiceName()); 640 if( aServiceName.equalsAsciiL( 641 RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.MeanValueRegressionCurve" ))) 642 continue; 643 } 644 // take first non-empty curve 645 if( aCurveSeq[nI].is()) 646 { 647 xResult.set( aCurveSeq[nI] ); 648 break; 649 } 650 } 651 } 652 return xResult; 653 } 654 655 void setXMLRangePropertyAtDataSequence( 656 const Reference< chart2::data::XDataSequence > & xDataSequence, 657 const OUString & rXMLRange ) 658 { 659 if( !xDataSequence.is()) 660 return; 661 try 662 { 663 const OUString aXMLRangePropName( RTL_CONSTASCII_USTRINGPARAM( "CachedXMLRange" )); 664 Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW ); 665 Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo()); 666 if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName )) 667 xProp->setPropertyValue( aXMLRangePropName, uno::makeAny( rXMLRange )); 668 } 669 catch( const uno::Exception & ex ) 670 { 671 (void)ex; // avoid warning for pro build 672 OSL_ENSURE( false, ::rtl::OUStringToOString( 673 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught, Message: " )) + 674 ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr()); 675 } 676 } 677 678 bool getXMLRangePropertyFromDataSequence( 679 const Reference< chart2::data::XDataSequence > & xDataSequence, 680 OUString & rOutXMLRange, 681 bool bClearProp /* = false */) 682 { 683 bool bResult = false; 684 if( xDataSequence.is()) 685 { 686 try 687 { 688 const OUString aXMLRangePropName( RTL_CONSTASCII_USTRINGPARAM( "CachedXMLRange" )); 689 Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW ); 690 Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo()); 691 bResult = 692 ( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ) && 693 ( xProp->getPropertyValue( aXMLRangePropName ) >>= rOutXMLRange ) && 694 rOutXMLRange.getLength()); 695 // clear the property after usage 696 if( bClearProp && bResult ) 697 xProp->setPropertyValue( aXMLRangePropName, uno::Any( OUString())); 698 } 699 catch( const uno::Exception & ex ) 700 { 701 (void)ex; // avoid warning for pro build 702 OSL_ENSURE( false, ::rtl::OUStringToOString( 703 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught, Message: " )) + 704 ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr()); 705 } 706 } 707 return bResult; 708 } 709 710 void copyProperties( 711 const Reference< beans::XPropertySet > & xSource, 712 const Reference< beans::XPropertySet > & xDestination ) 713 { 714 if( ! (xSource.is() && xDestination.is()) ) 715 return; 716 717 try 718 { 719 Reference< beans::XPropertySetInfo > xSrcInfo( xSource->getPropertySetInfo(), uno::UNO_QUERY_THROW ); 720 Reference< beans::XPropertySetInfo > xDestInfo( xDestination->getPropertySetInfo(), uno::UNO_QUERY_THROW ); 721 Sequence< beans::Property > aProperties( xSrcInfo->getProperties()); 722 const sal_Int32 nLength = aProperties.getLength(); 723 for( sal_Int32 i = 0; i < nLength; ++i ) 724 { 725 OUString aName( aProperties[i].Name); 726 if( xDestInfo->hasPropertyByName( aName )) 727 { 728 beans::Property aProp( xDestInfo->getPropertyByName( aName )); 729 if( (aProp.Attributes & beans::PropertyAttribute::READONLY) == 0 ) 730 xDestination->setPropertyValue( 731 aName, xSource->getPropertyValue( aName )); 732 } 733 } 734 } 735 catch( const uno::Exception & ) 736 { 737 OSL_ENSURE( false, "Copying property sets failed!" ); 738 } 739 } 740 741 bool switchBackToDataProviderFromParent( const Reference< chart2::XChartDocument >& xChartDoc, const tSchXMLLSequencesPerIndex & rLSequencesPerIndex ) 742 { 743 //return whether the switch is successful 744 if( !xChartDoc.is() || !xChartDoc->hasInternalDataProvider() ) 745 return false; 746 Reference< chart2::data::XDataProvider > xDataProviderFromParent( SchXMLTools::getDataProviderFromParent( xChartDoc ) ); 747 if( !xDataProviderFromParent.is() ) 748 return false; 749 uno::Reference< chart2::data::XDataReceiver > xDataReceiver( xChartDoc, uno::UNO_QUERY ); 750 if( !xDataReceiver.is() ) 751 return false; 752 753 xDataReceiver->attachDataProvider( xDataProviderFromParent ); 754 755 for( tSchXMLLSequencesPerIndex::const_iterator aLSeqIt( rLSequencesPerIndex.begin() ); 756 aLSeqIt != rLSequencesPerIndex.end(); ++aLSeqIt ) 757 { 758 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( aLSeqIt->second ); 759 if( !xLabeledSeq.is() ) 760 continue; 761 Reference< chart2::data::XDataSequence > xNewSeq; 762 xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getValues(), xDataProviderFromParent ); 763 if( xNewSeq.is() ) 764 xLabeledSeq->setValues( xNewSeq ); 765 xNewSeq = lcl_createNewSequenceFromCachedXMLRange( xLabeledSeq->getLabel(), xDataProviderFromParent ); 766 if( xNewSeq.is() ) 767 xLabeledSeq->setLabel( xNewSeq ); 768 } 769 return true; 770 } 771 772 void setBuildIDAtImportInfo( uno::Reference< frame::XModel > xModel, Reference< beans::XPropertySet > xImportInfo ) 773 { 774 ::rtl::OUString aGenerator( lcl_getGeneratorFromModelOrItsParent(xModel) ); 775 if( aGenerator.getLength() ) 776 SvXMLMetaDocumentContext::setBuildId( aGenerator, xImportInfo ); 777 } 778 779 bool isDocumentGeneratedWithOpenOfficeOlderThan3_3( const uno::Reference< frame::XModel >& xChartModel ) 780 { 781 bool bResult = isDocumentGeneratedWithOpenOfficeOlderThan3_0( xChartModel ); 782 if( !bResult ) 783 { 784 ::rtl::OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) ); 785 if( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org_project/3") ) ) != -1 ) 786 { 787 if( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org_project/300m") ) ) != -1 ) 788 { 789 sal_Int32 nBuilId = lcl_getBuildIDFromGenerator( lcl_getGeneratorFromModel(xChartModel) ); 790 if( nBuilId>0 && nBuilId<9491 ) //9491 is build id of dev300m76 791 bResult= true; 792 } 793 else if( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org_project/310m") ) ) != -1 ) 794 bResult= true; 795 else if( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org_project/320m") ) ) != -1 ) 796 bResult= true; 797 } 798 } 799 return bResult; 800 } 801 802 bool isDocumentGeneratedWithOpenOfficeOlderThan3_0( const uno::Reference< frame::XModel >& xChartModel ) 803 { 804 bool bResult = isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel ); 805 if( !bResult ) 806 { 807 ::rtl::OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) ); 808 if( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org_project/680m") ) ) != -1 ) 809 bResult= true; 810 } 811 return bResult; 812 } 813 814 bool isDocumentGeneratedWithOpenOfficeOlderThan2_4( const uno::Reference< frame::XModel >& xChartModel ) 815 { 816 if( isDocumentGeneratedWithOpenOfficeOlderThan2_3( xChartModel ) ) 817 return true; 818 819 if( isDocumentGeneratedWithOpenOfficeOlderThan3_0( xChartModel ) ) 820 { 821 sal_Int32 nBuilId = lcl_getBuildIDFromGenerator( lcl_getGeneratorFromModel(xChartModel) ); 822 if( nBuilId>0 && nBuilId<=9238 ) //9238 is build id of OpenOffice.org 2.3.1 823 return true; 824 } 825 return false; 826 } 827 828 bool isDocumentGeneratedWithOpenOfficeOlderThan2_3( const uno::Reference< frame::XModel >& xChartModel ) 829 { 830 bool bResult = false; 831 ::rtl::OUString aGenerator( lcl_getGeneratorFromModel(xChartModel) ); 832 //if there is a meta stream at the chart object it was not written with an older OpenOffice version < 2.3 833 if( !aGenerator.getLength() ) 834 { 835 //if there is no meta stream at the chart object we need to check whether the parent document is OpenOffice at all 836 uno::Reference< container::XChild > xChild( xChartModel, uno::UNO_QUERY ); 837 if( xChild.is() ) 838 { 839 aGenerator = lcl_getGeneratorFromModel( uno::Reference< frame::XModel >( xChild->getParent(), uno::UNO_QUERY) ); 840 if( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org_project") ) ) != -1 ) 841 { 842 //the chart application has not created files without a meta stream since OOo 2.3 (OOo 2.3 has written a metastream already) 843 //only the report builder extension has created some files with OOo 3.1 that do not have a meta stream 844 if( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org_project/31") ) ) != -1 ) 845 bResult = false;//#i100102# probably generated with OOo 3.1 by the report designer 846 else 847 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 848 } 849 else if( isDocumentGeneratedWithOpenOfficeOlderThan2_0(xChartModel) ) 850 bResult= true; 851 } 852 } 853 return bResult; 854 } 855 856 bool isDocumentGeneratedWithOpenOfficeOlderThan2_0( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xChartModel) 857 { 858 bool bResult = false; 859 ::rtl::OUString aGenerator( lcl_getGeneratorFromModelOrItsParent(xChartModel) ); 860 if( ( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("OpenOffice.org 1") ) ) == 0 ) 861 || ( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("StarOffice 6") ) ) == 0 ) 862 || ( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("StarOffice 7") ) ) == 0 ) 863 || ( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("StarSuite 6") ) ) == 0 ) 864 || ( aGenerator.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("StarSuite 7") ) ) == 0 ) 865 ) 866 bResult= true; 867 return bResult; 868 } 869 870 Reference< chart2::data::XDataProvider > getDataProviderFromParent( const Reference< chart2::XChartDocument >& xChartDoc ) 871 { 872 Reference< chart2::data::XDataProvider > xRet; 873 uno::Reference< container::XChild > xChild( xChartDoc, uno::UNO_QUERY ); 874 if( xChild.is() ) 875 { 876 Reference< lang::XMultiServiceFactory > xFact( xChild->getParent(), uno::UNO_QUERY ); 877 if( xFact.is() ) 878 { 879 const OUString aDataProviderServiceName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.chart2.data.DataProvider")); 880 const uno::Sequence< OUString > aServiceNames( xFact->getAvailableServiceNames()); 881 const OUString * pBegin = aServiceNames.getConstArray(); 882 const OUString * pEnd = pBegin + aServiceNames.getLength(); 883 if( ::std::find( pBegin, pEnd, aDataProviderServiceName ) != pEnd ) 884 { 885 xRet = Reference< chart2::data::XDataProvider >( 886 xFact->createInstance( aDataProviderServiceName ), uno::UNO_QUERY ); 887 } 888 } 889 } 890 return xRet; 891 } 892 893 } // namespace SchXMLTools 894