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