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 ) :
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  , const ::std::map< css::uno::Reference< css::chart2::XDataSeries> , sal_Int32 >& rSeriesMap )
500 {
501  //detect old series count
502  //and add old series to aSeriesMap
503  ::std::map< css::uno::Reference<
504  css::chart2::XDataSeries >, sal_Int32 > aSeriesMap(rSeriesMap);
505  sal_Int32 nOldSeriesCount = 0;
506  {
507  sal_Int32 nMaxOldSeriesIndex = 0;
508  sal_Int32 nOldSeriesIndex = 0;
509  for (auto const& style : rStyleVector)
510  {
511  DataRowPointStyle aStyle(style);
512  if(aStyle.meType == DataRowPointStyle::DATA_SERIES &&
513  aStyle.m_xSeries.is() )
514  {
515  nMaxOldSeriesIndex = nOldSeriesIndex;
516 
517  if( aSeriesMap.end() == aSeriesMap.find(aStyle.m_xSeries) )
518  aSeriesMap[aStyle.m_xSeries] = nOldSeriesIndex;
519 
520  nOldSeriesIndex++;
521  }
522  }
523  nOldSeriesCount = nMaxOldSeriesIndex+1;
524  }
525 
526  //initialize new series styles
527  ::std::map< Reference< chart2::XDataSeries >, sal_Int32 >::const_iterator aSeriesMapEnd( aSeriesMap.end() );
528 
529  //sort by index
530  ::std::vector< NewDonutSeries > aNewSeriesVector;
531  {
532  ::std::map< sal_Int32, Reference< chart2::XDataSeries > > aIndexSeriesMap;
533  for (auto const& series : aSeriesMap)
534  aIndexSeriesMap[series.second] = series.first;
535 
536  for (auto const& indexSeries : aIndexSeriesMap)
537  aNewSeriesVector.emplace_back(indexSeries.second,nOldSeriesCount );
538  }
539 
540  //overwrite attached axis information according to old series styles
541  for (auto const& style : rStyleVector)
542  {
543  DataRowPointStyle aStyle(style);
544  if(aStyle.meType == DataRowPointStyle::DATA_SERIES )
545  {
546  auto aSeriesMapIt = aSeriesMap.find( aStyle.m_xSeries );
547  if( aSeriesMapIt != aSeriesMapEnd && aSeriesMapIt->second < static_cast<sal_Int32>(aNewSeriesVector.size()) )
548  aNewSeriesVector[aSeriesMapIt->second].mnAttachedAxis = aStyle.mnAttachedAxis;
549  }
550  }
551 
552  //overwrite new series style names with old series style name information
553  for (auto const& style : rStyleVector)
554  {
555  DataRowPointStyle aStyle(style);
556  if( aStyle.meType == DataRowPointStyle::DATA_SERIES )
557  {
558  auto aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
559  if( aSeriesMapEnd != aSeriesMapIt )
560  {
561  sal_Int32 nNewPointIndex = aSeriesMapIt->second;
562 
563  for (auto & newSeries : aNewSeriesVector)
564  newSeries.setSeriesStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
565  }
566  }
567  }
568 
569  //overwrite new series style names with point style name information
570  for (auto const& style : rStyleVector)
571  {
572  DataRowPointStyle aStyle(style);
573  if( aStyle.meType == DataRowPointStyle::DATA_POINT )
574  {
575  auto aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
576  if( aSeriesMapEnd != aSeriesMapIt )
577  {
578  sal_Int32 nNewPointIndex = aSeriesMapIt->second;
579  sal_Int32 nNewSeriesIndex = aStyle.m_nPointIndex;
580  sal_Int32 nRepeatCount = aStyle.m_nPointRepeat;
581 
582  while( nRepeatCount && (nNewSeriesIndex>=0) && (nNewSeriesIndex< static_cast<sal_Int32>(aNewSeriesVector.size()) ) )
583  {
584  NewDonutSeries& rNewSeries( aNewSeriesVector[nNewSeriesIndex] );
585  rNewSeries.setPointStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
586 
587  nRepeatCount--;
588  nNewSeriesIndex++;
589  }
590  }
591  }
592  }
593 
594  //put information from aNewSeriesVector to output parameter rStyleVector
595  rStyleVector.clear();
596 
597  for (auto & newSeries : aNewSeriesVector)
598  {
599  ::std::vector< DataRowPointStyle > aVector( newSeries.creatStyleVector() );
600  rStyleVector.insert(rStyleVector.end(),aVector.begin(),aVector.end());
601  }
602 }
603 
604 bool lcl_SpecialHandlingForDonutChartNeeded(
605  std::u16string_view rServiceName,
606  const SvXMLImport & rImport )
607 {
608  bool bResult = false;
609  if( rServiceName == u"com.sun.star.chart2.DonutChartType" )
610  {
612  }
613  return bResult;
614 }
615 
616 } // anonymous namespace
617 
619  const uno::Reference< chart2::XChartDocument >& xNewDoc
620  , const OUString& rRectangularRange
621  , css::chart::ChartDataRowSource eDataRowSource
622  , bool bRowHasLabels, bool bColHasLabels
623  , bool bSwitchOnLabelsAndCategoriesForOwnData
624  , const OUString& sColTrans
625  , const OUString& sRowTrans )
626 {
627  if( !xNewDoc.is() )
628  return;
629 
630  uno::Reference< chart2::XDiagram > xNewDia( xNewDoc->getFirstDiagram());
631  uno::Reference< chart2::data::XDataProvider > xDataProvider( xNewDoc->getDataProvider() );
632  if( !xNewDia.is() || !xDataProvider.is() )
633  return;
634 
635  bool bFirstCellAsLabel =
636  (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bRowHasLabels : bColHasLabels;
637  bool bHasCateories =
638  (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bColHasLabels : bRowHasLabels;
639 
640  if( bSwitchOnLabelsAndCategoriesForOwnData )
641  {
642  bFirstCellAsLabel = true;
643  bHasCateories = true;
644  }
645 
646  uno::Sequence< beans::PropertyValue > aArgs( 3 );
647  aArgs[0] = beans::PropertyValue(
648  "CellRangeRepresentation",
649  -1, uno::makeAny( rRectangularRange ),
650  beans::PropertyState_DIRECT_VALUE );
651  aArgs[1] = beans::PropertyValue(
652  "DataRowSource",
653  -1, uno::makeAny( eDataRowSource ),
654  beans::PropertyState_DIRECT_VALUE );
655  aArgs[2] = beans::PropertyValue(
656  "FirstCellAsLabel",
657  -1, uno::makeAny( bFirstCellAsLabel ),
658  beans::PropertyState_DIRECT_VALUE );
659 
660  if( !sColTrans.isEmpty() || !sRowTrans.isEmpty() )
661  {
662  aArgs.realloc( aArgs.getLength() + 1 );
663  aArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 1 ] = beans::PropertyValue(
664  "SequenceMapping",
665  -1, uno::makeAny( !sColTrans.isEmpty()
666  ? lcl_getNumberSequenceFromString( sColTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() )
667  : lcl_getNumberSequenceFromString( sRowTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() ) ),
668  beans::PropertyState_DIRECT_VALUE );
669  }
670 
671  //work around wrong writer ranges ( see Issue 58464 )
672  {
673  OUString aChartOleObjectName;
674  if( xNewDoc.is() )
675  {
676  utl::MediaDescriptor aMediaDescriptor( xNewDoc->getArgs() );
677 
678  utl::MediaDescriptor::const_iterator aIt(
679  aMediaDescriptor.find( OUString( "HierarchicalDocumentName" )));
680  if( aIt != aMediaDescriptor.end() )
681  {
682  aChartOleObjectName = (*aIt).second.get< OUString >();
683  }
684  }
685  if( !aChartOleObjectName.isEmpty() )
686  {
687  aArgs.realloc( aArgs.getLength() + 1 );
688  aArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 1 ] = beans::PropertyValue(
689  "ChartOleObjectName",
690  -1, uno::makeAny( aChartOleObjectName ),
691  beans::PropertyState_DIRECT_VALUE );
692  }
693  }
694 
695  uno::Reference< chart2::data::XDataSource > xDataSource(
696  xDataProvider->createDataSource( aArgs ));
697 
698  aArgs.realloc( aArgs.getLength() + 2 );
699  aArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 2 ] = beans::PropertyValue(
700  "HasCategories",
701  -1, uno::makeAny( bHasCateories ),
702  beans::PropertyState_DIRECT_VALUE );
703  aArgs[ 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  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  for( sal_Int32 i=0; i<nCandleStickCount; ++i )
985  {
986  sal_Int32 nSeriesIndex = i*nSeriesPerCandleStick;
987  if( bHasJapaneseCandlestick )
988  {
989  // open values
990  lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], "values-first");
991  aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
992  // low values
993  lcl_MoveDataToCandleStickSeries(
994  uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
995  aNewSeries[i], "values-min");
996  }
997  else
998  {
999  // low values
1000  lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], "values-min");
1001  aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
1002  }
1003  // high values
1004  lcl_MoveDataToCandleStickSeries(
1005  uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
1006  aNewSeries[i], "values-max");
1007  // close values
1008  lcl_MoveDataToCandleStickSeries(
1009  uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
1010  aNewSeries[i], "values-last");
1011  }
1012  xDSContainer->setDataSeries( aNewSeries );
1013  }
1014  }
1015  catch(const uno::Exception&)
1016  {
1017  TOOLS_WARN_EXCEPTION("xmloff.chart", "Exception while merging series for stock chart" );
1018  }
1019 }
1020 
1021 css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLChartContext::createFastChildContext(
1022  sal_Int32 nElement,
1023  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
1024 {
1025  SvXMLImportContext* pContext = nullptr;
1026  uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
1027  uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
1028 
1029  switch(nElement)
1030  {
1032  pContext = new SchXMLPlotAreaContext( mrImportHelper, GetImport(),
1041  break;
1042  case XML_ELEMENT(CHART, XML_TITLE):
1043  if( xDoc.is())
1044  {
1045  if( xProp.is())
1046  {
1047  xProp->setPropertyValue("HasMainTitle", uno::makeAny(true) );
1048  }
1049  uno::Reference< drawing::XShape > xTitleShape = xDoc->getTitle();
1050  pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1051  maMainTitle, xTitleShape );
1052  }
1053  break;
1055  if( xDoc.is())
1056  {
1057  if( xProp.is())
1058  {
1059  xProp->setPropertyValue("HasSubTitle", uno::makeAny(true) );
1060  }
1061  uno::Reference< drawing::XShape > xTitleShape = xDoc->getSubTitle();
1062  pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1063  maSubTitle, xTitleShape );
1064  }
1065  break;
1066  case XML_ELEMENT(CHART, XML_LEGEND):
1067  pContext = new SchXMLLegendContext( mrImportHelper, GetImport() );
1068  break;
1069  case XML_ELEMENT(TABLE, XML_TABLE):
1070  {
1071  SchXMLTableContext * pTableContext =
1073  m_bHasTableElement = true;
1074  // #i85913# take into account column- and row- mapping for
1075  // charts with own data only for those which were not copied
1076  // from a place where they got data from the container. Note,
1077  // that this requires the plot-area been read before the table
1078  // (which is required in the ODF spec)
1079  // Note: For stock charts and donut charts with special handling
1080  // the mapping must not be applied!
1081  if( msChartAddress.isEmpty() && !mbIsStockChart &&
1082  !lcl_SpecialHandlingForDonutChartNeeded(
1084  {
1085  if( !msColTrans.isEmpty() )
1086  {
1087  OSL_ASSERT( msRowTrans.isEmpty() );
1088  pTableContext->setColumnPermutation( lcl_getNumberSequenceFromString( msColTrans, true ));
1089  msColTrans.clear();
1090  }
1091  else if( !msRowTrans.isEmpty() )
1092  {
1093  pTableContext->setRowPermutation( lcl_getNumberSequenceFromString( msRowTrans, true ));
1094  msRowTrans.clear();
1095  }
1096  }
1097  pContext = pTableContext;
1098  }
1099  break;
1100 
1101  default:
1102  // try importing as an additional shape
1103  if( ! mxDrawPage.is())
1104  {
1105  uno::Reference< drawing::XDrawPageSupplier > xSupp( xDoc, uno::UNO_QUERY );
1106  if( xSupp.is())
1107  mxDrawPage = xSupp->getDrawPage();
1108 
1109  SAL_WARN_IF( !mxDrawPage.is(), "xmloff.chart", "Invalid Chart Page" );
1110  }
1111  if( mxDrawPage.is())
1113  GetImport(), nElement, xAttrList, mxDrawPage );
1114  break;
1115  }
1116 
1117  return pContext;
1118 }
1119 
1120 /*
1121  With a locked controller the following is done here:
1122  1. Hide title, subtitle, and legend.
1123  2. Set the size of the draw page.
1124  3. Set a (logically) empty data set.
1125  4. Set the chart type.
1126 */
1128  const OUString & rChartTypeServiceName // currently the old service name
1129  )
1130 {
1131  uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
1132  SAL_WARN_IF( !xDoc.is(), "xmloff.chart", "No valid document!" );
1133 
1134  // Remove Title and Diagram ("De-InitNew")
1135  uno::Reference< chart2::XChartDocument > xNewDoc( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
1136  if( xNewDoc.is())
1137  {
1138  xNewDoc->setFirstDiagram( nullptr );
1139  uno::Reference< chart2::XTitled > xTitled( xNewDoc, uno::UNO_QUERY );
1140  if( xTitled.is())
1141  xTitled->setTitleObject( nullptr );
1142  }
1143 
1144  // Set the chart type via setting the diagram.
1145  if( !rChartTypeServiceName.isEmpty() && xDoc.is())
1146  {
1147  uno::Reference< lang::XMultiServiceFactory > xFact( xDoc, uno::UNO_QUERY );
1148  if( xFact.is())
1149  {
1150  uno::Reference< chart::XDiagram > xDia( xFact->createInstance( rChartTypeServiceName ), uno::UNO_QUERY );
1151  if( xDia.is())
1152  xDoc->setDiagram( xDia );
1153  }
1154  }
1155 }
1156 
1158  OUString& rTitle,
1159  uno::Reference< drawing::XShape > const & xTitleShape ) :
1160  SvXMLImportContext( rImport ),
1161  mrImportHelper( rImpHelper ),
1162  mrTitle( rTitle ),
1163  mxTitleShape( xTitleShape )
1164 {
1165 }
1166 
1168 {}
1169 
1170 void SchXMLTitleContext::startFastElement( sal_Int32 /*nElement*/,
1171  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
1172 {
1173  css::awt::Point aPosition;
1174  bool bHasXPosition=false;
1175  bool bHasYPosition=false;
1176 
1177  for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
1178  {
1179  switch (aIter.getToken())
1180  {
1181  case XML_ELEMENT(SVG, XML_X):
1182  case XML_ELEMENT(SVG_COMPAT, XML_X):
1183  {
1185  aPosition.X, aIter.toView() );
1186  bHasXPosition = true;
1187  break;
1188  }
1189  case XML_ELEMENT(SVG, XML_Y):
1190  case XML_ELEMENT(SVG_COMPAT, XML_Y):
1191  {
1193  aPosition.Y, aIter.toView() );
1194  bHasYPosition = true;
1195  break;
1196  }
1198  msAutoStyleName = aIter.toString();
1199  break;
1200  default:
1201  XMLOFF_WARN_UNKNOWN("xmloff", aIter);
1202  }
1203  }
1204 
1205  if( mxTitleShape.is())
1206  {
1207  if( bHasXPosition && bHasYPosition )
1208  mxTitleShape->setPosition( aPosition );
1209 
1210  uno::Reference<beans::XPropertySet> xProp(mxTitleShape, uno::UNO_QUERY);
1212  }
1213 }
1214 
1215 css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLTitleContext::createFastChildContext(
1216  sal_Int32 nElement,
1217  const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
1218 {
1219  SvXMLImportContext* pContext = nullptr;
1220 
1221  if( nElement == XML_ELEMENT(TEXT, XML_P) ||
1222  nElement == XML_ELEMENT(LO_EXT, XML_P) )
1223  {
1224  pContext = new SchXMLParagraphContext( GetImport(), mrTitle );
1225  }
1226  else
1227  XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
1228 
1229  return pContext;
1230 }
1231 
1232 /* 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:59
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:113
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: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:3452
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:119
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)