LibreOffice Module xmloff (master)  1
SchXMLChartContext.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include "SchXMLChartContext.hxx"
21 #include <SchXMLImport.hxx>
22 #include "SchXMLLegendContext.hxx"
25 #include "SchXMLTableContext.hxx"
26 #include "SchXMLSeries2Context.hxx"
27 #include "SchXMLTools.hxx"
28 #include <osl/diagnose.h>
29 #include <sal/log.hxx>
30 #include <tools/diagnose_ex.h>
32 #include <xmloff/xmlnamespace.hxx>
33 #include <xmloff/xmltoken.hxx>
34 #include <xmloff/namespacemap.hxx>
35 #include <xmloff/xmluconv.hxx>
36 #include <xmloff/xmlstyle.hxx>
38 
39 #include <vector>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/chart/XChartDocument.hpp>
42 #include <com/sun/star/chart/XDiagram.hpp>
43 #include <com/sun/star/xml/sax/XAttributeList.hpp>
44 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
45 #include <com/sun/star/drawing/XDrawPage.hpp>
46 #include <com/sun/star/chart/ChartDataRowSource.hpp>
47 #include <com/sun/star/embed/Aspects.hpp>
48 #include <com/sun/star/embed/XVisualObject.hpp>
49 
50 #include <com/sun/star/chart2/XChartDocument.hpp>
51 #include <com/sun/star/chart2/data/XDataSink.hpp>
52 #include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
53 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
54 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
55 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
56 #include <com/sun/star/chart2/XTitled.hpp>
57 
58 #include <com/sun/star/container/XChild.hpp>
59 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
60 
61 using namespace com::sun::star;
62 using namespace ::xmloff::token;
64 using namespace ::SchXMLTools;
65 
66 namespace
67 {
68 
69 void lcl_setRoleAtLabeledSequence(
70  const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq,
71  const OUString &rRole )
72 {
73  // set role of sequence
74  uno::Reference< chart2::data::XDataSequence > xValues( xLSeq->getValues());
75  if( xValues.is())
76  {
77  uno::Reference< beans::XPropertySet > xProp( xValues, uno::UNO_QUERY );
78  if( xProp.is())
79  xProp->setPropertyValue("Role", uno::makeAny( rRole ));
80  }
81 }
82 
83 void lcl_MoveDataToCandleStickSeries(
84  const uno::Reference< chart2::data::XDataSource > & xDataSource,
85  const uno::Reference< chart2::XDataSeries > & xDestination,
86  const OUString & rRole )
87 {
88  try
89  {
90  uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq(
91  xDataSource->getDataSequences());
92  if( aLabeledSeq.hasElements())
93  {
94  lcl_setRoleAtLabeledSequence( aLabeledSeq[0], rRole );
95 
96  // add to data series
97  uno::Reference< chart2::data::XDataSource > xSource( xDestination, uno::UNO_QUERY_THROW );
98  // @todo: realloc only once outside this function
99  uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aData( xSource->getDataSequences());
100  aData.realloc( aData.getLength() + 1);
101  aData[ aData.getLength() - 1 ] = aLabeledSeq[0];
102  uno::Reference< chart2::data::XDataSink > xSink( xDestination, uno::UNO_QUERY_THROW );
103  xSink->setData( aData );
104  }
105  }
106  catch(const uno::Exception&)
107  {
108  TOOLS_WARN_EXCEPTION("xmloff.chart", "Exception caught while moving data to candlestick series" );
109  }
110 }
111 
112 void lcl_setRoleAtFirstSequence(
113  const uno::Reference< chart2::XDataSeries > & xSeries,
114  const OUString & rRole )
115 {
116  uno::Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
117  if( xSource.is())
118  {
119  uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
120  if( aSeq.hasElements())
121  lcl_setRoleAtLabeledSequence( aSeq[0], rRole );
122  }
123 }
124 
125 void lcl_removeEmptyChartTypeGroups( const uno::Reference< chart2::XChartDocument > & xDoc )
126 {
127  if( ! xDoc.is())
128  return;
129 
130  uno::Reference< chart2::XDiagram > xDia( xDoc->getFirstDiagram());
131  if( ! xDia.is())
132  return;
133 
134  try
135  {
136  // count all charttype groups to be able to leave at least one
137  sal_Int32 nRemainingGroups = 0;
138  uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDia, uno::UNO_QUERY_THROW );
139  const uno::Sequence< uno::Reference< chart2::XCoordinateSystem > >
140  aCooSysSeq( xCooSysCnt->getCoordinateSystems());
141  for( auto const & i : aCooSysSeq )
142  {
143  uno::Reference< chart2::XChartTypeContainer > xCTCnt( i, uno::UNO_QUERY_THROW );
144  nRemainingGroups += xCTCnt->getChartTypes().getLength();
145  }
146 
147  // delete all empty groups, but leave at least group (empty or not)
148  for( sal_Int32 nI = aCooSysSeq.getLength(); nI-- && (nRemainingGroups > 1); )
149  {
150  uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nI], uno::UNO_QUERY_THROW );
151  uno::Sequence< uno::Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
152  for( sal_Int32 nJ=aCTSeq.getLength(); nJ-- && (nRemainingGroups > 1); )
153  {
154  uno::Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nJ], uno::UNO_QUERY_THROW );
155  if( !xDSCnt->getDataSeries().hasElements() )
156  {
157  // note: iterator stays valid as we have a local sequence
158  xCTCnt->removeChartType( aCTSeq[nJ] );
159  --nRemainingGroups;
160  }
161  }
162  }
163  }
164  catch(const uno::Exception&)
165  {
166  TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught while removing empty chart types");
167  }
168 }
169 
170 uno::Sequence< sal_Int32 > lcl_getNumberSequenceFromString( const OUString& rStr, bool bAddOneToEachOldIndex )
171 {
172  const sal_Unicode aSpace( ' ' );
173 
174  // count number of entries
175  ::std::vector< sal_Int32 > aVec;
176  sal_Int32 nLastPos = 0;
177  sal_Int32 nPos = 0;
178  while( nPos != -1 )
179  {
180  nPos = rStr.indexOf( aSpace, nLastPos );
181  if( nPos > nLastPos )
182  {
183  aVec.push_back( rStr.copy( nLastPos, (nPos - nLastPos) ).toInt32() );
184  }
185  if( nPos != -1 )
186  nLastPos = nPos + 1;
187  }
188  // last entry
189  if( nLastPos != 0 &&
190  rStr.getLength() > nLastPos )
191  {
192  aVec.push_back( rStr.copy( nLastPos ).toInt32() );
193  }
194 
195  const sal_Int32 nVecSize = aVec.size();
196  uno::Sequence< sal_Int32 > aSeq( nVecSize );
197 
198  if(!bAddOneToEachOldIndex)
199  {
200  sal_Int32* pSeqArr = aSeq.getArray();
201  for( nPos = 0; nPos < nVecSize; ++nPos )
202  {
203  pSeqArr[ nPos ] = aVec[ nPos ];
204  }
205  }
206  else if( bAddOneToEachOldIndex )
207  {
208  aSeq.realloc( nVecSize+1 );
209  aSeq[0]=0;
210 
211  sal_Int32* pSeqArr = aSeq.getArray();
212  for( nPos = 0; nPos < nVecSize; ++nPos )
213  {
214  pSeqArr[ nPos+1 ] = aVec[ nPos ]+1;
215  }
216  }
217 
218  return aSeq;
219 }
220 
221 } // anonymous namespace
222 
224  SvXMLImport& rImport, const OUString& rLocalName ) :
225  SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
226  mrImportHelper( rImpHelper ),
227  m_bHasRangeAtPlotArea( false ),
228  m_bHasTableElement( false ),
229  mbAllRangeAddressesAvailable( true ),
230  mbColHasLabels( false ),
231  mbRowHasLabels( false ),
232  meDataRowSource( chart::ChartDataRowSource_COLUMNS ),
233  mbIsStockChart( false )
234 {
235 }
236 
238 {}
239 
240 static bool lcl_hasServiceName(Reference<lang::XMultiServiceFactory> const & xFactory, OUString const & rServiceName)
241 {
242  const uno::Sequence<OUString> aServiceNames(xFactory->getAvailableServiceNames());
243 
244  return std::find(aServiceNames.begin(), aServiceNames.end(), rServiceName) != aServiceNames.end();
245 }
246 
247 static void lcl_setDataProvider(uno::Reference<chart2::XChartDocument> const & xChartDoc, OUString const & sDataPilotSource)
248 {
249  if (!xChartDoc.is())
250  return;
251 
252  try
253  {
254  uno::Reference<container::XChild> xChild(xChartDoc, uno::UNO_QUERY);
255  uno::Reference<chart2::data::XDataReceiver> xDataReceiver(xChartDoc, uno::UNO_QUERY);
256  if (xChild.is() && xDataReceiver.is())
257  {
258  bool bHasOwnData = true;
259 
260  Reference<lang::XMultiServiceFactory> xFact(xChild->getParent(), uno::UNO_QUERY);
261  if (xFact.is())
262  {
263  if (!xChartDoc->getDataProvider().is())
264  {
265  bool bHasDataPilotSource = !sDataPilotSource.isEmpty();
266  OUString aDataProviderServiceName("com.sun.star.chart2.data.DataProvider");
267  if (bHasDataPilotSource)
268  aDataProviderServiceName = "com.sun.star.chart2.data.PivotTableDataProvider";
269 
270  if (lcl_hasServiceName(xFact, aDataProviderServiceName))
271  {
272  Reference<chart2::data::XDataProvider> xProvider(xFact->createInstance(aDataProviderServiceName), uno::UNO_QUERY);
273 
274  if (xProvider.is())
275  {
276  if (bHasDataPilotSource)
277  {
278  Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(xProvider, uno::UNO_QUERY);
279  xPivotTableDataProvider->setPivotTableName(sDataPilotSource);
280  xDataReceiver->attachDataProvider(xProvider);
281  bHasOwnData = !xPivotTableDataProvider->hasPivotTable();
282  }
283  else
284  {
285  xDataReceiver->attachDataProvider(xProvider);
286  bHasOwnData = false;
287  }
288  }
289  }
290  }
291  else
292  bHasOwnData = false;
293  }
294  // else we have no parent => we have our own data
295 
296  if (bHasOwnData && ! xChartDoc->hasInternalDataProvider())
297  xChartDoc->createInternalDataProvider(false);
298  }
299  }
300  catch (const uno::Exception &)
301  {
302  TOOLS_INFO_EXCEPTION("xmloff.chart", "SchXMLChartContext::StartElement()");
303  }
304 }
305 
306 void SchXMLChartContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
307 {
308  // parse attributes
309  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
310  const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetChartAttrTokenMap();
311 
312  uno::Reference< embed::XVisualObject > xVisualObject( mrImportHelper.GetChartDocument(), uno::UNO_QUERY);
313  SAL_WARN_IF(!xVisualObject.is(), "xmloff.chart", "need xVisualObject for page size");
314  if( xVisualObject.is() )
315  maChartSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); //#i103460# take the size given from the parent frame as default
316 
317  OUString sAutoStyleName;
318  OUString aOldChartTypeName;
319  bool bHasAddin = false;
320 
321  for( sal_Int16 i = 0; i < nAttrCount; i++ )
322  {
323  OUString sAttrName = xAttrList->getNameByIndex( i );
324  OUString aLocalName;
325  OUString aValue = xAttrList->getValueByIndex( i );
326  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
327 
328  switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
329  {
331  msDataPilotSource = aValue;
332  break;
333  case XML_TOK_CHART_HREF:
335  break;
336  case XML_TOK_CHART_CLASS:
337  {
338  OUString sClassName;
339  sal_uInt16 nClassPrefix =
341  aValue, &sClassName );
342  if( XML_NAMESPACE_CHART == nClassPrefix )
343  {
344  SchXMLChartTypeEnum eChartTypeEnum = SchXMLTools::GetChartTypeEnum( sClassName );
345  if( eChartTypeEnum != XML_CHART_CLASS_UNKNOWN )
346  {
347  aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( sClassName, true /* bUseOldNames */ );
348  maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( sClassName, false /* bUseOldNames */ );
349  switch( eChartTypeEnum )
350  {
352  mbIsStockChart = true;
353  break;
354  default:
355  break;
356  }
357  }
358  }
359  else if( XML_NAMESPACE_OOO == nClassPrefix )
360  {
361  // service is taken from add-in-name attribute
362  bHasAddin = true;
363 
364  aOldChartTypeName = sClassName;
365  maChartTypeServiceName = sClassName;
366  }
367  }
368  break;
369 
370  case XML_TOK_CHART_WIDTH:
372  maChartSize.Width, aValue );
373  break;
374 
377  maChartSize.Height, aValue );
378  break;
379 
381  sAutoStyleName = aValue;
382  break;
383 
385  msColTrans = aValue;
386  break;
388  msRowTrans = aValue;
389  break;
390  }
391  }
392 
393  uno::Reference<chart::XChartDocument> xDoc = mrImportHelper.GetChartDocument();
394  uno::Reference<chart2::XChartDocument> xNewDoc(xDoc, uno::UNO_QUERY);
395 
397 
398  if( aOldChartTypeName.isEmpty() )
399  {
400  SAL_WARN("xmloff.chart", "need a charttype to create a diagram" );
401  //set a fallback value:
402  const OUString& aChartClass_Bar( GetXMLToken(XML_BAR ) );
403  aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, true /* bUseOldNames */ );
404  maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, false /* bUseOldNames */ );
405  }
406 
407  // Set the size of the draw page.
408  if( xVisualObject.is() )
409  xVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, maChartSize );
410 
411  InitChart( aOldChartTypeName);
412 
413  if( bHasAddin )
414  {
415  //correct charttype service name when having an addin
416  //and don't refresh addin during load
417  uno::Reference< beans::XPropertySet > xDocProp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
418  if( xDocProp.is() )
419  {
420  try
421  {
422  xDocProp->getPropertyValue("BaseDiagram") >>= aOldChartTypeName;
424  xDocProp->setPropertyValue("RefreshAddInAllowed", uno::makeAny( false) );
425  }
426  catch(const uno::Exception&)
427  {
428  TOOLS_WARN_EXCEPTION("xmloff.chart", "Exception during import SchXMLChartContext::StartElement" );
429  }
430  }
431  }
432 
433  // set auto-styles for Area
434  uno::Reference<beans::XPropertySet> xProp = mrImportHelper.GetChartDocument()->getArea();
435  mrImportHelper.FillAutoStyle(sAutoStyleName, xProp);
436 }
437 
438 namespace
439 {
440 
441 struct NewDonutSeries
442 {
443  css::uno::Reference< css::chart2::XDataSeries > m_xSeries;
444  OUString msStyleName;
445  sal_Int32 mnAttachedAxis;
446 
447  ::std::vector< OUString > m_aSeriesStyles;
448  ::std::vector< OUString > m_aPointStyles;
449 
450  NewDonutSeries( const css::uno::Reference< css::chart2::XDataSeries >& xSeries, sal_Int32 nPointCount )
451  : m_xSeries( xSeries )
452  , mnAttachedAxis( 1 )
453  {
454  m_aPointStyles.resize(nPointCount);
455  m_aSeriesStyles.resize(nPointCount);
456  }
457 
458  void setSeriesStyleNameToPoint( const OUString& rStyleName, sal_Int32 nPointIndex )
459  {
460  SAL_WARN_IF(nPointIndex >= static_cast<sal_Int32>(m_aSeriesStyles.size()), "xmloff.chart", "donut point <-> series count mismatch");
461  if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
462  m_aSeriesStyles[nPointIndex]=rStyleName;
463  }
464 
465  void setPointStyleNameToPoint( const OUString& rStyleName, sal_Int32 nPointIndex )
466  {
467  SAL_WARN_IF(nPointIndex >= static_cast<sal_Int32>(m_aPointStyles.size()), "xmloff.chart", "donut point <-> series count mismatch");
468  if( nPointIndex < static_cast<sal_Int32>(m_aPointStyles.size()) )
469  m_aPointStyles[nPointIndex]=rStyleName;
470  }
471 
472  ::std::vector< DataRowPointStyle > creatStyleVector()
473  {
474  ::std::vector< DataRowPointStyle > aRet;
475 
477  , m_xSeries, -1, 1, msStyleName, mnAttachedAxis );
478  aRet.push_back( aSeriesStyle );
479 
480  sal_Int32 nPointIndex=0;
481  for (auto const& pointStyle : m_aPointStyles)
482  {
484  , m_xSeries, nPointIndex, 1, pointStyle, mnAttachedAxis );
485  if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
486  {
487  aPointStyle.msSeriesStyleNameForDonuts = m_aSeriesStyles[nPointIndex];
488  }
489  if( !aPointStyle.msSeriesStyleNameForDonuts.isEmpty()
490  || !aPointStyle.msStyleName.isEmpty() )
491  aRet.push_back( aPointStyle );
492  ++nPointIndex;
493  }
494 
495  return aRet;
496  }
497 };
498 
499 void lcl_swapPointAndSeriesStylesForDonutCharts( ::std::vector< DataRowPointStyle >& rStyleVector
500  , const ::std::map< css::uno::Reference< css::chart2::XDataSeries> , sal_Int32 >& rSeriesMap )
501 {
502  //detect old series count
503  //and add old series to aSeriesMap
504  ::std::map< css::uno::Reference<
505  css::chart2::XDataSeries >, sal_Int32 > aSeriesMap(rSeriesMap);
506  sal_Int32 nOldSeriesCount = 0;
507  {
508  sal_Int32 nMaxOldSeriesIndex = 0;
509  sal_Int32 nOldSeriesIndex = 0;
510  for (auto const& style : rStyleVector)
511  {
512  DataRowPointStyle aStyle(style);
513  if(aStyle.meType == DataRowPointStyle::DATA_SERIES &&
514  aStyle.m_xSeries.is() )
515  {
516  nMaxOldSeriesIndex = nOldSeriesIndex;
517 
518  if( aSeriesMap.end() == aSeriesMap.find(aStyle.m_xSeries) )
519  aSeriesMap[aStyle.m_xSeries] = nOldSeriesIndex;
520 
521  nOldSeriesIndex++;
522  }
523  }
524  nOldSeriesCount = nMaxOldSeriesIndex+1;
525  }
526 
527  //initialize new series styles
528  ::std::map< Reference< chart2::XDataSeries >, sal_Int32 >::const_iterator aSeriesMapEnd( aSeriesMap.end() );
529 
530  //sort by index
531  ::std::vector< NewDonutSeries > aNewSeriesVector;
532  {
533  ::std::map< sal_Int32, Reference< chart2::XDataSeries > > aIndexSeriesMap;
534  for (auto const& series : aSeriesMap)
535  aIndexSeriesMap[series.second] = series.first;
536 
537  for (auto const& indexSeries : aIndexSeriesMap)
538  aNewSeriesVector.emplace_back(indexSeries.second,nOldSeriesCount );
539  }
540 
541  //overwrite attached axis information according to old series styles
542  for (auto const& style : rStyleVector)
543  {
544  DataRowPointStyle aStyle(style);
545  if(aStyle.meType == DataRowPointStyle::DATA_SERIES )
546  {
547  auto aSeriesMapIt = aSeriesMap.find( aStyle.m_xSeries );
548  if( aSeriesMapIt != aSeriesMapEnd && aSeriesMapIt->second < static_cast<sal_Int32>(aNewSeriesVector.size()) )
549  aNewSeriesVector[aSeriesMapIt->second].mnAttachedAxis = aStyle.mnAttachedAxis;
550  }
551  }
552 
553  //overwrite new series style names with old series style name information
554  for (auto const& style : rStyleVector)
555  {
556  DataRowPointStyle aStyle(style);
557  if( aStyle.meType == DataRowPointStyle::DATA_SERIES )
558  {
559  auto aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
560  if( aSeriesMapEnd != aSeriesMapIt )
561  {
562  sal_Int32 nNewPointIndex = aSeriesMapIt->second;
563 
564  for (auto & newSeries : aNewSeriesVector)
565  newSeries.setSeriesStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
566  }
567  }
568  }
569 
570  //overwrite new series style names with point style name information
571  for (auto const& style : rStyleVector)
572  {
573  DataRowPointStyle aStyle(style);
574  if( aStyle.meType == DataRowPointStyle::DATA_POINT )
575  {
576  auto aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
577  if( aSeriesMapEnd != aSeriesMapIt )
578  {
579  sal_Int32 nNewPointIndex = aSeriesMapIt->second;
580  sal_Int32 nNewSeriesIndex = aStyle.m_nPointIndex;
581  sal_Int32 nRepeatCount = aStyle.m_nPointRepeat;
582 
583  while( nRepeatCount && (nNewSeriesIndex>=0) && (nNewSeriesIndex< static_cast<sal_Int32>(aNewSeriesVector.size()) ) )
584  {
585  NewDonutSeries& rNewSeries( aNewSeriesVector[nNewSeriesIndex] );
586  rNewSeries.setPointStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
587 
588  nRepeatCount--;
589  nNewSeriesIndex++;
590  }
591  }
592  }
593  }
594 
595  //put information from aNewSeriesVector to output parameter rStyleVector
596  rStyleVector.clear();
597 
598  for (auto & newSeries : aNewSeriesVector)
599  {
600  ::std::vector< DataRowPointStyle > aVector( newSeries.creatStyleVector() );
601  rStyleVector.insert(rStyleVector.end(),aVector.begin(),aVector.end());
602  }
603 }
604 
605 bool lcl_SpecialHandlingForDonutChartNeeded(
606  const OUString & rServiceName,
607  const SvXMLImport & rImport )
608 {
609  bool bResult = false;
610  if( rServiceName == "com.sun.star.chart2.DonutChartType" )
611  {
613  }
614  return bResult;
615 }
616 
617 } // anonymous namespace
618 
620  const uno::Reference< chart2::XChartDocument >& xNewDoc
621  , const OUString& rRectangularRange
622  , css::chart::ChartDataRowSource eDataRowSource
623  , bool bRowHasLabels, bool bColHasLabels
624  , bool bSwitchOnLabelsAndCategoriesForOwnData
625  , const OUString& sColTrans
626  , const OUString& sRowTrans )
627 {
628  if( !xNewDoc.is() )
629  return;
630 
631  uno::Reference< chart2::XDiagram > xNewDia( xNewDoc->getFirstDiagram());
632  uno::Reference< chart2::data::XDataProvider > xDataProvider( xNewDoc->getDataProvider() );
633  if( !xNewDia.is() || !xDataProvider.is() )
634  return;
635 
636  bool bFirstCellAsLabel =
637  (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bRowHasLabels : bColHasLabels;
638  bool bHasCateories =
639  (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bColHasLabels : bRowHasLabels;
640 
641  if( bSwitchOnLabelsAndCategoriesForOwnData )
642  {
643  bFirstCellAsLabel = true;
644  bHasCateories = true;
645  }
646 
647  uno::Sequence< beans::PropertyValue > aArgs( 3 );
648  aArgs[0] = beans::PropertyValue(
649  "CellRangeRepresentation",
650  -1, uno::makeAny( rRectangularRange ),
651  beans::PropertyState_DIRECT_VALUE );
652  aArgs[1] = beans::PropertyValue(
653  "DataRowSource",
654  -1, uno::makeAny( eDataRowSource ),
655  beans::PropertyState_DIRECT_VALUE );
656  aArgs[2] = beans::PropertyValue(
657  "FirstCellAsLabel",
658  -1, uno::makeAny( bFirstCellAsLabel ),
659  beans::PropertyState_DIRECT_VALUE );
660 
661  if( !sColTrans.isEmpty() || !sRowTrans.isEmpty() )
662  {
663  aArgs.realloc( aArgs.getLength() + 1 );
664  aArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 1 ] = beans::PropertyValue(
665  "SequenceMapping",
666  -1, uno::makeAny( !sColTrans.isEmpty()
667  ? lcl_getNumberSequenceFromString( sColTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() )
668  : lcl_getNumberSequenceFromString( sRowTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() ) ),
669  beans::PropertyState_DIRECT_VALUE );
670  }
671 
672  //work around wrong writer ranges ( see Issue 58464 )
673  {
674  OUString aChartOleObjectName;
675  if( xNewDoc.is() )
676  {
677  utl::MediaDescriptor aMediaDescriptor( xNewDoc->getArgs() );
678 
679  utl::MediaDescriptor::const_iterator aIt(
680  aMediaDescriptor.find( OUString( "HierarchicalDocumentName" )));
681  if( aIt != aMediaDescriptor.end() )
682  {
683  aChartOleObjectName = (*aIt).second.get< OUString >();
684  }
685  }
686  if( !aChartOleObjectName.isEmpty() )
687  {
688  aArgs.realloc( aArgs.getLength() + 1 );
689  aArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 1 ] = beans::PropertyValue(
690  "ChartOleObjectName",
691  -1, uno::makeAny( aChartOleObjectName ),
692  beans::PropertyState_DIRECT_VALUE );
693  }
694  }
695 
696  uno::Reference< chart2::data::XDataSource > xDataSource(
697  xDataProvider->createDataSource( aArgs ));
698 
699  aArgs.realloc( aArgs.getLength() + 2 );
700  aArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 2 ] = beans::PropertyValue(
701  "HasCategories",
702  -1, uno::makeAny( bHasCateories ),
703  beans::PropertyState_DIRECT_VALUE );
704  aArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 1 ] = beans::PropertyValue(
705  "UseCategoriesAsX",
706  -1, uno::makeAny( false ),//categories in ODF files are not to be used as x values (independent from what is offered in our ui)
707  beans::PropertyState_DIRECT_VALUE );
708 
709  xNewDia->setDiagramData( xDataSource, aArgs );
710 }
711 
713 {
714  uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
715  uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
716  uno::Reference< chart2::XChartDocument > xNewDoc( xDoc, uno::UNO_QUERY );
717 
718  if( xProp.is())
719  {
720  if( !maMainTitle.isEmpty())
721  {
722  uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getTitle(), uno::UNO_QUERY );
723  if( xTitleProp.is())
724  {
725  try
726  {
727  xTitleProp->setPropertyValue("String", uno::Any(maMainTitle) );
728  }
729  catch(const beans::UnknownPropertyException&)
730  {
731  SAL_WARN("xmloff.chart", "Property String for Title not available" );
732  }
733  }
734  }
735  if( !maSubTitle.isEmpty())
736  {
737  uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getSubTitle(), uno::UNO_QUERY );
738  if( xTitleProp.is())
739  {
740  try
741  {
742  xTitleProp->setPropertyValue("String", uno::Any(maSubTitle) );
743  }
744  catch(const beans::UnknownPropertyException&)
745  {
746  SAL_WARN("xmloff.chart", "Property String for Title not available" );
747  }
748  }
749  }
750  }
751 
752  // cleanup: remove empty chart type groups
753  lcl_removeEmptyChartTypeGroups( xNewDoc );
754 
755  // set stack mode before a potential chart type detection (in case we have a rectangular range)
756  uno::Reference< chart::XDiagram > xDiagram( xDoc->getDiagram() );
757  uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
758  if( xDiaProp.is())
759  {
761  xDiaProp->setPropertyValue("Stacked",maSeriesDefaultsAndStyles.maStackedDefault);
763  xDiaProp->setPropertyValue("Percent",maSeriesDefaultsAndStyles.maPercentDefault);
765  xDiaProp->setPropertyValue("Deep",maSeriesDefaultsAndStyles.maDeepDefault);
767  xDiaProp->setPropertyValue("StackedBarsConnected",maSeriesDefaultsAndStyles.maStackedBarsConnectedDefault);
768  }
769 
770  //the OOo 2.0 implementation and older has a bug with donuts
771  bool bSpecialHandlingForDonutChart = lcl_SpecialHandlingForDonutChartNeeded(
773 
774  // apply data
775  if(!xNewDoc.is())
776  return;
777 
778  bool bHasOwnData = false;
779  if( m_aXLinkHRefAttributeToIndicateDataProvider == "." ) //data comes from the chart itself
780  bHasOwnData = true;
781  else if( m_aXLinkHRefAttributeToIndicateDataProvider == ".." ) //data comes from the parent application
782  bHasOwnData = false;
783  else if( !m_aXLinkHRefAttributeToIndicateDataProvider.isEmpty() ) //not supported so far to get the data by sibling objects -> fall back to chart itself if data are available
784  bHasOwnData = m_bHasTableElement;
785  else
786  bHasOwnData = !m_bHasRangeAtPlotArea;
787 
788  if( xNewDoc->hasInternalDataProvider())
789  {
791  {
792  //#i103147# ODF, workaround broken files with a missing table:cell-range-address at the plot-area
793  bool bSwitchSuccessful = SchXMLTools::switchBackToDataProviderFromParent( xNewDoc, maLSequencesPerIndex );
794  bHasOwnData = !bSwitchSuccessful;
795  }
796  else
797  bHasOwnData = true;//e.g. in case of copy->paste from calc to impress
798  }
799  else if( bHasOwnData )
800  {
801  xNewDoc->createInternalDataProvider( false /* bCloneExistingData */ );
802  }
803  if( bHasOwnData )
804  msChartAddress = "all";
805 
806  bool bSwitchRangesFromOuterToInternalIfNecessary = false;
807  if( !bHasOwnData && mbAllRangeAddressesAvailable )
808  {
809  // special handling for stock chart (merge series together)
810  if( mbIsStockChart )
812  }
813  else if( !msChartAddress.isEmpty() )
814  {
815  //own data or only rectangular range available
816 
817  if( xNewDoc->hasInternalDataProvider() )
819 
820  bool bOlderThan2_3 = SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( xNewDoc );
821  bool bOldFileWithOwnDataFromRows = (bOlderThan2_3 && bHasOwnData && (meDataRowSource==chart::ChartDataRowSource_ROWS)); // in this case there are range addresses that are simply wrong.
822 
823  if( mbAllRangeAddressesAvailable && !bSpecialHandlingForDonutChart && !mbIsStockChart &&
824  !bOldFileWithOwnDataFromRows )
825  {
826  //bHasOwnData is true in this case!
827  //e.g. for normal files with own data or also in case of copy paste scenario (e.g. calc to impress)
828  bSwitchRangesFromOuterToInternalIfNecessary = true;
829  }
830  else
831  {
832  //apply data from rectangular range
833 
834  // create datasource from data provider with rectangular range parameters and change the diagram setDiagramData
835  try
836  {
837  if( bOlderThan2_3 && xDiaProp.is() )//for older charts the hidden cells were removed by calc on the fly
838  xDiaProp->setPropertyValue("IncludeHiddenCells",uno::makeAny(false));
839 
840  // note: mbRowHasLabels means the first row contains labels, that means we have "column-descriptions",
841  // (analogously mbColHasLabels means we have "row-descriptions")
843  }
844  catch(const uno::Exception&)
845  {
846  //try to fallback to internal data
847  TOOLS_WARN_EXCEPTION("xmloff.chart", "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram try to fallback to internal data" );
848  if(!bHasOwnData)
849  {
850  bHasOwnData = true;
851  msChartAddress = "all";
852  if( !xNewDoc->hasInternalDataProvider() )
853  {
854  xNewDoc->createInternalDataProvider( false /* bCloneExistingData */ );
856  try
857  {
859  }
860  catch(const uno::Exception&)
861  {
862  TOOLS_WARN_EXCEPTION("xmloff.chart", "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram fallback to internal data failed also" );
863  }
864  }
865  }
866  }
867  }
868  }
869  else
870  {
871  SAL_WARN("xmloff.chart", "Must not get here" );
872  }
873 
874  // now all series and data point properties are available and can be set
875  {
876  if( bSpecialHandlingForDonutChart )
877  {
878  uno::Reference< chart2::XDiagram > xNewDiagram( xNewDoc->getFirstDiagram() );
879  lcl_swapPointAndSeriesStylesForDonutCharts( maSeriesDefaultsAndStyles.maSeriesStyleVector
881  }
882 
884 
885  //set defaults from diagram to the new series:
886  //check whether we need to remove lines from symbol only charts
887  bool bSwitchOffLinesForScatter = false;
888  {
889  bool bLinesOn = true;
890  if( (maSeriesDefaultsAndStyles.maLinesOnProperty >>= bLinesOn) && !bLinesOn )
891  {
892  if( maChartTypeServiceName == "com.sun.star.chart2.ScatterChartType" )
893  {
894  bSwitchOffLinesForScatter = true;
896  }
897  }
898  }
900 
901  // set autostyles for series and data points
903  const SvXMLStyleContext* pStyle = nullptr;
904  OUString sCurrStyleName;
905 
906  if( pStylesCtxt )
907  {
908  //iterate over data-series first
909  //don't set series styles for donut charts
910  if( !bSpecialHandlingForDonutChart )
911  {
913  maSeriesDefaultsAndStyles, pStylesCtxt, pStyle,
914  sCurrStyleName, mrImportHelper, GetImport(),
916  // ... then set attributes for statistics (after their existence was set in the series)
918  maSeriesDefaultsAndStyles, pStylesCtxt,
919  pStyle, sCurrStyleName );
920 
922  maSeriesDefaultsAndStyles, pStylesCtxt,
923  pStyle, sCurrStyleName );
924  }
925  }
926 
927  //#i98319# call switchRangesFromOuterToInternalIfNecessary before the data point styles are applied, otherwise in copy->paste scenario the data point styles do get lost
928  if( bSwitchRangesFromOuterToInternalIfNecessary )
929  {
930  if( xNewDoc->hasInternalDataProvider() )
932  }
933 
934  if( pStylesCtxt )
935  {
936  // ... then iterate over data-point attributes, so the latter are not overwritten
938  , pStylesCtxt, pStyle, sCurrStyleName, mrImportHelper, GetImport(), mbIsStockChart, bSpecialHandlingForDonutChart, bSwitchOffLinesForScatter );
939  }
940  }
941 
942  if( xProp.is())
943  xProp->setPropertyValue("RefreshAddInAllowed", uno::makeAny( true) );
944 }
945 
947 {
948  OSL_ASSERT( mbIsStockChart );
949  try
950  {
951  uno::Reference< chart::XChartDocument > xOldDoc( mrImportHelper.GetChartDocument());
952  uno::Reference< chart2::XChartDocument > xDoc( xOldDoc, uno::UNO_QUERY_THROW );
953  uno::Reference< chart2::XDiagram > xDiagram( xDoc->getFirstDiagram());
954  if( ! xDiagram.is())
955  return;
956 
957  bool bHasJapaneseCandlestick = true;
958  uno::Reference< chart2::XDataSeriesContainer > xDSContainer;
959  uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
960  const uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
961  for( const auto& rCooSys : aCooSysSeq )
962  {
963  uno::Reference< chart2::XChartTypeContainer > xCTCnt( rCooSys, uno::UNO_QUERY_THROW );
964  uno::Sequence< uno::Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
965  auto pChartType = std::find_if(aChartTypes.begin(), aChartTypes.end(),
966  [](const auto& rChartType) { return rChartType->getChartType() == "com.sun.star.chart2.CandleStickChartType"; });
967  if (pChartType != aChartTypes.end())
968  {
969  xDSContainer.set( *pChartType, uno::UNO_QUERY_THROW );
970  uno::Reference< beans::XPropertySet > xCTProp( *pChartType, uno::UNO_QUERY_THROW );
971  xCTProp->getPropertyValue("Japanese") >>= bHasJapaneseCandlestick;
972  }
973  }
974 
975  if( xDSContainer.is())
976  {
977  // with japanese candlesticks: open, low, high, close
978  // otherwise: low, high, close
979  uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDSContainer->getDataSeries());
980  const sal_Int32 nSeriesCount( aSeriesSeq.getLength());
981  const sal_Int32 nSeriesPerCandleStick = bHasJapaneseCandlestick ? 4: 3;
982  sal_Int32 nCandleStickCount = nSeriesCount / nSeriesPerCandleStick;
983  OSL_ASSERT( nSeriesPerCandleStick * nCandleStickCount == nSeriesCount );
984  uno::Sequence< uno::Reference< chart2::XDataSeries > > aNewSeries( nCandleStickCount );
985  for( sal_Int32 i=0; i<nCandleStickCount; ++i )
986  {
987  sal_Int32 nSeriesIndex = i*nSeriesPerCandleStick;
988  if( bHasJapaneseCandlestick )
989  {
990  // open values
991  lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], "values-first");
992  aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
993  // low values
994  lcl_MoveDataToCandleStickSeries(
995  uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
996  aNewSeries[i], "values-min");
997  }
998  else
999  {
1000  // low values
1001  lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], "values-min");
1002  aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
1003  }
1004  // high values
1005  lcl_MoveDataToCandleStickSeries(
1006  uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
1007  aNewSeries[i], "values-max");
1008  // close values
1009  lcl_MoveDataToCandleStickSeries(
1010  uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
1011  aNewSeries[i], "values-last");
1012  }
1013  xDSContainer->setDataSeries( aNewSeries );
1014  }
1015  }
1016  catch(const uno::Exception&)
1017  {
1018  TOOLS_WARN_EXCEPTION("xmloff.chart", "Exception while merging series for stock chart" );
1019  }
1020 }
1021 
1023  sal_uInt16 nPrefix,
1024  const OUString& rLocalName,
1025  const uno::Reference< xml::sax::XAttributeList >& xAttrList )
1026 {
1027  SvXMLImportContext* pContext = nullptr;
1028  const SvXMLTokenMap& rTokenMap = mrImportHelper.GetChartElemTokenMap();
1029  uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
1030  uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
1031 
1032  switch( rTokenMap.Get( nPrefix, rLocalName ))
1033  {
1035  pContext = new SchXMLPlotAreaContext( mrImportHelper, GetImport(), rLocalName,
1044  break;
1045 
1046  case XML_TOK_CHART_TITLE:
1047  if( xDoc.is())
1048  {
1049  if( xProp.is())
1050  {
1051  xProp->setPropertyValue("HasMainTitle", uno::makeAny(true) );
1052  }
1053  uno::Reference< drawing::XShape > xTitleShape = xDoc->getTitle();
1054  pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1055  rLocalName, maMainTitle, xTitleShape );
1056  }
1057  break;
1058 
1060  if( xDoc.is())
1061  {
1062  if( xProp.is())
1063  {
1064  xProp->setPropertyValue("HasSubTitle", uno::makeAny(true) );
1065  }
1066  uno::Reference< drawing::XShape > xTitleShape = xDoc->getSubTitle();
1067  pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1068  rLocalName, maSubTitle, xTitleShape );
1069  }
1070  break;
1071 
1072  case XML_TOK_CHART_LEGEND:
1073  pContext = new SchXMLLegendContext( mrImportHelper, GetImport(), rLocalName );
1074  break;
1075 
1076  case XML_TOK_CHART_TABLE:
1077  {
1078  SchXMLTableContext * pTableContext =
1079  new SchXMLTableContext( mrImportHelper, GetImport(), rLocalName, maTable );
1080  m_bHasTableElement = true;
1081  // #i85913# take into account column- and row- mapping for
1082  // charts with own data only for those which were not copied
1083  // from a place where they got data from the container. Note,
1084  // that this requires the plot-area been read before the table
1085  // (which is required in the ODF spec)
1086  // Note: For stock charts and donut charts with special handling
1087  // the mapping must not be applied!
1088  if( msChartAddress.isEmpty() && !mbIsStockChart &&
1089  !lcl_SpecialHandlingForDonutChartNeeded(
1091  {
1092  if( !msColTrans.isEmpty() )
1093  {
1094  OSL_ASSERT( msRowTrans.isEmpty() );
1095  pTableContext->setColumnPermutation( lcl_getNumberSequenceFromString( msColTrans, true ));
1096  msColTrans.clear();
1097  }
1098  else if( !msRowTrans.isEmpty() )
1099  {
1100  pTableContext->setRowPermutation( lcl_getNumberSequenceFromString( msRowTrans, true ));
1101  msRowTrans.clear();
1102  }
1103  }
1104  pContext = pTableContext;
1105  }
1106  break;
1107 
1108  default:
1109  // try importing as an additional shape
1110  if( ! mxDrawPage.is())
1111  {
1112  uno::Reference< drawing::XDrawPageSupplier > xSupp( xDoc, uno::UNO_QUERY );
1113  if( xSupp.is())
1114  mxDrawPage = xSupp->getDrawPage();
1115 
1116  SAL_WARN_IF( !mxDrawPage.is(), "xmloff.chart", "Invalid Chart Page" );
1117  }
1118  if( mxDrawPage.is())
1119  pContext = GetImport().GetShapeImport()->CreateGroupChildContext(
1120  GetImport(), nPrefix, rLocalName, xAttrList, mxDrawPage );
1121  break;
1122  }
1123 
1124  return pContext;
1125 }
1126 
1127 /*
1128  With a locked controller the following is done here:
1129  1. Hide title, subtitle, and legend.
1130  2. Set the size of the draw page.
1131  3. Set a (logically) empty data set.
1132  4. Set the chart type.
1133 */
1135  const OUString & rChartTypeServiceName // currently the old service name
1136  )
1137 {
1138  uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
1139  SAL_WARN_IF( !xDoc.is(), "xmloff.chart", "No valid document!" );
1140 
1141  // Remove Title and Diagram ("De-InitNew")
1142  uno::Reference< chart2::XChartDocument > xNewDoc( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
1143  if( xNewDoc.is())
1144  {
1145  xNewDoc->setFirstDiagram( nullptr );
1146  uno::Reference< chart2::XTitled > xTitled( xNewDoc, uno::UNO_QUERY );
1147  if( xTitled.is())
1148  xTitled->setTitleObject( nullptr );
1149  }
1150 
1151  // Set the chart type via setting the diagram.
1152  if( !rChartTypeServiceName.isEmpty() && xDoc.is())
1153  {
1154  uno::Reference< lang::XMultiServiceFactory > xFact( xDoc, uno::UNO_QUERY );
1155  if( xFact.is())
1156  {
1157  uno::Reference< chart::XDiagram > xDia( xFact->createInstance( rChartTypeServiceName ), uno::UNO_QUERY );
1158  if( xDia.is())
1159  xDoc->setDiagram( xDia );
1160  }
1161  }
1162 }
1163 
1165  const OUString& rLocalName,
1166  OUString& rTitle,
1167  uno::Reference< drawing::XShape > const & xTitleShape ) :
1168  SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
1169  mrImportHelper( rImpHelper ),
1170  mrTitle( rTitle ),
1171  mxTitleShape( xTitleShape )
1172 {
1173 }
1174 
1176 {}
1177 
1178 void SchXMLTitleContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
1179 {
1180  sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
1181 
1182  css::awt::Point aPosition;
1183  bool bHasXPosition=false;
1184  bool bHasYPosition=false;
1185 
1186  for( sal_Int16 i = 0; i < nAttrCount; i++ )
1187  {
1188  OUString sAttrName = xAttrList->getNameByIndex( i );
1189  OUString aLocalName;
1190  OUString aValue = xAttrList->getValueByIndex( i );
1191  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
1192 
1193  if( nPrefix == XML_NAMESPACE_SVG )
1194  {
1195  if( IsXMLToken( aLocalName, XML_X ) )
1196  {
1198  aPosition.X, aValue );
1199  bHasXPosition = true;
1200  }
1201  else if( IsXMLToken( aLocalName, XML_Y ) )
1202  {
1204  aPosition.Y, aValue );
1205  bHasYPosition = true;
1206  }
1207  }
1208  else if( nPrefix == XML_NAMESPACE_CHART )
1209  {
1210  if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
1211  msAutoStyleName = aValue;
1212  }
1213  }
1214 
1215  if( mxTitleShape.is())
1216  {
1217  if( bHasXPosition && bHasYPosition )
1218  mxTitleShape->setPosition( aPosition );
1219 
1220  uno::Reference<beans::XPropertySet> xProp(mxTitleShape, uno::UNO_QUERY);
1222  }
1223 }
1224 
1226  sal_uInt16 nPrefix,
1227  const OUString& rLocalName,
1228  const uno::Reference< xml::sax::XAttributeList >& )
1229 {
1230  SvXMLImportContext* pContext = nullptr;
1231 
1232  if( (nPrefix == XML_NAMESPACE_TEXT ||
1233  nPrefix == XML_NAMESPACE_LO_EXT) &&
1234  IsXMLToken( rLocalName, XML_P ) )
1235  {
1236  pContext = new SchXMLParagraphContext( GetImport(), rLocalName, mrTitle );
1237  }
1238 
1239  return pContext;
1240 }
1241 
1242 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SchXMLChartContext(SchXMLImportHelper &rImpHelper, SvXMLImport &rImport, const OUString &rLocalName)
tools::SvRef< SvBaseLink > xSink
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3434
OUString GetNewChartTypeName(const OUString &rOldChartTypeName)
OUString m_aXLinkHRefAttributeToIndicateDataProvider
const char aData[]
constexpr sal_uInt16 XML_NAMESPACE_CHART
virtual void EndElement() override
EndElement is called before a context will be destructed, but after an elements context has been pars...
static void switchSeriesLinesOff(::std::vector< DataRowPointStyle > &rSeriesStyleVector)
SvXMLStylesContext * GetAutoStylesContext() const
SchXMLImportHelper & mrImportHelper
css::chart::ChartDataRowSource meDataRowSource
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:62
virtual void StartElement(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
StartElement is called after a context has been constructed and before an elements context is parsed...
constexpr sal_uInt16 XML_NAMESPACE_OOO
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:394
virtual void StartElement(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
StartElement is called after a context has been constructed and before an elements context is parsed...
Sequence< OUString > aServiceNames
void setRowPermutation(const css::uno::Sequence< sal_Int32 > &rPermutation)
constexpr sal_uInt16 XML_NAMESPACE_LO_EXT
void FillAutoStyle(const OUString &rAutoStyleName, const css::uno::Reference< css::beans::XPropertySet > &rProp)
Fill in the autostyle.
static void setDefaultsToSeries(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles)
sal_uInt16 GetKeyByAttrName(const OUString &rAttrName, OUString *pPrefix, OUString *pLocalName, OUString *pNamespace) const
css::awt::Size maChartSize
const SvXMLTokenMap & GetChartAttrTokenMap()
virtual ~SchXMLTitleContext() override
void InitChart(const OUString &rChartTypeServiceName)
This method bundles some settings to the chart model and executes them with a locked controller...
SchXMLTitleContext(SchXMLImportHelper &rImpHelper, SvXMLImport &rImport, const OUString &rLocalName, OUString &rTitle, css::uno::Reference< css::drawing::XShape > const &xTitleShape)
tSchXMLLSequencesPerIndex maLSequencesPerIndex
bool convertMeasureToCore(sal_Int32 &rValue, const OUString &rString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32) const
convert string to measure with meCoreMeasureUnit, using optional min and max values ...
Definition: xmluconv.cxx:171
sal_uInt16 sal_Unicode
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.
static void setStylesToStatisticsObjects(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles, const SvXMLStylesContext *pStylesCtxt, const SvXMLStyleContext *&rpStyle, OUString &rCurrStyleName)
sal_uInt16 GetKeyByAttrValueQName(const OUString &rAttrName, OUString *pLocalName) const
SchXMLImportHelper & mrImportHelper
css::uno::Any maStackedBarsConnectedDefault
OUString msStyleName
constexpr sal_uInt16 XML_NAMESPACE_SVG
#define TOOLS_WARN_EXCEPTION(area, stream)
int i
constexpr sal_uInt16 XML_NAMESPACE_TEXT
static void initSeriesPropertySets(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles, const css::uno::Reference< css::frame::XModel > &xChartModel)
static void setStylesToSeries(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles, const SvXMLStylesContext *pStylesCtxt, const SvXMLStyleContext *&rpStyle, OUString &rCurrStyleName, const SchXMLImportHelper &rImportHelper, const SvXMLImport &rImport, bool bIsStockChart, tSchXMLLSequencesPerIndex &rInOutLSequencesPerIndex)
sal_uInt16 Get(sal_uInt16 nPrefix, const OUString &rLName) const
Definition: xmltkmap.cxx:99
static void setStylesToRegressionCurves(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles, const SvXMLStylesContext *pStylesCtxt, const SvXMLStyleContext *&rpStyle, OUString const &rCurrStyleName)
static bool lcl_hasServiceName(Reference< lang::XMultiServiceFactory > const &xFactory, OUString const &rServiceName)
OUString GetChartTypeByClassName(const OUString &rClassName, bool bUseOldNames)
static void setStylesToDataPoints(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles, const SvXMLStylesContext *pStylesCtxt, const SvXMLStyleContext *&rpStyle, OUString &rCurrStyleName, const SchXMLImportHelper &rImportHelper, const SvXMLImport &rImport, bool bIsStockChart, bool bIsDonutChart, bool bSwitchOffLinesForScatter)
With this class you can import a element containing its data as element o...
css::uno::Reference< css::drawing::XShape > mxTitleShape
const SvXMLTokenMap & GetChartElemTokenMap()
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:44
#define TOOLS_INFO_EXCEPTION(area, stream)
const css::uno::Reference< css::chart::XChartDocument > & GetChartDocument() const
static::std::map< css::uno::Reference< css::chart2::XDataSeries >, sal_Int32 > getDataSeriesIndexMapFromDiagram(const css::uno::Reference< css::chart2::XDiagram > &xDiagram)
::std::vector< DataRowPointStyle > maSeriesStyleVector
Any makeAny(Color const &value)
static void switchRangesFromOuterToInternalIfNecessary(const SchXMLTable &rTable, const tSchXMLLSequencesPerIndex &rLSequencesPerIndex, const css::uno::Reference< css::chart2::XChartDocument > &xChartDoc, css::chart::ChartDataRowSource eDataRowSource)
This function reorders local data to fit the correct data structure.
#define SAL_WARN_IF(condition, area, stream)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3378
Handling of tokens in XML:
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlimp.hxx:396
const css::uno::Reference< css::frame::XModel > & GetModel() const
Definition: xmlimp.hxx:400
bool switchBackToDataProviderFromParent(const Reference< chart2::XChartDocument > &xChartDoc, const tSchXMLLSequencesPerIndex &rLSequencesPerIndex)
Sequence< sal_Int8 > aSeq
css::uno::Reference< css::drawing::XShapes > mxDrawPage
SeriesDefaultsAndStyles maSeriesDefaultsAndStyles
#define SAL_WARN(area, stream)
SchXMLChartTypeEnum GetChartTypeEnum(const OUString &rClassName)
virtual ~SchXMLChartContext() override
bool isDocumentGeneratedWithOpenOfficeOlderThan2_3(const uno::Reference< frame::XModel > &xChartModel)
static void lcl_setDataProvider(uno::Reference< chart2::XChartDocument > const &xChartDoc, OUString const &sDataPilotSource)
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.
void setColumnPermutation(const css::uno::Sequence< sal_Int32 > &rPermutation)
sal_uInt16 nPos
static void applyTableToInternalDataProvider(const SchXMLTable &rTable, const css::uno::Reference< css::chart2::XChartDocument > &xChartDoc)
rtl::Reference< XMLShapeImportHelper > const & GetShapeImport()
Definition: xmlimp.hxx:600
Reference< chart2::XDataSeries > m_xSeries
static void lcl_ApplyDataFromRectangularRangeToDiagram(const uno::Reference< chart2::XChartDocument > &xNewDoc, const OUString &rRectangularRange, css::chart::ChartDataRowSource eDataRowSource, bool bRowHasLabels, bool bColHasLabels, bool bSwitchOnLabelsAndCategoriesForOwnData, const OUString &sColTrans, const OUString &sRowTrans)