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.getArray()[ 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  auto pSeqArr = aSeq.getArray();
210  pSeqArr[0]=0;
211 
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 ) :
225  SvXMLImportContext( rImport ),
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::startFastElement( sal_Int32 /*nElement*/,
307  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
308 {
309  // parse attributes
310 
311  uno::Reference< embed::XVisualObject > xVisualObject( mrImportHelper.GetChartDocument(), uno::UNO_QUERY);
312  SAL_WARN_IF(!xVisualObject.is(), "xmloff.chart", "need xVisualObject for page size");
313  if( xVisualObject.is() )
314  maChartSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); //#i103460# take the size given from the parent frame as default
315 
316  OUString sAutoStyleName;
317  OUString aOldChartTypeName;
318  bool bHasAddin = false;
319 
320  for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
321  {
322  switch( aIter.getToken() )
323  {
324  case XML_ELEMENT(LO_EXT, XML_DATA_PILOT_SOURCE):
325  msDataPilotSource = aIter.toString();
326  break;
327  case XML_ELEMENT(XLINK, XML_HREF):
329  break;
330  case XML_ELEMENT(CHART, XML_CLASS):
331  {
332  OUString aValue = aIter.toString();
333  OUString sClassName;
334  sal_uInt16 nClassPrefix =
336  aValue, &sClassName );
337  if( XML_NAMESPACE_CHART == nClassPrefix )
338  {
339  SchXMLChartTypeEnum eChartTypeEnum = SchXMLTools::GetChartTypeEnum( sClassName );
340  if( eChartTypeEnum != XML_CHART_CLASS_UNKNOWN )
341  {
342  aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( sClassName, true /* bUseOldNames */ );
343  maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( sClassName, false /* bUseOldNames */ );
344  switch( eChartTypeEnum )
345  {
347  mbIsStockChart = true;
348  break;
349  default:
350  break;
351  }
352  }
353  }
354  else if( XML_NAMESPACE_OOO == nClassPrefix )
355  {
356  // service is taken from add-in-name attribute
357  bHasAddin = true;
358 
359  aOldChartTypeName = sClassName;
360  maChartTypeServiceName = sClassName;
361  }
362  }
363  break;
364 
365  case XML_ELEMENT(SVG, XML_WIDTH):
366  case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
368  maChartSize.Width, aIter.toView() );
369  break;
370 
371  case XML_ELEMENT(SVG, XML_HEIGHT):
372  case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
374  maChartSize.Height, aIter.toView() );
375  break;
376 
378  sAutoStyleName = aIter.toString();
379  break;
380 
382  msColTrans = aIter.toString();
383  break;
385  msRowTrans = aIter.toString();
386  break;
387  default:
388  XMLOFF_WARN_UNKNOWN("xmloff", aIter);
389  }
390  }
391 
392  uno::Reference<chart::XChartDocument> xDoc = mrImportHelper.GetChartDocument();
393  uno::Reference<chart2::XChartDocument> xNewDoc(xDoc, uno::UNO_QUERY);
394 
396 
397  if( aOldChartTypeName.isEmpty() )
398  {
399  SAL_WARN("xmloff.chart", "need a charttype to create a diagram" );
400  //set a fallback value:
401  const OUString& aChartClass_Bar( GetXMLToken(XML_BAR ) );
402  aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, true /* bUseOldNames */ );
403  maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, false /* bUseOldNames */ );
404  }
405 
406  // Set the size of the draw page.
407  if( xVisualObject.is() )
408  xVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, maChartSize );
409 
410  InitChart( aOldChartTypeName);
411 
412  if( bHasAddin )
413  {
414  //correct charttype service name when having an addin
415  //and don't refresh addin during load
416  uno::Reference< beans::XPropertySet > xDocProp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
417  if( xDocProp.is() )
418  {
419  try
420  {
421  xDocProp->getPropertyValue("BaseDiagram") >>= aOldChartTypeName;
423  xDocProp->setPropertyValue("RefreshAddInAllowed", uno::makeAny( false) );
424  }
425  catch(const uno::Exception&)
426  {
427  TOOLS_WARN_EXCEPTION("xmloff.chart", "Exception during import SchXMLChartContext::StartElement" );
428  }
429  }
430  }
431 
432  // set auto-styles for Area
433  uno::Reference<beans::XPropertySet> xProp = mrImportHelper.GetChartDocument()->getArea();
434  mrImportHelper.FillAutoStyle(sAutoStyleName, xProp);
435 }
436 
437 namespace
438 {
439 
440 struct NewDonutSeries
441 {
442  css::uno::Reference< css::chart2::XDataSeries > m_xSeries;
443  OUString msStyleName;
444  sal_Int32 mnAttachedAxis;
445 
446  ::std::vector< OUString > m_aSeriesStyles;
447  ::std::vector< OUString > m_aPointStyles;
448 
449  NewDonutSeries( const css::uno::Reference< css::chart2::XDataSeries >& xSeries, sal_Int32 nPointCount )
450  : m_xSeries( xSeries )
451  , mnAttachedAxis( 1 )
452  {
453  m_aPointStyles.resize(nPointCount);
454  m_aSeriesStyles.resize(nPointCount);
455  }
456 
457  void setSeriesStyleNameToPoint( const OUString& rStyleName, sal_Int32 nPointIndex )
458  {
459  SAL_WARN_IF(nPointIndex >= static_cast<sal_Int32>(m_aSeriesStyles.size()), "xmloff.chart", "donut point <-> series count mismatch");
460  if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
461  m_aSeriesStyles[nPointIndex]=rStyleName;
462  }
463 
464  void setPointStyleNameToPoint( const OUString& rStyleName, sal_Int32 nPointIndex )
465  {
466  SAL_WARN_IF(nPointIndex >= static_cast<sal_Int32>(m_aPointStyles.size()), "xmloff.chart", "donut point <-> series count mismatch");
467  if( nPointIndex < static_cast<sal_Int32>(m_aPointStyles.size()) )
468  m_aPointStyles[nPointIndex]=rStyleName;
469  }
470 
471  ::std::vector< DataRowPointStyle > creatStyleVector()
472  {
473  ::std::vector< DataRowPointStyle > aRet;
474 
476  , m_xSeries, -1, 1, msStyleName, mnAttachedAxis );
477  aRet.push_back( aSeriesStyle );
478 
479  sal_Int32 nPointIndex=0;
480  for (auto const& pointStyle : m_aPointStyles)
481  {
483  , m_xSeries, nPointIndex, 1, pointStyle, mnAttachedAxis );
484  if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
485  {
486  aPointStyle.msSeriesStyleNameForDonuts = m_aSeriesStyles[nPointIndex];
487  }
488  if( !aPointStyle.msSeriesStyleNameForDonuts.isEmpty()
489  || !aPointStyle.msStyleName.isEmpty() )
490  aRet.push_back( aPointStyle );
491  ++nPointIndex;
492  }
493 
494  return aRet;
495  }
496 };
497 
498 void lcl_swapPointAndSeriesStylesForDonutCharts( ::std::vector< DataRowPointStyle >& rStyleVector
499  , ::std::map< css::uno::Reference< css::chart2::XDataSeries> , sal_Int32 >&& aSeriesMap )
500 {
501  //detect old series count
502  //and add old series to aSeriesMap
503  sal_Int32 nOldSeriesCount = 0;
504  {
505  sal_Int32 nMaxOldSeriesIndex = 0;
506  sal_Int32 nOldSeriesIndex = 0;
507  for (auto const& style : rStyleVector)
508  {
509  DataRowPointStyle aStyle(style);
510  if(aStyle.meType == DataRowPointStyle::DATA_SERIES &&
511  aStyle.m_xSeries.is() )
512  {
513  nMaxOldSeriesIndex = nOldSeriesIndex;
514 
515  if( aSeriesMap.end() == aSeriesMap.find(aStyle.m_xSeries) )
516  aSeriesMap[aStyle.m_xSeries] = nOldSeriesIndex;
517 
518  nOldSeriesIndex++;
519  }
520  }
521  nOldSeriesCount = nMaxOldSeriesIndex+1;
522  }
523 
524  //initialize new series styles
525  ::std::map< Reference< chart2::XDataSeries >, sal_Int32 >::const_iterator aSeriesMapEnd( aSeriesMap.end() );
526 
527  //sort by index
528  ::std::vector< NewDonutSeries > aNewSeriesVector;
529  {
530  ::std::map< sal_Int32, Reference< chart2::XDataSeries > > aIndexSeriesMap;
531  for (auto const& series : aSeriesMap)
532  aIndexSeriesMap[series.second] = series.first;
533 
534  for (auto const& indexSeries : aIndexSeriesMap)
535  aNewSeriesVector.emplace_back(indexSeries.second,nOldSeriesCount );
536  }
537 
538  //overwrite attached axis information according to old series styles
539  for (auto const& style : rStyleVector)
540  {
541  DataRowPointStyle aStyle(style);
542  if(aStyle.meType == DataRowPointStyle::DATA_SERIES )
543  {
544  auto aSeriesMapIt = aSeriesMap.find( aStyle.m_xSeries );
545  if( aSeriesMapIt != aSeriesMapEnd && aSeriesMapIt->second < static_cast<sal_Int32>(aNewSeriesVector.size()) )
546  aNewSeriesVector[aSeriesMapIt->second].mnAttachedAxis = aStyle.mnAttachedAxis;
547  }
548  }
549 
550  //overwrite new series style names with old series style name information
551  for (auto const& style : rStyleVector)
552  {
553  DataRowPointStyle aStyle(style);
554  if( aStyle.meType == DataRowPointStyle::DATA_SERIES )
555  {
556  auto aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
557  if( aSeriesMapEnd != aSeriesMapIt )
558  {
559  sal_Int32 nNewPointIndex = aSeriesMapIt->second;
560 
561  for (auto & newSeries : aNewSeriesVector)
562  newSeries.setSeriesStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
563  }
564  }
565  }
566 
567  //overwrite new series style names with point style name information
568  for (auto const& style : rStyleVector)
569  {
570  DataRowPointStyle aStyle(style);
571  if( aStyle.meType == DataRowPointStyle::DATA_POINT )
572  {
573  auto aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
574  if( aSeriesMapEnd != aSeriesMapIt )
575  {
576  sal_Int32 nNewPointIndex = aSeriesMapIt->second;
577  sal_Int32 nNewSeriesIndex = aStyle.m_nPointIndex;
578  sal_Int32 nRepeatCount = aStyle.m_nPointRepeat;
579 
580  while( nRepeatCount && (nNewSeriesIndex>=0) && (nNewSeriesIndex< static_cast<sal_Int32>(aNewSeriesVector.size()) ) )
581  {
582  NewDonutSeries& rNewSeries( aNewSeriesVector[nNewSeriesIndex] );
583  rNewSeries.setPointStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
584 
585  nRepeatCount--;
586  nNewSeriesIndex++;
587  }
588  }
589  }
590  }
591 
592  //put information from aNewSeriesVector to output parameter rStyleVector
593  rStyleVector.clear();
594 
595  for (auto & newSeries : aNewSeriesVector)
596  {
597  ::std::vector< DataRowPointStyle > aVector( newSeries.creatStyleVector() );
598  rStyleVector.insert(rStyleVector.end(),aVector.begin(),aVector.end());
599  }
600 }
601 
602 bool lcl_SpecialHandlingForDonutChartNeeded(
603  std::u16string_view rServiceName,
604  const SvXMLImport & rImport )
605 {
606  bool bResult = false;
607  if( rServiceName == u"com.sun.star.chart2.DonutChartType" )
608  {
610  }
611  return bResult;
612 }
613 
614 } // anonymous namespace
615 
617  const uno::Reference< chart2::XChartDocument >& xNewDoc
618  , const OUString& rRectangularRange
619  , css::chart::ChartDataRowSource eDataRowSource
620  , bool bRowHasLabels, bool bColHasLabels
621  , bool bSwitchOnLabelsAndCategoriesForOwnData
622  , const OUString& sColTrans
623  , const OUString& sRowTrans )
624 {
625  if( !xNewDoc.is() )
626  return;
627 
628  uno::Reference< chart2::XDiagram > xNewDia( xNewDoc->getFirstDiagram());
629  uno::Reference< chart2::data::XDataProvider > xDataProvider( xNewDoc->getDataProvider() );
630  if( !xNewDia.is() || !xDataProvider.is() )
631  return;
632 
633  bool bFirstCellAsLabel =
634  (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bRowHasLabels : bColHasLabels;
635  bool bHasCateories =
636  (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bColHasLabels : bRowHasLabels;
637 
638  if( bSwitchOnLabelsAndCategoriesForOwnData )
639  {
640  bFirstCellAsLabel = true;
641  bHasCateories = true;
642  }
643 
644  uno::Sequence< beans::PropertyValue > aArgs{
645  beans::PropertyValue(
646  "CellRangeRepresentation",
647  -1, uno::makeAny( rRectangularRange ),
648  beans::PropertyState_DIRECT_VALUE ),
649  beans::PropertyValue(
650  "DataRowSource",
651  -1, uno::makeAny( eDataRowSource ),
652  beans::PropertyState_DIRECT_VALUE ),
653  beans::PropertyValue(
654  "FirstCellAsLabel",
655  -1, uno::makeAny( bFirstCellAsLabel ),
656  beans::PropertyState_DIRECT_VALUE )
657  };
658 
659  if( !sColTrans.isEmpty() || !sRowTrans.isEmpty() )
660  {
661  aArgs.realloc( aArgs.getLength() + 1 );
662  aArgs.getArray()[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 1 ] = beans::PropertyValue(
663  "SequenceMapping",
664  -1, uno::makeAny( !sColTrans.isEmpty()
665  ? lcl_getNumberSequenceFromString( sColTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() )
666  : lcl_getNumberSequenceFromString( sRowTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() ) ),
667  beans::PropertyState_DIRECT_VALUE );
668  }
669 
670  //work around wrong writer ranges ( see Issue 58464 )
671  {
672  OUString aChartOleObjectName;
673  if( xNewDoc.is() )
674  {
675  utl::MediaDescriptor aMediaDescriptor( xNewDoc->getArgs() );
676 
677  utl::MediaDescriptor::const_iterator aIt(
678  aMediaDescriptor.find( OUString( "HierarchicalDocumentName" )));
679  if( aIt != aMediaDescriptor.end() )
680  {
681  aChartOleObjectName = (*aIt).second.get< OUString >();
682  }
683  }
684  if( !aChartOleObjectName.isEmpty() )
685  {
686  aArgs.realloc( aArgs.getLength() + 1 );
687  aArgs.getArray()[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 1 ] = beans::PropertyValue(
688  "ChartOleObjectName",
689  -1, uno::makeAny( aChartOleObjectName ),
690  beans::PropertyState_DIRECT_VALUE );
691  }
692  }
693 
694  uno::Reference< chart2::data::XDataSource > xDataSource(
695  xDataProvider->createDataSource( aArgs ));
696 
697  aArgs.realloc( aArgs.getLength() + 2 );
698  auto pArgs = aArgs.getArray();
699  pArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 2 ] = beans::PropertyValue(
700  "HasCategories",
701  -1, uno::makeAny( bHasCateories ),
702  beans::PropertyState_DIRECT_VALUE );
703  pArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 1 ] = beans::PropertyValue(
704  "UseCategoriesAsX",
705  -1, uno::makeAny( false ),//categories in ODF files are not to be used as x values (independent from what is offered in our ui)
706  beans::PropertyState_DIRECT_VALUE );
707 
708  xNewDia->setDiagramData( xDataSource, aArgs );
709 }
710 
712 {
713  uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
714  uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
715  uno::Reference< chart2::XChartDocument > xNewDoc( xDoc, uno::UNO_QUERY );
716 
717  if( xProp.is())
718  {
719  if( !maMainTitle.isEmpty())
720  {
721  uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getTitle(), uno::UNO_QUERY );
722  if( xTitleProp.is())
723  {
724  try
725  {
726  xTitleProp->setPropertyValue("String", uno::Any(maMainTitle) );
727  }
728  catch(const beans::UnknownPropertyException&)
729  {
730  SAL_WARN("xmloff.chart", "Property String for Title not available" );
731  }
732  }
733  }
734  if( !maSubTitle.isEmpty())
735  {
736  uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getSubTitle(), uno::UNO_QUERY );
737  if( xTitleProp.is())
738  {
739  try
740  {
741  xTitleProp->setPropertyValue("String", uno::Any(maSubTitle) );
742  }
743  catch(const beans::UnknownPropertyException&)
744  {
745  SAL_WARN("xmloff.chart", "Property String for Title not available" );
746  }
747  }
748  }
749  }
750 
751  // cleanup: remove empty chart type groups
752  lcl_removeEmptyChartTypeGroups( xNewDoc );
753 
754  // set stack mode before a potential chart type detection (in case we have a rectangular range)
755  uno::Reference< chart::XDiagram > xDiagram( xDoc->getDiagram() );
756  uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
757  if( xDiaProp.is())
758  {
760  xDiaProp->setPropertyValue("Stacked",maSeriesDefaultsAndStyles.maStackedDefault);
762  xDiaProp->setPropertyValue("Percent",maSeriesDefaultsAndStyles.maPercentDefault);
764  xDiaProp->setPropertyValue("Deep",maSeriesDefaultsAndStyles.maDeepDefault);
766  xDiaProp->setPropertyValue("StackedBarsConnected",maSeriesDefaultsAndStyles.maStackedBarsConnectedDefault);
767  }
768 
769  //the OOo 2.0 implementation and older has a bug with donuts
770  bool bSpecialHandlingForDonutChart = lcl_SpecialHandlingForDonutChartNeeded(
772 
773  // apply data
774  if(!xNewDoc.is())
775  return;
776 
777  bool bHasOwnData = false;
778  if( m_aXLinkHRefAttributeToIndicateDataProvider == "." ) //data comes from the chart itself
779  bHasOwnData = true;
780  else if( m_aXLinkHRefAttributeToIndicateDataProvider == ".." ) //data comes from the parent application
781  bHasOwnData = false;
782  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
783  bHasOwnData = m_bHasTableElement;
784  else
785  bHasOwnData = !m_bHasRangeAtPlotArea;
786 
787  if( xNewDoc->hasInternalDataProvider())
788  {
790  {
791  //#i103147# ODF, workaround broken files with a missing table:cell-range-address at the plot-area
792  bool bSwitchSuccessful = SchXMLTools::switchBackToDataProviderFromParent( xNewDoc, maLSequencesPerIndex );
793  bHasOwnData = !bSwitchSuccessful;
794  }
795  else
796  bHasOwnData = true;//e.g. in case of copy->paste from calc to impress
797  }
798  else if( bHasOwnData )
799  {
800  xNewDoc->createInternalDataProvider( false /* bCloneExistingData */ );
801  }
802  if( bHasOwnData )
803  msChartAddress = "all";
804 
805  bool bSwitchRangesFromOuterToInternalIfNecessary = false;
806  if( !bHasOwnData && mbAllRangeAddressesAvailable )
807  {
808  // special handling for stock chart (merge series together)
809  if( mbIsStockChart )
811  }
812  else if( !msChartAddress.isEmpty() )
813  {
814  //own data or only rectangular range available
815 
816  if( xNewDoc->hasInternalDataProvider() )
818 
819  bool bOlderThan2_3 = SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( xNewDoc );
820  bool bOldFileWithOwnDataFromRows = (bOlderThan2_3 && bHasOwnData && (meDataRowSource==chart::ChartDataRowSource_ROWS)); // in this case there are range addresses that are simply wrong.
821 
822  if( mbAllRangeAddressesAvailable && !bSpecialHandlingForDonutChart && !mbIsStockChart &&
823  !bOldFileWithOwnDataFromRows )
824  {
825  //bHasOwnData is true in this case!
826  //e.g. for normal files with own data or also in case of copy paste scenario (e.g. calc to impress)
827  bSwitchRangesFromOuterToInternalIfNecessary = true;
828  }
829  else
830  {
831  //apply data from rectangular range
832 
833  // create datasource from data provider with rectangular range parameters and change the diagram setDiagramData
834  try
835  {
836  if( bOlderThan2_3 && xDiaProp.is() )//for older charts the hidden cells were removed by calc on the fly
837  xDiaProp->setPropertyValue("IncludeHiddenCells",uno::makeAny(false));
838 
839  // note: mbRowHasLabels means the first row contains labels, that means we have "column-descriptions",
840  // (analogously mbColHasLabels means we have "row-descriptions")
842  }
843  catch(const uno::Exception&)
844  {
845  //try to fallback to internal data
846  TOOLS_WARN_EXCEPTION("xmloff.chart", "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram try to fallback to internal data" );
847  if(!bHasOwnData)
848  {
849  bHasOwnData = true;
850  msChartAddress = "all";
851  if( !xNewDoc->hasInternalDataProvider() )
852  {
853  xNewDoc->createInternalDataProvider( false /* bCloneExistingData */ );
855  try
856  {
858  }
859  catch(const uno::Exception&)
860  {
861  TOOLS_WARN_EXCEPTION("xmloff.chart", "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram fallback to internal data failed also" );
862  }
863  }
864  }
865  }
866  }
867  }
868  else
869  {
870  SAL_WARN("xmloff.chart", "Must not get here" );
871  }
872 
873  // now all series and data point properties are available and can be set
874  {
875  if( bSpecialHandlingForDonutChart )
876  {
877  uno::Reference< chart2::XDiagram > xNewDiagram( xNewDoc->getFirstDiagram() );
878  lcl_swapPointAndSeriesStylesForDonutCharts( maSeriesDefaultsAndStyles.maSeriesStyleVector
880  }
881 
883 
884  //set defaults from diagram to the new series:
885  //check whether we need to remove lines from symbol only charts
886  bool bSwitchOffLinesForScatter = false;
887  {
888  bool bLinesOn = true;
889  if( (maSeriesDefaultsAndStyles.maLinesOnProperty >>= bLinesOn) && !bLinesOn )
890  {
891  if( maChartTypeServiceName == "com.sun.star.chart2.ScatterChartType" )
892  {
893  bSwitchOffLinesForScatter = true;
895  }
896  }
897  }
899 
900  // set autostyles for series and data points
902  const SvXMLStyleContext* pStyle = nullptr;
903  OUString sCurrStyleName;
904 
905  if( pStylesCtxt )
906  {
907  //iterate over data-series first
908  //don't set series styles for donut charts
909  if( !bSpecialHandlingForDonutChart )
910  {
912  maSeriesDefaultsAndStyles, pStylesCtxt, pStyle,
913  sCurrStyleName, mrImportHelper, GetImport(),
915  // ... then set attributes for statistics (after their existence was set in the series)
917  maSeriesDefaultsAndStyles, pStylesCtxt,
918  pStyle, sCurrStyleName );
919 
921  maSeriesDefaultsAndStyles, pStylesCtxt,
922  pStyle, sCurrStyleName );
923  }
924  }
925 
926  //#i98319# call switchRangesFromOuterToInternalIfNecessary before the data point styles are applied, otherwise in copy->paste scenario the data point styles do get lost
927  if( bSwitchRangesFromOuterToInternalIfNecessary )
928  {
929  if( xNewDoc->hasInternalDataProvider() )
931  }
932 
933  if( pStylesCtxt )
934  {
935  // ... then iterate over data-point attributes, so the latter are not overwritten
937  , pStylesCtxt, pStyle, sCurrStyleName, mrImportHelper, GetImport(), mbIsStockChart, bSpecialHandlingForDonutChart, bSwitchOffLinesForScatter );
938  }
939  }
940 
941  if( xProp.is())
942  xProp->setPropertyValue("RefreshAddInAllowed", uno::makeAny( true) );
943 }
944 
946 {
947  OSL_ASSERT( mbIsStockChart );
948  try
949  {
950  uno::Reference< chart::XChartDocument > xOldDoc( mrImportHelper.GetChartDocument());
951  uno::Reference< chart2::XChartDocument > xDoc( xOldDoc, uno::UNO_QUERY_THROW );
952  uno::Reference< chart2::XDiagram > xDiagram( xDoc->getFirstDiagram());
953  if( ! xDiagram.is())
954  return;
955 
956  bool bHasJapaneseCandlestick = true;
957  uno::Reference< chart2::XDataSeriesContainer > xDSContainer;
958  uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
959  const uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
960  for( const auto& rCooSys : aCooSysSeq )
961  {
962  uno::Reference< chart2::XChartTypeContainer > xCTCnt( rCooSys, uno::UNO_QUERY_THROW );
963  const uno::Sequence< uno::Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
964  auto pChartType = std::find_if(aChartTypes.begin(), aChartTypes.end(),
965  [](const auto& rChartType) { return rChartType->getChartType() == "com.sun.star.chart2.CandleStickChartType"; });
966  if (pChartType != aChartTypes.end())
967  {
968  xDSContainer.set( *pChartType, uno::UNO_QUERY_THROW );
969  uno::Reference< beans::XPropertySet > xCTProp( *pChartType, uno::UNO_QUERY_THROW );
970  xCTProp->getPropertyValue("Japanese") >>= bHasJapaneseCandlestick;
971  }
972  }
973 
974  if( xDSContainer.is())
975  {
976  // with japanese candlesticks: open, low, high, close
977  // otherwise: low, high, close
978  uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDSContainer->getDataSeries());
979  const sal_Int32 nSeriesCount( aSeriesSeq.getLength());
980  const sal_Int32 nSeriesPerCandleStick = bHasJapaneseCandlestick ? 4: 3;
981  sal_Int32 nCandleStickCount = nSeriesCount / nSeriesPerCandleStick;
982  OSL_ASSERT( nSeriesPerCandleStick * nCandleStickCount == nSeriesCount );
983  uno::Sequence< uno::Reference< chart2::XDataSeries > > aNewSeries( nCandleStickCount );
984  auto aNewSeriesRange = asNonConstRange(aNewSeries);
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  aNewSeriesRange[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  aNewSeriesRange[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 
1022 css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLChartContext::createFastChildContext(
1023  sal_Int32 nElement,
1024  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
1025 {
1026  SvXMLImportContext* pContext = nullptr;
1027  uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
1028  uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
1029 
1030  switch(nElement)
1031  {
1033  pContext = new SchXMLPlotAreaContext( mrImportHelper, GetImport(),
1042  break;
1043  case XML_ELEMENT(CHART, XML_TITLE):
1044  if( xDoc.is())
1045  {
1046  if( xProp.is())
1047  {
1048  xProp->setPropertyValue("HasMainTitle", uno::makeAny(true) );
1049  }
1050  uno::Reference< drawing::XShape > xTitleShape = xDoc->getTitle();
1051  pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1052  maMainTitle, xTitleShape );
1053  }
1054  break;
1056  if( xDoc.is())
1057  {
1058  if( xProp.is())
1059  {
1060  xProp->setPropertyValue("HasSubTitle", uno::makeAny(true) );
1061  }
1062  uno::Reference< drawing::XShape > xTitleShape = xDoc->getSubTitle();
1063  pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1064  maSubTitle, xTitleShape );
1065  }
1066  break;
1067  case XML_ELEMENT(CHART, XML_LEGEND):
1068  pContext = new SchXMLLegendContext( mrImportHelper, GetImport() );
1069  break;
1070  case XML_ELEMENT(TABLE, XML_TABLE):
1071  {
1072  SchXMLTableContext * pTableContext =
1074  m_bHasTableElement = true;
1075  // #i85913# take into account column- and row- mapping for
1076  // charts with own data only for those which were not copied
1077  // from a place where they got data from the container. Note,
1078  // that this requires the plot-area been read before the table
1079  // (which is required in the ODF spec)
1080  // Note: For stock charts and donut charts with special handling
1081  // the mapping must not be applied!
1082  if( msChartAddress.isEmpty() && !mbIsStockChart &&
1083  !lcl_SpecialHandlingForDonutChartNeeded(
1085  {
1086  if( !msColTrans.isEmpty() )
1087  {
1088  OSL_ASSERT( msRowTrans.isEmpty() );
1089  pTableContext->setColumnPermutation( lcl_getNumberSequenceFromString( msColTrans, true ));
1090  msColTrans.clear();
1091  }
1092  else if( !msRowTrans.isEmpty() )
1093  {
1094  pTableContext->setRowPermutation( lcl_getNumberSequenceFromString( msRowTrans, true ));
1095  msRowTrans.clear();
1096  }
1097  }
1098  pContext = pTableContext;
1099  }
1100  break;
1101 
1102  default:
1103  // try importing as an additional shape
1104  if( ! mxDrawPage.is())
1105  {
1106  uno::Reference< drawing::XDrawPageSupplier > xSupp( xDoc, uno::UNO_QUERY );
1107  if( xSupp.is())
1108  mxDrawPage = xSupp->getDrawPage();
1109 
1110  SAL_WARN_IF( !mxDrawPage.is(), "xmloff.chart", "Invalid Chart Page" );
1111  }
1112  if( mxDrawPage.is())
1114  GetImport(), nElement, xAttrList, mxDrawPage );
1115  break;
1116  }
1117 
1118  return pContext;
1119 }
1120 
1121 /*
1122  With a locked controller the following is done here:
1123  1. Hide title, subtitle, and legend.
1124  2. Set the size of the draw page.
1125  3. Set a (logically) empty data set.
1126  4. Set the chart type.
1127 */
1129  const OUString & rChartTypeServiceName // currently the old service name
1130  )
1131 {
1132  uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
1133  SAL_WARN_IF( !xDoc.is(), "xmloff.chart", "No valid document!" );
1134 
1135  // Remove Title and Diagram ("De-InitNew")
1136  uno::Reference< chart2::XChartDocument > xNewDoc( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
1137  if( xNewDoc.is())
1138  {
1139  xNewDoc->setFirstDiagram( nullptr );
1140  uno::Reference< chart2::XTitled > xTitled( xNewDoc, uno::UNO_QUERY );
1141  if( xTitled.is())
1142  xTitled->setTitleObject( nullptr );
1143  }
1144 
1145  // Set the chart type via setting the diagram.
1146  if( !rChartTypeServiceName.isEmpty() && xDoc.is())
1147  {
1148  uno::Reference< lang::XMultiServiceFactory > xFact( xDoc, uno::UNO_QUERY );
1149  if( xFact.is())
1150  {
1151  uno::Reference< chart::XDiagram > xDia( xFact->createInstance( rChartTypeServiceName ), uno::UNO_QUERY );
1152  if( xDia.is())
1153  xDoc->setDiagram( xDia );
1154  }
1155  }
1156 }
1157 
1159  OUString& rTitle,
1160  uno::Reference< drawing::XShape > const & xTitleShape ) :
1161  SvXMLImportContext( rImport ),
1162  mrImportHelper( rImpHelper ),
1163  mrTitle( rTitle ),
1164  mxTitleShape( xTitleShape )
1165 {
1166 }
1167 
1169 {}
1170 
1171 void SchXMLTitleContext::startFastElement( sal_Int32 /*nElement*/,
1172  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
1173 {
1174  css::awt::Point aPosition;
1175  bool bHasXPosition=false;
1176  bool bHasYPosition=false;
1177 
1178  for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
1179  {
1180  switch (aIter.getToken())
1181  {
1182  case XML_ELEMENT(SVG, XML_X):
1183  case XML_ELEMENT(SVG_COMPAT, XML_X):
1184  {
1186  aPosition.X, aIter.toView() );
1187  bHasXPosition = true;
1188  break;
1189  }
1190  case XML_ELEMENT(SVG, XML_Y):
1191  case XML_ELEMENT(SVG_COMPAT, XML_Y):
1192  {
1194  aPosition.Y, aIter.toView() );
1195  bHasYPosition = true;
1196  break;
1197  }
1199  msAutoStyleName = aIter.toString();
1200  break;
1201  default:
1202  XMLOFF_WARN_UNKNOWN("xmloff", aIter);
1203  }
1204  }
1205 
1206  if( mxTitleShape.is())
1207  {
1208  if( bHasXPosition && bHasYPosition )
1209  mxTitleShape->setPosition( aPosition );
1210 
1211  uno::Reference<beans::XPropertySet> xProp(mxTitleShape, uno::UNO_QUERY);
1213  }
1214 }
1215 
1216 css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLTitleContext::createFastChildContext(
1217  sal_Int32 nElement,
1218  const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
1219 {
1220  SvXMLImportContext* pContext = nullptr;
1221 
1222  if( nElement == XML_ELEMENT(TEXT, XML_P) ||
1223  nElement == XML_ELEMENT(LO_EXT, XML_P) )
1224  {
1225  pContext = new SchXMLParagraphContext( GetImport(), mrTitle );
1226  }
1227  else
1228  XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
1229 
1230  return pContext;
1231 }
1232 
1233 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
tools::SvRef< SvBaseLink > xSink
bool convertMeasureToCore(sal_Int32 &rValue, std::u16string_view 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:186
OUString GetNewChartTypeName(const OUString &rOldChartTypeName)
OUString m_aXLinkHRefAttributeToIndicateDataProvider
constexpr sal_uInt16 XML_NAMESPACE_CHART
virtual void SAL_CALL startFastElement(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
static void switchSeriesLinesOff(::std::vector< DataRowPointStyle > &rSeriesStyleVector)
SvXMLStylesContext * GetAutoStylesContext() const
SchXMLImportHelper & mrImportHelper
css::chart::ChartDataRowSource meDataRowSource
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:60
constexpr sal_uInt16 XML_NAMESPACE_OOO
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:398
Sequence< OUString > aServiceNames
void setRowPermutation(const css::uno::Sequence< sal_Int32 > &rPermutation)
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
void FillAutoStyle(const OUString &rAutoStyleName, const css::uno::Reference< css::beans::XPropertySet > &rProp)
Fill in the autostyle.
static void setDefaultsToSeries(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles)
css::awt::Size maChartSize
virtual ~SchXMLTitleContext() override
void InitChart(const OUString &rChartTypeServiceName)
This method bundles some settings to the chart model and executes them with a locked controller...
tSchXMLLSequencesPerIndex maLSequencesPerIndex
sal_uInt16 sal_Unicode
static void setStylesToStatisticsObjects(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles, const SvXMLStylesContext *pStylesCtxt, const SvXMLStyleContext *&rpStyle, OUString &rCurrStyleName)
OUString GetChartTypeByClassName(std::u16string_view rClassName, bool bUseOldNames)
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:114
sal_uInt16 GetKeyByAttrValueQName(const OUString &rAttrName, OUString *pLocalName) const
SchXMLImportHelper & mrImportHelper
virtual void SAL_CALL startFastElement(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
css::uno::Any maStackedBarsConnectedDefault
OUString msStyleName
constexpr OUStringLiteral aData
#define TOOLS_WARN_EXCEPTION(area, stream)
SchXMLChartContext(SchXMLImportHelper &rImpHelper, SvXMLImport &rImport)
int i
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)
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)
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
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:45
#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:3472
Handling of tokens in XML:
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:97
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlimp.hxx:400
const css::uno::Reference< css::frame::XModel > & GetModel() const
Definition: xmlimp.hxx:404
bool switchBackToDataProviderFromParent(const Reference< chart2::XChartDocument > &xChartDoc, const tSchXMLLSequencesPerIndex &rLSequencesPerIndex)
Sequence< sal_Int8 > aSeq
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
TABLE
css::uno::Reference< css::drawing::XShapes > mxDrawPage
SeriesDefaultsAndStyles maSeriesDefaultsAndStyles
#define SAL_WARN(area, stream)
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
Definition: xmlictxt.hxx:120
virtual ~SchXMLChartContext() override
bool isDocumentGeneratedWithOpenOfficeOlderThan2_3(const uno::Reference< frame::XModel > &xChartModel)
SchXMLChartTypeEnum GetChartTypeEnum(std::u16string_view rClassName)
static SvXMLShapeContext * CreateGroupChildContext(SvXMLImport &rImport, sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList, css::uno::Reference< css::drawing::XShapes > const &rShapes, bool bTemporaryShape=false)
static void lcl_setDataProvider(uno::Reference< chart2::XChartDocument > const &xChartDoc, OUString const &sDataPilotSource)
void setColumnPermutation(const css::uno::Sequence< sal_Int32 > &rPermutation)
TEXT
sal_uInt16 nPos
static void applyTableToInternalDataProvider(const SchXMLTable &rTable, const css::uno::Reference< css::chart2::XChartDocument > &xChartDoc)
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)
SchXMLTitleContext(SchXMLImportHelper &rImpHelper, SvXMLImport &rImport, OUString &rTitle, css::uno::Reference< css::drawing::XShape > const &xTitleShape)