1 // xlsxchart.cpp
2 
3 #include <QtGlobal>
4 #include <QString>
5 #include <QIODevice>
6 #include <QXmlStreamReader>
7 #include <QXmlStreamWriter>
8 #include <QDebug>
9 
10 #include "xlsxchart_p.h"
11 #include "xlsxworksheet.h"
12 #include "xlsxcellrange.h"
13 #include "xlsxutility_p.h"
14 
15 QT_BEGIN_NAMESPACE_XLSX
16 
ChartPrivate(Chart * q,Chart::CreateFlag flag)17 ChartPrivate::ChartPrivate(Chart *q, Chart::CreateFlag flag)
18     : AbstractOOXmlFilePrivate(q, flag), chartType(static_cast<Chart::ChartType>(0))
19 {
20 
21 }
22 
~ChartPrivate()23 ChartPrivate::~ChartPrivate()
24 {
25 }
26 
27 
28 
29 /*!
30  * \internal
31  */
Chart(AbstractSheet * parent,CreateFlag flag)32 Chart::Chart(AbstractSheet *parent, CreateFlag flag)
33     : AbstractOOXmlFile(new ChartPrivate(this, flag))
34 {
35     Q_D(Chart);
36 
37     d_func()->sheet = parent;
38 
39     // d->legendPos = Chart::ChartAxisPos::None;
40     d->legendPos = Chart::None;
41     d->legendOverlay = false;
42     d->majorGridlinesEnabled = false;
43     d->minorGridlinesEnabled = false;
44 }
45 
46 /*!
47  * Destroys the chart.
48  */
~Chart()49 Chart::~Chart()
50 {
51 }
52 
53 /*!
54  * Add the data series which is in the range \a range of the \a sheet.
55  */
addSeries(const CellRange & range,AbstractSheet * sheet,bool headerH,bool headerV,bool swapHeaders)56 void Chart::addSeries(const CellRange &range, AbstractSheet *sheet, bool headerH, bool headerV, bool swapHeaders)
57 {
58     Q_D(Chart);
59 
60     if (!range.isValid())
61         return;
62     if (sheet && sheet->sheetType() != AbstractSheet::ST_WorkSheet)
63         return;
64     if (!sheet && d->sheet->sheetType() != AbstractSheet::ST_WorkSheet)
65         return;
66 
67     QString sheetName = sheet ? sheet->sheetName() : d->sheet->sheetName();
68     //In case sheetName contains space or '
69     sheetName = escapeSheetName(sheetName);
70 
71     if (range.columnCount() == 1 || range.rowCount() == 1)
72     {
73         QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
74         series->numberDataSource_numRef = sheetName + QLatin1String("!") + range.toString(true, true);
75         d->seriesList.append(series);
76     }
77     else if ((range.columnCount() < range.rowCount()) || swapHeaders )
78     {
79         //Column based series
80         int firstDataRow = range.firstRow();
81         int firstDataColumn = range.firstColumn();
82 
83         QString axDataSouruce_numRef;
84         if (d->chartType == CT_ScatterChart || d->chartType == CT_BubbleChart)
85         {
86             firstDataColumn += 1;
87             CellRange subRange(range.firstRow(), range.firstColumn(), range.lastRow(), range.firstColumn());
88             axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
89         }
90 
91         if( headerH )
92         {
93             firstDataRow += 1;
94         }
95         if( headerV )
96         {
97             firstDataColumn += 1;
98         }
99 
100         for (int col=firstDataColumn; col<=range.lastColumn(); ++col)
101         {
102             CellRange subRange(firstDataRow, col, range.lastRow(), col);
103             QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
104             series->axDataSource_numRef = axDataSouruce_numRef;
105             series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
106 
107             if( headerH )
108             {
109                 CellRange subRange(range.firstRow(), col, range.firstRow(), col);
110                 series->headerH_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
111             }
112             else
113             {
114                 series->headerH_numRef = QString();
115             }
116             if( headerV )
117             {
118                 CellRange subRange(firstDataRow, range.firstColumn(), range.lastRow(), range.firstColumn());
119                 series->headerV_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
120             }
121             else
122             {
123                 series->headerV_numRef = QString();
124             }
125             series->swapHeader = swapHeaders;
126 
127             d->seriesList.append(series);
128         }
129 
130     }
131     else
132     {
133         //Row based series
134         int firstDataRow = range.firstRow();
135         int firstDataColumn = range.firstColumn();
136 
137         QString axDataSouruce_numRef;
138         if (d->chartType == CT_ScatterChart || d->chartType == CT_BubbleChart)
139         {
140             firstDataRow += 1;
141             CellRange subRange(range.firstRow(), range.firstColumn(), range.firstRow(), range.lastColumn());
142             axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
143         }
144 
145         if( headerH )
146         {
147             firstDataRow += 1;
148         }
149         if( headerV )
150         {
151             firstDataColumn += 1;
152         }
153 
154         for (int row=firstDataRow; row<=range.lastRow(); ++row)
155         {
156             CellRange subRange(row, firstDataColumn, row, range.lastColumn());
157             QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
158             series->axDataSource_numRef = axDataSouruce_numRef;
159             series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
160 
161             if( headerH )
162             {
163                 CellRange subRange(range.firstRow(), firstDataColumn, range.firstRow(), range.lastColumn());
164                 series->headerH_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
165             }
166             else
167             {
168                 series->headerH_numRef = QString();
169             }
170 
171             if( headerV )
172             {
173                 CellRange subRange(row, range.firstColumn(), row, range.firstColumn());
174                 series->headerV_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
175             }
176             else
177             {
178                 series->headerV_numRef = QString();
179             }
180             series->swapHeader = swapHeaders;
181 
182             d->seriesList.append(series);
183         }
184     }
185 }
186 
187 /*!
188  * Set the type of the chart to \a type
189  */
setChartType(ChartType type)190 void Chart::setChartType(ChartType type)
191 {
192     Q_D(Chart);
193 
194     d->chartType = type;
195 }
196 
197 /*!
198  * \internal
199  *
200  */
setChartStyle(int id)201 void Chart::setChartStyle(int id)
202 {
203     Q_UNUSED(id)
204     //!Todo
205 }
206 
setAxisTitle(Chart::ChartAxisPos pos,QString axisTitle)207 void Chart::setAxisTitle(Chart::ChartAxisPos pos, QString axisTitle)
208 {
209     Q_D(Chart);
210 
211     if ( axisTitle.isEmpty() )
212         return;
213 
214     // dev24 : fixed for old compiler
215     if ( pos == Chart::Left )
216     {
217         d->axisNames[ XlsxAxis::Left ] = axisTitle;
218     }
219     else if ( pos == Chart::Top )
220     {
221         d->axisNames[ XlsxAxis::Top ] = axisTitle;
222     }
223     else if ( pos == Chart::Right )
224     {
225         d->axisNames[ XlsxAxis::Right ] = axisTitle;
226     }
227     else if ( pos == Chart::Bottom )
228     {
229         d->axisNames[ XlsxAxis::Bottom ] = axisTitle;
230     }
231 
232 }
233 
234 // dev25
setChartTitle(QString strchartTitle)235 void Chart::setChartTitle(QString strchartTitle)
236 {
237     Q_D(Chart);
238 
239     d->chartTitle = strchartTitle;
240 }
241 
242 
setChartLegend(Chart::ChartAxisPos legendPos,bool overlay)243 void Chart::setChartLegend(Chart::ChartAxisPos legendPos, bool overlay)
244 {
245     Q_D(Chart);
246 
247     d->legendPos = legendPos;
248     d->legendOverlay = overlay;
249 }
250 
251 
setGridlinesEnable(bool majorGridlinesEnable,bool minorGridlinesEnable)252 void Chart::setGridlinesEnable(bool majorGridlinesEnable, bool minorGridlinesEnable)
253 {
254     Q_D(Chart);
255 
256     d->majorGridlinesEnabled = majorGridlinesEnable;
257     d->minorGridlinesEnabled = minorGridlinesEnable;
258 }
259 
260 
261 /*!
262  * \internal
263  */
saveToXmlFile(QIODevice * device) const264 void Chart::saveToXmlFile(QIODevice *device) const
265 {
266     Q_D(const Chart);
267 
268     /*
269         <chartSpace>
270             <chart>
271                 <view3D>
272                     <perspective val="30"/>
273                 </view3D>
274                 <plotArea>
275                     <layout/>
276                     <barChart>
277                     ...
278                     </barChart>
279                     <catAx/>
280                     <valAx/>
281                 </plotArea>
282                 <legend>
283                 ...
284                 </legend>
285             </chart>
286             <printSettings>
287             </printSettings>
288         </chartSpace>
289     */
290 
291     QXmlStreamWriter writer(device);
292 
293     writer.writeStartDocument(QStringLiteral("1.0"), true);
294 
295     // L.4.13.2.2 Chart
296     //
297     //  chartSpace is the root node, which contains an element defining the chart,
298     // and an element defining the print settings for the chart.
299 
300     writer.writeStartElement(QStringLiteral("c:chartSpace"));
301 
302     writer.writeAttribute(QStringLiteral("xmlns:c"),
303                           QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart"));
304     writer.writeAttribute(QStringLiteral("xmlns:a"),
305                           QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/main"));
306     writer.writeAttribute(QStringLiteral("xmlns:r"),
307                           QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
308 
309     /*
310     * chart is the root element for the chart. If the chart is a 3D chart,
311     * then a view3D element is contained, which specifies the 3D view.
312     * It then has a plot area, which defines a layout and contains an element
313     * that corresponds to, and defines, the type of chart.
314     */
315 
316     d->saveXmlChart(writer);
317 
318     writer.writeEndElement();// c:chartSpace
319     writer.writeEndDocument();
320 }
321 
322 /*!
323  * \internal
324  */
loadFromXmlFile(QIODevice * device)325 bool Chart::loadFromXmlFile(QIODevice *device)
326 {
327     Q_D(Chart);
328 
329     QXmlStreamReader reader(device);
330     while (!reader.atEnd())
331     {
332         reader.readNextStartElement();
333         if (reader.tokenType() == QXmlStreamReader::StartElement)
334         {
335             if (reader.name() == QLatin1String("chart"))
336             {
337                 if (!d->loadXmlChart(reader))
338                 {
339                     return false;
340                 }
341             }
342         }
343     }
344 
345     return true;
346 }
347 
348 
loadXmlChart(QXmlStreamReader & reader)349 bool ChartPrivate::loadXmlChart(QXmlStreamReader &reader)
350 {
351     Q_ASSERT(reader.name() == QLatin1String("chart"));
352 
353 //    qDebug() << "-------------- loadXmlChart";
354 
355     while (!reader.atEnd())
356     {
357         reader.readNextStartElement();
358 
359 //        qDebug() << "-------------1- " << reader.name();
360 
361         if (reader.tokenType() == QXmlStreamReader::StartElement)
362         {
363 
364             if (reader.name() == QLatin1String("plotArea"))
365             {
366                 if (!loadXmlPlotArea(reader))
367                 {
368                     return false;
369                 }
370             }
371             else if (reader.name() == QLatin1String("title"))
372             {
373                 //!Todo
374 
375                 if ( loadXmlChartTitle(reader) )
376                 {
377                 }
378 
379             }
380 //            else if (reader.name() == QLatin1String("legend"))
381 //            {
382 //                loadXmlChartLegend(reader);
383 //                qDebug() << "-------------- loadXmlChartLegend";
384 //            }
385         }
386         else if (reader.tokenType() == QXmlStreamReader::EndElement &&
387                  reader.name() == QLatin1String("chart") )
388         {
389             break;
390         }
391     }
392     return true;
393 }
394 
395 // TO DEBUG: loop is not work, when i looping second element.
396 /*
397 dchrt_CT_PlotArea =
398     element layout { dchrt_CT_Layout }?,
399     (element areaChart { dchrt_CT_AreaChart }
400         | element area3DChart { dchrt_ CT_Area3DChart }
401         | element lineChart { dchrt_CT_LineChart }
402         | element line3DChart { dchrt_CT_Line3DChart }
403         | element stockChart { dchrt_CT_StockChart }
404         | element radarChart { dchrt_CT_RadarChart }
405         | element scatterChart { dchrt_CT_ScatterChart }
406         | element pieChart { dchrt_CT_PieChart }
407         | element pie3DChart { dchrt_CT_Pie3DChart }
408         | element doughnutChart { dchrt_CT_DoughnutChart }
409         | element barChart { dchrt_CT_BarChart }
410         | element bar3DChart { dchrt_CT_Bar3DChart }
411         | element ofPieChart { dchrt_CT_OfPieChart }
412         | element surfaceChart { dchrt_CT_SurfaceChart }
413         | element surface3DChart { dchrt_CT_Surface3DChart }
414         | element bubbleChart { dchrt_CT_BubbleChart })+,
415     (element valAx { dchrt_CT_ValAx }
416         | element catAx { dchrt_CT_CatAx }
417         | element dateAx { dchrt_CT_DateAx }
418         | element serAx { dchrt_CT_SerAx })*,
419     element dTable { dchrt_CT_DTable }?,
420     element spPr { a_CT_ShapeProperties }?,
421     element extLst { dchrt_CT_ExtensionList }?
422  */
loadXmlPlotArea(QXmlStreamReader & reader)423 bool ChartPrivate::loadXmlPlotArea(QXmlStreamReader &reader)
424 {
425     Q_ASSERT(reader.name() == QLatin1String("plotArea"));
426 
427     // TO DEBUG:
428 
429     reader.readNext();
430 
431     while (!reader.atEnd())
432     {
433 //        qDebug() << "-------------2- " << reader.name();
434 
435         if (reader.isStartElement())
436         {
437             if (!loadXmlPlotAreaElement(reader))
438             {
439                 qDebug() << "[debug] failed to load plotarea element.";
440                 return false;
441             }
442             else if (reader.name() == QLatin1String("legend"))  // Why here?
443             {
444                 loadXmlChartLegend(reader);
445 //                qDebug() << "-------------- loadXmlChartLegend";
446             }
447 
448             reader.readNext();
449         }
450         else
451         {
452             reader.readNext();
453         }
454     }
455 
456     return true;
457 }
458 
loadXmlPlotAreaElement(QXmlStreamReader & reader)459 bool ChartPrivate::loadXmlPlotAreaElement(QXmlStreamReader &reader)
460 {
461     if (reader.name() == QLatin1String("layout"))
462     {
463         //!ToDo extract attributes
464         layout = readSubTree(reader);
465     }
466     else if (reader.name().endsWith(QLatin1String("Chart")))
467     {
468         // for pieChart, barChart, ... (choose one)
469         if ( !loadXmlXxxChart(reader) )
470         {
471             qDebug() << "[debug] failed to load chart";
472             return false;
473         }
474     }
475     else if (reader.name() == QLatin1String("catAx")) // choose one : catAx, dateAx, serAx, valAx
476     {
477         // qDebug() << "loadXmlAxisCatAx()";
478         loadXmlAxisCatAx(reader);
479     }
480     else if (reader.name() == QLatin1String("dateAx")) // choose one : catAx, dateAx, serAx, valAx
481     {
482         // qDebug() << "loadXmlAxisDateAx()";
483         loadXmlAxisDateAx(reader);
484     }
485     else if (reader.name() == QLatin1String("serAx")) // choose one : catAx, dateAx, serAx, valAx
486     {
487         // qDebug() << "loadXmlAxisSerAx()";
488         loadXmlAxisSerAx(reader);
489     }
490     else if (reader.name() == QLatin1String("valAx")) // choose one : catAx, dateAx, serAx, valAx
491     {
492         // qDebug() << "loadXmlAxisValAx()";
493         loadXmlAxisValAx(reader);
494     }
495     else if (reader.name() == QLatin1String("dTable"))
496     {
497         //!ToDo
498         // dTable "CT_DTable"
499         // reader.skipCurrentElement();
500     }
501     else if (reader.name() == QLatin1String("spPr"))
502     {
503         //!ToDo
504         // spPr "a:CT_ShapeProperties"
505         // reader.skipCurrentElement();
506     }
507     else if (reader.name() == QLatin1String("extLst"))
508     {
509         //!ToDo
510         // extLst "CT_ExtensionList"
511         // reader.skipCurrentElement();
512     }
513 
514     return true;
515 }
516 
loadXmlXxxChart(QXmlStreamReader & reader)517 bool ChartPrivate::loadXmlXxxChart(QXmlStreamReader &reader)
518 {
519     const auto& name = reader.name();
520 
521     if (name == QLatin1String("areaChart"))
522     {
523         chartType = Chart::CT_AreaChart;
524     }
525     else if (name == QLatin1String("area3DChart"))
526     {
527         chartType = Chart::CT_Area3DChart;
528     }
529     else if (name == QLatin1String("lineChart"))
530     {
531         chartType = Chart::CT_LineChart;
532     }
533     else if (name == QLatin1String("line3DChart"))
534     {
535         chartType = Chart::CT_Line3DChart;
536     }
537     else if (name == QLatin1String("stockChart"))
538     {
539         chartType = Chart::CT_StockChart;
540     }
541     else if (name == QLatin1String("radarChart"))
542     {
543         chartType = Chart::CT_RadarChart;
544     }
545     else if (name == QLatin1String("scatterChart"))
546     {
547         chartType = Chart::CT_ScatterChart;
548     }
549     else if (name == QLatin1String("pieChart"))
550     {
551         chartType = Chart::CT_PieChart;
552     }
553     else if (name == QLatin1String("pie3DChart"))
554     {
555         chartType = Chart::CT_Pie3DChart;
556     }
557     else if (name == QLatin1String("doughnutChart"))
558     {
559         chartType = Chart::CT_DoughnutChart;
560     }
561     else if (name == QLatin1String("barChart"))
562     {
563         chartType = Chart::CT_BarChart;
564     }
565     else if (name == QLatin1String("bar3DChart"))
566     {
567         chartType = Chart::CT_Bar3DChart;
568     }
569     else if (name == QLatin1String("ofPieChart"))
570     {
571         chartType = Chart::CT_OfPieChart;
572     }
573     else if (name == QLatin1String("surfaceChart"))
574     {
575         chartType = Chart::CT_SurfaceChart;
576     }
577     else if (name == QLatin1String("surface3DChart"))
578     {
579         chartType = Chart::CT_Surface3DChart;
580     }
581     else if (name == QLatin1String("bubbleChart"))
582     {
583         chartType = Chart::CT_BubbleChart;
584     }
585     else
586     {
587         qDebug() << "[undefined chart type] " << name;
588         chartType = Chart::CT_NoStatementChart;
589         return false;
590     }
591 
592     while( !reader.atEnd() )
593     {
594         reader.readNextStartElement();
595         if (reader.tokenType() == QXmlStreamReader::StartElement)
596         {
597             // dev57
598 
599             if ( reader.name() == QLatin1String("ser") )
600             {
601                 loadXmlSer(reader);
602             }
603             else if (reader.name() == QLatin1String("varyColors"))
604             {
605             }
606             else if (reader.name() == QLatin1String("barDir"))
607             {
608             }
609             else if (reader.name() == QLatin1String("axId"))
610             {
611                 //
612 
613             }
614             else if (reader.name() == QLatin1String("scatterStyle"))
615             {
616             }
617             else if (reader.name() == QLatin1String("holeSize"))
618             {
619             }
620             else
621             {
622             }
623 
624         }
625         else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
626                   reader.name() == name )
627         {
628             break;
629         }
630     }
631 
632     return true;
633 }
634 
loadXmlSer(QXmlStreamReader & reader)635 bool ChartPrivate::loadXmlSer(QXmlStreamReader &reader)
636 {
637     Q_ASSERT(reader.name() == QLatin1String("ser"));
638 
639     QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
640     seriesList.append(series);
641 
642     while ( !reader.atEnd() &&
643             !(reader.tokenType() == QXmlStreamReader::EndElement &&
644              reader.name() == QLatin1String("ser")) )
645     {
646         if (reader.readNextStartElement())
647         {
648             //TODO beide Header noch auswerten RTR 2019.11
649             const auto& name = reader.name();
650             if ( name == QLatin1String("tx") )
651             {
652                 while ( !reader.atEnd() &&
653                         !(reader.tokenType() == QXmlStreamReader::EndElement &&
654                          reader.name() == name))
655                 {
656                     if (reader.readNextStartElement())
657                     {
658                         if (reader.name() == QLatin1String("strRef"))
659                             series->headerV_numRef = loadXmlStrRef(reader);
660                     }
661                 }
662             }
663             else if ( name == QLatin1String("cat") ||
664                  name == QLatin1String("xVal") )
665             {
666                 while ( !reader.atEnd() &&
667                         !(reader.tokenType() == QXmlStreamReader::EndElement &&
668                          reader.name() == name))
669                 {
670                     if (reader.readNextStartElement())
671                     {
672                         if (reader.name() == QLatin1String("numRef"))
673                             series->axDataSource_numRef = loadXmlNumRef(reader);
674                         else
675                         if (reader.name() == QLatin1String("strRef"))
676                             series->headerH_numRef = loadXmlStrRef(reader);
677                     }
678                 }
679             }
680             else if (name == QLatin1String("val") || name == QLatin1String("yVal"))
681             {
682                 while ( !reader.atEnd() &&
683                         !(reader.tokenType() == QXmlStreamReader::EndElement &&
684                         reader.name() == name))
685                 {
686                     if (reader.readNextStartElement())
687                     {
688                         if (reader.name() == QLatin1String("numRef"))
689                             series->numberDataSource_numRef = loadXmlNumRef(reader);
690                     }
691                 }
692             }
693             else if (name == QLatin1String("extLst"))
694             {
695                 while ( !reader.atEnd() &&
696                         !(reader.tokenType() == QXmlStreamReader::EndElement &&
697                          reader.name() == name))
698                 {
699                     reader.readNextStartElement();
700                 }
701             }
702         }
703     }
704 
705     return true;
706 }
707 
708 
loadXmlNumRef(QXmlStreamReader & reader)709 QString ChartPrivate::loadXmlNumRef(QXmlStreamReader &reader)
710 {
711     Q_ASSERT(reader.name() == QLatin1String("numRef"));
712 
713     while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
714                                 && reader.name() == QLatin1String("numRef")))
715     {
716         if (reader.readNextStartElement())
717         {
718             if (reader.name() == QLatin1String("f"))
719                 return reader.readElementText();
720         }
721     }
722 
723     return QString();
724 }
725 
726 
loadXmlStrRef(QXmlStreamReader & reader)727 QString ChartPrivate::loadXmlStrRef(QXmlStreamReader &reader)
728 {
729     Q_ASSERT(reader.name() == QLatin1String("strRef"));
730 
731     while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
732                                 && reader.name() == QLatin1String("strRef")))
733     {
734         if (reader.readNextStartElement())
735         {
736             if (reader.name() == QLatin1String("f"))
737                 return reader.readElementText();
738         }
739     }
740 
741     return QString();
742 }
743 
744 
saveXmlChart(QXmlStreamWriter & writer) const745 void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const
746 {
747     //----------------------------------------------------
748     // c:chart
749     writer.writeStartElement(QStringLiteral("c:chart"));
750 
751     //----------------------------------------------------
752     // c:title
753 
754     saveXmlChartTitle(writer); // write 'chart title'
755 
756     //----------------------------------------------------
757     // c:plotArea
758 
759     writer.writeStartElement(QStringLiteral("c:plotArea"));
760 
761     // a little workaround for Start- and EndElement with starting ">" and ending without ">"
762     writer.device()->write("><c:layout>"); //layout
763     writer.device()->write(layout.toUtf8());
764     writer.device()->write("</c:layout"); //layout
765 
766     // dev35
767     switch (chartType)
768     {
769         case Chart::CT_AreaChart:       saveXmlAreaChart(writer); break;
770         case Chart::CT_Area3DChart:     saveXmlAreaChart(writer); break;
771         case Chart::CT_LineChart:       saveXmlLineChart(writer); break;
772         case Chart::CT_Line3DChart:     saveXmlLineChart(writer); break;
773         case Chart::CT_StockChart: break;
774         case Chart::CT_RadarChart: break;
775         case Chart::CT_ScatterChart:    saveXmlScatterChart(writer); break;
776         case Chart::CT_PieChart:        saveXmlPieChart(writer); break;
777         case Chart::CT_Pie3DChart:      saveXmlPieChart(writer); break;
778         case Chart::CT_DoughnutChart:   saveXmlDoughnutChart(writer); break;
779         case Chart::CT_BarChart:        saveXmlBarChart(writer); break;
780         case Chart::CT_Bar3DChart:      saveXmlBarChart(writer); break;
781         case Chart::CT_OfPieChart: break;
782         case Chart::CT_SurfaceChart:  break;
783         case Chart::CT_Surface3DChart: break;
784         case Chart::CT_BubbleChart:  break;
785         default:  break;
786     }
787 
788     saveXmlAxis(writer); // c:catAx, c:valAx, c:serAx, c:dateAx (choose one)
789 
790     //!TODO: write element
791     // c:dTable CT_DTable
792     // c:spPr   CT_ShapeProperties
793     // c:extLst CT_ExtensionList
794 
795     writer.writeEndElement(); // c:plotArea
796 
797     // c:legend
798     saveXmlChartLegend(writer); // c:legend
799 
800     writer.writeEndElement(); // c:chart
801 }
802 
loadXmlChartTitle(QXmlStreamReader & reader)803 bool ChartPrivate::loadXmlChartTitle(QXmlStreamReader &reader)
804 {
805     //!TODO : load chart title
806 
807     Q_ASSERT(reader.name() == QLatin1String("title"));
808 
809     while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
810                                 && reader.name() == QLatin1String("title")))
811     {
812         if (reader.readNextStartElement())
813         {
814             if (reader.name() == QLatin1String("tx")) // c:tx
815                 return loadXmlChartTitleTx(reader);
816         }
817     }
818 
819     return false;
820 }
821 
loadXmlChartTitleTx(QXmlStreamReader & reader)822 bool ChartPrivate::loadXmlChartTitleTx(QXmlStreamReader &reader)
823 {
824     Q_ASSERT(reader.name() == QLatin1String("tx"));
825 
826     while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
827                                 && reader.name() == QLatin1String("tx")))
828     {
829         if (reader.readNextStartElement())
830         {
831             if (reader.name() == QLatin1String("rich")) // c:rich
832                 return loadXmlChartTitleTxRich(reader);
833         }
834     }
835 
836     return false;
837 }
838 
loadXmlChartTitleTxRich(QXmlStreamReader & reader)839 bool ChartPrivate::loadXmlChartTitleTxRich(QXmlStreamReader &reader)
840 {
841     Q_ASSERT(reader.name() == QLatin1String("rich"));
842 
843     while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
844                                 && reader.name() == QLatin1String("rich")))
845     {
846         if (reader.readNextStartElement())
847         {
848             if (reader.name() == QLatin1String("p")) // a:p
849                 return loadXmlChartTitleTxRichP(reader);
850         }
851     }
852 
853     return false;
854 }
855 
loadXmlChartTitleTxRichP(QXmlStreamReader & reader)856 bool ChartPrivate::loadXmlChartTitleTxRichP(QXmlStreamReader &reader)
857 {
858     Q_ASSERT(reader.name() == QLatin1String("p"));
859 
860     while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
861                                 && reader.name() == QLatin1String("p")))
862     {
863         if (reader.readNextStartElement())
864         {
865             if (reader.name() == QLatin1String("r")) // a:r
866                 return loadXmlChartTitleTxRichP_R(reader);
867         }
868     }
869 
870     return false;
871 }
872 
loadXmlChartTitleTxRichP_R(QXmlStreamReader & reader)873 bool ChartPrivate::loadXmlChartTitleTxRichP_R(QXmlStreamReader &reader)
874 {
875     Q_ASSERT(reader.name() == QLatin1String("r"));
876 
877     while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
878                                 && reader.name() == QLatin1String("r")))
879     {
880         if (reader.readNextStartElement())
881         {
882             if (reader.name() == QLatin1String("t")) // a:t
883             {
884                 QString textValue = reader.readElementText();
885                 this->chartTitle = textValue;
886                 return true;
887             }
888         }
889     }
890 
891     return false;
892 }
893 
894 
895 // write 'chart title'
saveXmlChartTitle(QXmlStreamWriter & writer) const896 void ChartPrivate::saveXmlChartTitle(QXmlStreamWriter &writer) const
897 {
898     if ( chartTitle.isEmpty() )
899         return;
900 
901     writer.writeStartElement(QStringLiteral("c:title"));
902     /*
903     <xsd:complexType name="CT_Title">
904         <xsd:sequence>
905             <xsd:element name="tx"      type="CT_Tx"                minOccurs="0" maxOccurs="1"/>
906             <xsd:element name="layout"  type="CT_Layout"            minOccurs="0" maxOccurs="1"/>
907             <xsd:element name="overlay" type="CT_Boolean"           minOccurs="0" maxOccurs="1"/>
908             <xsd:element name="spPr"    type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
909             <xsd:element name="txPr"    type="a:CT_TextBody"        minOccurs="0" maxOccurs="1"/>
910             <xsd:element name="extLst"  type="CT_ExtensionList"     minOccurs="0" maxOccurs="1"/>
911         </xsd:sequence>
912     </xsd:complexType>
913     */
914 
915         writer.writeStartElement(QStringLiteral("c:tx"));
916         /*
917         <xsd:complexType name="CT_Tx">
918             <xsd:sequence>
919                 <xsd:choice     minOccurs="1"   maxOccurs="1">
920                 <xsd:element    name="strRef"   type="CT_StrRef"        minOccurs="1" maxOccurs="1"/>
921                 <xsd:element    name="rich"     type="a:CT_TextBody"    minOccurs="1" maxOccurs="1"/>
922                 </xsd:choice>
923             </xsd:sequence>
924         </xsd:complexType>
925         */
926 
927             writer.writeStartElement(QStringLiteral("c:rich"));
928             /*
929             <xsd:complexType name="CT_TextBody">
930                 <xsd:sequence>
931                     <xsd:element name="bodyPr"      type="CT_TextBodyProperties"    minOccurs=" 1"  maxOccurs="1"/>
932                     <xsd:element name="lstStyle"    type="CT_TextListStyle"         minOccurs="0"   maxOccurs="1"/>
933                     <xsd:element name="p"           type="CT_TextParagraph"         minOccurs="1"   maxOccurs="unbounded"/>
934                 </xsd:sequence>
935             </xsd:complexType>
936             */
937 
938                 writer.writeEmptyElement(QStringLiteral("a:bodyPr")); // <a:bodyPr/>
939                 /*
940                 <xsd:complexType name="CT_TextBodyProperties">
941                     <xsd:sequence>
942                         <xsd:element name="prstTxWarp" type="CT_PresetTextShape" minOccurs="0" maxOccurs="1"/>
943                         <xsd:group ref="EG_TextAutofit" minOccurs="0" maxOccurs="1"/>
944                         <xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0" maxOccurs="1"/>
945                         <xsd:group ref="EG_Text3D" minOccurs="0" maxOccurs="1"/>
946                         <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
947                     </xsd:sequence>
948                     <xsd:attribute name="rot" type="ST_Angle" use="optional"/>
949                     <xsd:attribute name="spcFirstLastPara" type="xsd:boolean" use="optional"/>
950                     <xsd:attribute name="vertOverflow" type="ST_TextVertOverflowType" use="optional"/>
951                     <xsd:attribute name="horzOverflow" type="ST_TextHorzOverflowType" use="optional"/>
952                     <xsd:attribute name="vert" type="ST_TextVerticalType" use="optional"/>
953                     <xsd:attribute name="wrap" type="ST_TextWrappingType" use="optional"/>
954                     <xsd:attribute name="lIns" type="ST_Coordinate32" use="optional"/>
955                     <xsd:attribute name="tIns" type="ST_Coordinate32" use="optional"/>
956                     <xsd:attribute name="rIns" type="ST_Coordinate32" use="optional"/>
957                     <xsd:attribute name="bIns" type="ST_Coordinate32" use="optional"/>
958                     <xsd:attribute name="numCol" type="ST_TextColumnCount" use="optional"/>
959                     <xsd:attribute name="spcCol" type="ST_PositiveCoordinate32" use="optional"/>
960                     <xsd:attribute name="rtlCol" type="xsd:boolean" use="optional"/>
961                     <xsd:attribute name="fromWordArt" type="xsd:boolean" use="optional"/>
962                     <xsd:attribute name="anchor" type="ST_TextAnchoringType" use="optional"/>
963                     <xsd:attribute name="anchorCtr" type="xsd:boolean" use="optional"/>
964                     <xsd:attribute name="forceAA" type="xsd:boolean" use="optional"/>
965                     <xsd:attribute name="upright" type="xsd:boolean" use="optional" default="false"/>
966                     <xsd:attribute name="compatLnSpc" type="xsd:boolean" use="optional"/>
967                 </xsd:complexType>
968                  */
969 
970                 writer.writeEmptyElement(QStringLiteral("a:lstStyle")); // <a:lstStyle/>
971 
972                 writer.writeStartElement(QStringLiteral("a:p"));
973                 /*
974                 <xsd:complexType name="CT_TextParagraph">
975                     <xsd:sequence>
976                         <xsd:element    name="pPr"          type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/>
977                         <xsd:group      ref="EG_TextRun"    minOccurs="0" maxOccurs="unbounded"/>
978                         <xsd:element    name="endParaRPr"   type="CT_TextCharacterProperties" minOccurs="0"
979                         maxOccurs="1"/>
980                     </xsd:sequence>
981                 </xsd:complexType>
982                  */
983 
984                     // <a:pPr lvl="0">
985                     writer.writeStartElement(QStringLiteral("a:pPr"));
986 
987                         writer.writeAttribute(QStringLiteral("lvl"), QStringLiteral("0"));
988 
989                         // <a:defRPr b="0"/>
990                         writer.writeStartElement(QStringLiteral("a:defRPr"));
991 
992                             writer.writeAttribute(QStringLiteral("b"), QStringLiteral("0"));
993 
994                         writer.writeEndElement();  // a:defRPr
995 
996                     writer.writeEndElement();  // a:pPr
997 
998                 /*
999                 <xsd:group name="EG_TextRun">
1000                     <xsd:choice>
1001                         <xsd:element name="r"   type="CT_RegularTextRun"/>
1002                         <xsd:element name="br"  type="CT_TextLineBreak"/>
1003                         <xsd:element name="fld" type="CT_TextField"/>
1004                     </xsd:choice>
1005                 </xsd:group>
1006                 */
1007 
1008                 writer.writeStartElement(QStringLiteral("a:r"));
1009                 /*
1010                 <xsd:complexType name="CT_RegularTextRun">
1011                     <xsd:sequence>
1012                         <xsd:element name="rPr" type="CT_TextCharacterProperties" minOccurs="0" maxOccurs="1"/>
1013                         <xsd:element name="t"   type="xsd:string" minOccurs="1" maxOccurs="1"/>
1014                     </xsd:sequence>
1015                 </xsd:complexType>
1016                  */
1017 
1018                     // <a:t>chart name</a:t>
1019                     writer.writeTextElement(QStringLiteral("a:t"), chartTitle);
1020 
1021                 writer.writeEndElement();  // a:r
1022 
1023                 writer.writeEndElement();  // a:p
1024 
1025             writer.writeEndElement();  // c:rich
1026 
1027         writer.writeEndElement();  // c:tx
1028 
1029         // <c:overlay val="0"/>
1030         writer.writeStartElement(QStringLiteral("c:overlay"));
1031             writer.writeAttribute(QStringLiteral("val"), QStringLiteral("0"));
1032         writer.writeEndElement();  // c:overlay
1033 
1034     writer.writeEndElement();  // c:title
1035 }
1036 // }}
1037 
1038 
1039 // write 'chart legend'
saveXmlChartLegend(QXmlStreamWriter & writer) const1040 void ChartPrivate::saveXmlChartLegend(QXmlStreamWriter &writer) const
1041 {
1042     if ( legendPos == Chart::None )
1043         return;
1044 
1045 //    <c:legend>
1046 //    <c:legendPos val="r"/>
1047 //    <c:overlay val="0"/>
1048 //    </c:legend>
1049 
1050     writer.writeStartElement(QStringLiteral("c:legend"));
1051 
1052         writer.writeStartElement(QStringLiteral("c:legendPos"));
1053 
1054             QString pos;
1055             switch( legendPos )
1056             {
1057                 //case Chart::ChartAxisPos::Right:
1058                 case Chart::Right :
1059                     pos = QStringLiteral("r");
1060                     break;
1061 
1062                 // case Chart::ChartAxisPos::Left:
1063                 case Chart::Left :
1064                     pos = QStringLiteral("l");
1065                     break;
1066 
1067                 // case Chart::ChartAxisPos::Top:
1068                 case Chart::Top :
1069                     pos = QStringLiteral("t");
1070                     break;
1071 
1072                 // case Chart::ChartAxisPos::Bottom:
1073                 case Chart::Bottom :
1074                     pos = QStringLiteral("b");
1075                     break;
1076 
1077                 default:
1078                     pos = QStringLiteral("r");
1079                     break;
1080             }
1081 
1082             writer.writeAttribute(QStringLiteral("val"), pos);
1083 
1084         writer.writeEndElement();  // c:legendPos
1085 
1086         writer.writeStartElement(QStringLiteral("c:overlay"));
1087 
1088             if( legendOverlay )
1089             {
1090                 writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1"));
1091             }
1092             else
1093             {
1094                 writer.writeAttribute(QStringLiteral("val"), QStringLiteral("0"));
1095             }
1096 
1097         writer.writeEndElement();  // c:overlay
1098 
1099     writer.writeEndElement(); // c:legend
1100 }
1101 
1102 
saveXmlPieChart(QXmlStreamWriter & writer) const1103 void ChartPrivate::saveXmlPieChart(QXmlStreamWriter &writer) const
1104 {
1105     QString name = chartType == Chart::CT_PieChart ? QStringLiteral("c:pieChart") : QStringLiteral("c:pie3DChart");
1106 
1107     writer.writeStartElement(name);
1108 
1109     //Do the same behavior as Excel, Pie prefer varyColors
1110     writer.writeEmptyElement(QStringLiteral("c:varyColors"));
1111     writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1"));
1112 
1113     for (int i=0; i<seriesList.size(); ++i)
1114         saveXmlSer(writer, seriesList[i].data(), i);
1115 
1116     writer.writeEndElement(); //pieChart, pie3DChart
1117 }
1118 
saveXmlBarChart(QXmlStreamWriter & writer) const1119 void ChartPrivate::saveXmlBarChart(QXmlStreamWriter &writer) const
1120 {
1121     QString name = chartType == Chart::CT_BarChart ? QStringLiteral("c:barChart") : QStringLiteral("c:bar3DChart");
1122 
1123     writer.writeStartElement(name);
1124 
1125     writer.writeEmptyElement(QStringLiteral("c:barDir"));
1126     writer.writeAttribute(QStringLiteral("val"), QStringLiteral("col"));
1127 
1128     for ( int i = 0 ; i < seriesList.size() ; ++i )
1129     {
1130         saveXmlSer(writer, seriesList[i].data(), i);
1131     }
1132 
1133     if ( axisList.isEmpty() )
1134     {
1135         const_cast<ChartPrivate*>(this)->axisList.append(
1136                     QSharedPointer<XlsxAxis>(
1137                         new XlsxAxis( XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1, axisNames[XlsxAxis::Bottom] )));
1138 
1139         const_cast<ChartPrivate*>(this)->axisList.append(
1140                     QSharedPointer<XlsxAxis>(
1141                         new XlsxAxis( XlsxAxis::T_Val, XlsxAxis::Left, 1, 0, axisNames[XlsxAxis::Left] )));
1142     }
1143 
1144 
1145     // Note: Bar3D have 2~3 axes
1146     // int axisListSize = axisList.size();
1147     // [dev62]
1148     // Q_ASSERT( axisListSize == 2 ||
1149     //          ( axisListSize == 3 && chartType == Chart::CT_Bar3DChart ) );
1150 
1151     for ( int i = 0 ; i < axisList.size() ; ++i )
1152     {
1153         writer.writeEmptyElement(QStringLiteral("c:axId"));
1154         writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
1155     }
1156 
1157     writer.writeEndElement(); //barChart, bar3DChart
1158 }
1159 
saveXmlLineChart(QXmlStreamWriter & writer) const1160 void ChartPrivate::saveXmlLineChart(QXmlStreamWriter &writer) const
1161 {
1162     QString name = chartType==Chart::CT_LineChart ? QStringLiteral("c:lineChart") : QStringLiteral("c:line3DChart");
1163 
1164     writer.writeStartElement(name);
1165 
1166     // writer.writeEmptyElement(QStringLiteral("grouping")); // dev22
1167 
1168     for (int i=0; i<seriesList.size(); ++i)
1169         saveXmlSer(writer, seriesList[i].data(), i);
1170 
1171     if (axisList.isEmpty())
1172     {
1173         const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1, axisNames[XlsxAxis::Bottom] )));
1174         const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0, axisNames[XlsxAxis::Left] )));
1175         if (chartType==Chart::CT_Line3DChart)
1176             const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Ser, XlsxAxis::Bottom, 2, 0)));
1177     }
1178 
1179     Q_ASSERT((axisList.size()==2||chartType==Chart::CT_LineChart)|| (axisList.size()==3 && chartType==Chart::CT_Line3DChart));
1180 
1181     for (int i=0; i<axisList.size(); ++i)
1182     {
1183         writer.writeEmptyElement(QStringLiteral("c:axId"));
1184         writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
1185     }
1186 
1187     writer.writeEndElement(); //lineChart, line3DChart
1188 }
1189 
saveXmlScatterChart(QXmlStreamWriter & writer) const1190 void ChartPrivate::saveXmlScatterChart(QXmlStreamWriter &writer) const
1191 {
1192     const QString name = QStringLiteral("c:scatterChart");
1193 
1194     writer.writeStartElement(name);
1195 
1196     writer.writeEmptyElement(QStringLiteral("c:scatterStyle"));
1197 
1198     for (int i=0; i<seriesList.size(); ++i)
1199         saveXmlSer(writer, seriesList[i].data(), i);
1200 
1201     if (axisList.isEmpty())
1202     {
1203         const_cast<ChartPrivate*>(this)->axisList.append(
1204                     QSharedPointer<XlsxAxis>(
1205                         new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Bottom, 0, 1, axisNames[XlsxAxis::Bottom] )));
1206         const_cast<ChartPrivate*>(this)->axisList.append(
1207                     QSharedPointer<XlsxAxis>(
1208                         new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0, axisNames[XlsxAxis::Left] )));
1209     }
1210 
1211     int axisListSize = axisList.size();
1212     Q_ASSERT(axisListSize == 2);
1213 
1214     for (int i=0; i<axisList.size(); ++i)
1215     {
1216         writer.writeEmptyElement(QStringLiteral("c:axId"));
1217         writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
1218     }
1219 
1220     writer.writeEndElement(); //c:scatterChart
1221 }
1222 
saveXmlAreaChart(QXmlStreamWriter & writer) const1223 void ChartPrivate::saveXmlAreaChart(QXmlStreamWriter &writer) const
1224 {
1225     QString name = chartType==Chart::CT_AreaChart ? QStringLiteral("c:areaChart") : QStringLiteral("c:area3DChart");
1226 
1227     writer.writeStartElement(name);
1228 
1229     // writer.writeEmptyElement(QStringLiteral("grouping")); // dev22
1230 
1231     for (int i=0; i<seriesList.size(); ++i)
1232         saveXmlSer(writer, seriesList[i].data(), i);
1233 
1234     if (axisList.isEmpty())
1235     {
1236         const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1)));
1237         const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0)));
1238     }
1239 
1240     //Note: Area3D have 2~3 axes
1241     Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Area3DChart));
1242 
1243     for (int i=0; i<axisList.size(); ++i)
1244     {
1245         writer.writeEmptyElement(QStringLiteral("c:axId"));
1246         writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
1247     }
1248 
1249     writer.writeEndElement(); //lineChart, line3DChart
1250 }
1251 
saveXmlDoughnutChart(QXmlStreamWriter & writer) const1252 void ChartPrivate::saveXmlDoughnutChart(QXmlStreamWriter &writer) const
1253 {
1254     QString name = QStringLiteral("c:doughnutChart");
1255 
1256     writer.writeStartElement(name);
1257 
1258     writer.writeEmptyElement(QStringLiteral("c:varyColors"));
1259     writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1"));
1260 
1261     for (int i=0; i<seriesList.size(); ++i)
1262         saveXmlSer(writer, seriesList[i].data(), i);
1263 
1264     writer.writeStartElement(QStringLiteral("c:holeSize"));
1265     writer.writeAttribute(QStringLiteral("val"), QString::number(50));
1266 
1267     writer.writeEndElement();
1268 }
1269 
saveXmlSer(QXmlStreamWriter & writer,XlsxSeries * ser,int id) const1270 void ChartPrivate::saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const
1271 {
1272 
1273     writer.writeStartElement(QStringLiteral("c:ser"));
1274     writer.writeEmptyElement(QStringLiteral("c:idx"));
1275     writer.writeAttribute(QStringLiteral("val"), QString::number(id));
1276     writer.writeEmptyElement(QStringLiteral("c:order"));
1277     writer.writeAttribute(QStringLiteral("val"), QString::number(id));
1278 
1279     QString header1;
1280     QString header2;
1281     if( ser->swapHeader )
1282     {
1283         header1 = ser->headerH_numRef;
1284         header2 = ser->headerV_numRef;
1285     }
1286     else
1287     {
1288         header1 = ser->headerV_numRef;
1289         header2 = ser->headerH_numRef;
1290     }
1291 
1292     if( !header1.isEmpty() )
1293     {
1294         writer.writeStartElement(QStringLiteral("c:tx"));
1295         writer.writeStartElement(QStringLiteral("c:strRef"));
1296         writer.writeTextElement(QStringLiteral("c:f"), header1);
1297         writer.writeEndElement();
1298         writer.writeEndElement();
1299     }
1300     if( !header2.isEmpty() )
1301     {
1302         writer.writeStartElement(QStringLiteral("c:cat"));
1303         writer.writeStartElement(QStringLiteral("c:strRef"));
1304         writer.writeTextElement(QStringLiteral("c:f"), header2);
1305         writer.writeEndElement();
1306         writer.writeEndElement();
1307     }
1308 
1309 #if 0
1310     if (!ser->axDataSource_numRef.isEmpty())
1311     {
1312         if (chartType == Chart::CT_ScatterChart || chartType == Chart::CT_BubbleChart)
1313         {
1314             writer.writeStartElement(QStringLiteral("c:xVal"));
1315         }
1316         else
1317         {
1318             writer.writeStartElement(QStringLiteral("c:cat"));
1319         }
1320 
1321         writer.writeStartElement(QStringLiteral("c:numRef"));
1322         writer.writeTextElement(QStringLiteral("c:f"), ser->axDataSource_numRef);
1323         writer.writeEndElement();//c:numRef
1324         writer.writeEndElement();//c:cat or c:xVal
1325     }
1326 #endif
1327 
1328     if (!ser->numberDataSource_numRef.isEmpty())
1329     {
1330         if (chartType == Chart::CT_ScatterChart || chartType == Chart::CT_BubbleChart)
1331             writer.writeStartElement(QStringLiteral("c:yVal"));
1332         else
1333             writer.writeStartElement(QStringLiteral("c:val"));
1334         writer.writeStartElement(QStringLiteral("c:numRef"));
1335         writer.writeTextElement(QStringLiteral("c:f"), ser->numberDataSource_numRef);
1336         writer.writeEndElement();//c:numRef
1337         writer.writeEndElement();//c:val or c:yVal
1338     }
1339 
1340     writer.writeEndElement();//c:ser
1341 }
1342 
loadXmlAxisCatAx(QXmlStreamReader & reader)1343 bool ChartPrivate::loadXmlAxisCatAx(QXmlStreamReader &reader)
1344 {
1345 
1346     XlsxAxis* axis = new XlsxAxis();
1347     axis->type = XlsxAxis::T_Cat;
1348     axisList.append( QSharedPointer<XlsxAxis>(axis) );
1349 
1350     // load EG_AxShared
1351     if ( ! loadXmlAxisEG_AxShared( reader, axis ) )
1352     {
1353         qDebug() << "failed to load EG_AxShared";
1354         return false;
1355     }
1356 
1357     //!TODO: load element
1358     // auto
1359     // lblAlgn
1360     // lblOffset
1361     // tickLblSkip
1362     // tickMarkSkip
1363     // noMultiLvlLbl
1364     // extLst
1365 
1366     return true;
1367 }
1368 
loadXmlAxisDateAx(QXmlStreamReader & reader)1369 bool ChartPrivate::loadXmlAxisDateAx(QXmlStreamReader &reader)
1370 {
1371 
1372     XlsxAxis* axis = new XlsxAxis();
1373     axis->type = XlsxAxis::T_Date;
1374     axisList.append( QSharedPointer<XlsxAxis>(axis) );
1375 
1376     // load EG_AxShared
1377     if ( ! loadXmlAxisEG_AxShared( reader, axis ) )
1378     {
1379         qDebug() << "failed to load EG_AxShared";
1380         return false;
1381     }
1382 
1383     //!TODO: load element
1384     // auto
1385     // lblOffset
1386     // baseTimeUnit
1387     // majorUnit
1388     // majorTimeUnit
1389     // minorUnit
1390     // minorTimeUnit
1391     // extLst
1392 
1393     return true;
1394 }
1395 
loadXmlAxisSerAx(QXmlStreamReader & reader)1396 bool ChartPrivate::loadXmlAxisSerAx(QXmlStreamReader &reader)
1397 {
1398 
1399     XlsxAxis* axis = new XlsxAxis();
1400     axis->type = XlsxAxis::T_Ser;
1401     axisList.append( QSharedPointer<XlsxAxis>(axis) );
1402 
1403     // load EG_AxShared
1404     if ( ! loadXmlAxisEG_AxShared( reader, axis ) )
1405     {
1406         qDebug() << "failed to load EG_AxShared";
1407         return false;
1408     }
1409 
1410     //!TODO: load element
1411     // tickLblSkip
1412     // tickMarkSkip
1413     // extLst
1414 
1415     return true;
1416 }
1417 
loadXmlAxisValAx(QXmlStreamReader & reader)1418 bool ChartPrivate::loadXmlAxisValAx(QXmlStreamReader &reader)
1419 {
1420     Q_ASSERT(reader.name() == QLatin1String("valAx"));
1421 
1422     XlsxAxis* axis = new XlsxAxis();
1423     axis->type = XlsxAxis::T_Val;
1424     axisList.append( QSharedPointer<XlsxAxis>(axis) );
1425 
1426     if ( ! loadXmlAxisEG_AxShared( reader, axis ) )
1427     {
1428         qDebug() << "failed to load EG_AxShared";
1429         return false;
1430     }
1431 
1432     //!TODO: load element
1433     // crossBetween
1434     // majorUnit
1435     // minorUnit
1436     // dispUnits
1437     // extLst
1438 
1439     return true;
1440 }
1441 
1442 /*
1443 <xsd:group name="EG_AxShared">
1444     <xsd:sequence>
1445         <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> (*)(M)
1446         <xsd:element name="scaling" type="CT_Scaling" minOccurs="1" maxOccurs="1"/> (*)(M)
1447         <xsd:element name="delete" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
1448         <xsd:element name="axPos" type="CT_AxPos" minOccurs="1" maxOccurs="1"/> (*)(M)
1449         <xsd:element name="majorGridlines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/>
1450         <xsd:element name="minorGridlines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/>
1451         <xsd:element name="title" type="CT_Title" minOccurs="0" maxOccurs="1"/> (*)
1452         <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0" maxOccurs="1"/>
1453         <xsd:element name="majorTickMark" type="CT_TickMark" minOccurs="0" maxOccurs="1"/>
1454         <xsd:element name="minorTickMark" type="CT_TickMark" minOccurs="0" maxOccurs="1"/>
1455         <xsd:element name="tickLblPos" type="CT_TickLblPos" minOccurs="0" maxOccurs="1"/>
1456         <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
1457         <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
1458         <xsd:element name="crossAx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> (*)(M)
1459         <xsd:choice minOccurs="0" maxOccurs="1">
1460             <xsd:element name="crosses" type="CT_Crosses" minOccurs="1" maxOccurs="1"/>
1461             <xsd:element name="crossesAt" type="CT_Double" minOccurs="1" maxOccurs="1"/>
1462         </xsd:choice>
1463     </xsd:sequence>
1464 </xsd:group>
1465 */
loadXmlAxisEG_AxShared(QXmlStreamReader & reader,XlsxAxis * axis)1466 bool ChartPrivate::loadXmlAxisEG_AxShared(QXmlStreamReader &reader, XlsxAxis* axis)
1467 {
1468     Q_ASSERT( NULL != axis );
1469     Q_ASSERT( reader.name().endsWith(QLatin1String("Ax")) );
1470     QString name = reader.name().toString(); //
1471 
1472     while ( !reader.atEnd() )
1473     {
1474         reader.readNextStartElement();
1475         if ( reader.tokenType() == QXmlStreamReader::StartElement )
1476         {
1477             // qDebug() << "[debug]" << QTime::currentTime() << reader.name().toString();
1478 
1479             if ( reader.name() == QLatin1String("axId") ) // mandatory element
1480             {
1481                 // dev57
1482                 uint axId = reader.attributes().value(QStringLiteral("val")).toString().toUInt(); // for Qt5.1
1483                 axis->axisId = axId;
1484             }
1485             else if ( reader.name() == QLatin1String("scaling") )
1486             {
1487                 // mandatory element
1488 
1489                 loadXmlAxisEG_AxShared_Scaling(reader, axis);
1490             }
1491             else if ( reader.name() == QLatin1String("delete") )
1492             {
1493                 //!TODO
1494             }
1495             else if ( reader.name() == QLatin1String("axPos") )
1496             {
1497                 // mandatory element
1498 
1499                 QString axPosVal = reader.attributes().value(QLatin1String("val")).toString();
1500 
1501                 if ( axPosVal == QLatin1String("l") ) { axis->axisPos = XlsxAxis::Left; }
1502                 else if ( axPosVal == QLatin1String("r") ) { axis->axisPos = XlsxAxis::Right; }
1503                 else if ( axPosVal == QLatin1String("t") ) { axis->axisPos = XlsxAxis::Top; }
1504                 else if ( axPosVal == QLatin1String("b") ) { axis->axisPos = XlsxAxis::Bottom; }
1505             }
1506             else if ( reader.name() == QLatin1String("majorGridlines") )
1507             {
1508                 //!TODO anything else?
1509                 majorGridlinesEnabled = true;
1510             }
1511             else if ( reader.name() == QLatin1String("minorGridlines") )
1512             {
1513                 //!TODO anything else?
1514                 minorGridlinesEnabled = true;
1515             }
1516             else if ( reader.name() == QLatin1String("title") )
1517             {
1518                 // title
1519                 if ( !loadXmlAxisEG_AxShared_Title(reader, axis) )
1520                 {
1521                     qDebug() << "failed to load EG_AxShared title.";
1522                     Q_ASSERT(false);
1523                     return false;
1524                 }
1525             }
1526             else if ( reader.name() == QLatin1String("numFmt") )
1527             {
1528                 //!TODO
1529             }
1530             else if ( reader.name() == QLatin1String("majorTickMark") )
1531             {
1532                 //!TODO
1533             }
1534             else if ( reader.name() == QLatin1String("minorTickMark") )
1535             {
1536                 //!TODO
1537             }
1538             else if ( reader.name() == QLatin1String("tickLblPos") )
1539             {
1540                 //!TODO
1541             }
1542             else if ( reader.name() == QLatin1String("spPr") )
1543             {
1544                 //!TODO
1545             }
1546             else if ( reader.name() == QLatin1String("txPr") )
1547             {
1548                 //!TODO
1549             }
1550             else if ( reader.name() == QLatin1String("crossAx") ) // mandatory element
1551             {
1552                 // dev57
1553                 uint crossAx = reader.attributes().value(QLatin1String("val")).toString().toUInt(); // for Qt5.1
1554                 axis->crossAx = crossAx;
1555             }
1556             else if ( reader.name() == QLatin1String("crosses") )
1557             {
1558                 //!TODO
1559             }
1560             else if ( reader.name() == QLatin1String("crossesAt") )
1561             {
1562                 //!TODO
1563             }
1564 
1565             // reader.readNext();
1566         }
1567         else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
1568                   reader.name().toString() == name )
1569         {
1570             break;
1571         }
1572     }
1573 
1574     return true;
1575 }
1576 
loadXmlAxisEG_AxShared_Scaling(QXmlStreamReader & reader,XlsxAxis * axis)1577 bool ChartPrivate::loadXmlAxisEG_AxShared_Scaling(QXmlStreamReader &reader, XlsxAxis* axis)
1578 {
1579     Q_UNUSED(axis);
1580     Q_ASSERT(reader.name() == QLatin1String("scaling"));
1581 
1582     while ( !reader.atEnd() )
1583     {
1584         reader.readNextStartElement();
1585         if ( reader.tokenType() == QXmlStreamReader::StartElement )
1586         {
1587             if ( reader.name() == QLatin1String("orientation") )
1588             {
1589             }
1590             else
1591             {
1592             }
1593         }
1594         else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
1595                   reader.name() == QLatin1String("scaling") )
1596         {
1597             break;
1598         }
1599     }
1600 
1601     return true;
1602 }
1603 
1604 /*
1605   <xsd:complexType name="CT_Title">
1606       <xsd:sequence>
1607           <xsd:element name="tx" type="CT_Tx" minOccurs="0" maxOccurs="1"/>
1608           <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
1609           <xsd:element name="overlay" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
1610           <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
1611           <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
1612           <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1613       </xsd:sequence>
1614   </xsd:complexType>
1615 
1616 <xsd:complexType name="CT_Tx">
1617     <xsd:sequence>
1618         <xsd:choice minOccurs="1" maxOccurs="1">
1619             <xsd:element name="strRef" type="CT_StrRef" minOccurs="1" maxOccurs="1"/>
1620             <xsd:element name="rich" type="a:CT_TextBody" minOccurs="1" maxOccurs="1"/>
1621         </xsd:choice>
1622     </xsd:sequence>
1623 </xsd:complexType>
1624 
1625 <xsd:complexType name="CT_StrRef">
1626     <xsd:sequence>
1627         <xsd:element name="f" type="xsd:string" minOccurs="1" maxOccurs="1"/>
1628         <xsd:element name="strCache" type="CT_StrData" minOccurs="0" maxOccurs="1"/>
1629         <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1630     </xsd:sequence>
1631 </xsd:complexType>
1632 
1633 <xsd:complexType name="CT_TextBody">
1634     <xsd:sequence>
1635         <xsd:element name="bodyPr" type="CT_TextBodyProperties" minOccurs="1" maxOccurs="1"/>
1636         <xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0" maxOccurs="1"/>
1637         <xsd:element name="p" type="CT_TextParagraph" minOccurs="1" maxOccurs="unbounded"/>
1638     </xsd:sequence>
1639 </xsd:complexType>
1640   */
loadXmlAxisEG_AxShared_Title(QXmlStreamReader & reader,XlsxAxis * axis)1641 bool ChartPrivate::loadXmlAxisEG_AxShared_Title(QXmlStreamReader &reader, XlsxAxis* axis)
1642 {
1643     Q_ASSERT(reader.name() == QLatin1String("title"));
1644 
1645     while ( !reader.atEnd() )
1646     {
1647         reader.readNextStartElement();
1648         if ( reader.tokenType() == QXmlStreamReader::StartElement )
1649         {
1650             if ( reader.name() == QLatin1String("tx") )
1651             {
1652                 loadXmlAxisEG_AxShared_Title_Tx(reader, axis);
1653             }
1654             else if ( reader.name() == QLatin1String("overlay") )
1655             {
1656                 //!TODO: load overlay
1657                 loadXmlAxisEG_AxShared_Title_Overlay(reader, axis);
1658             }
1659             else
1660             {
1661             }
1662         }
1663         else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
1664                   reader.name() == QLatin1String("title") )
1665         {
1666             break;
1667         }
1668     }
1669 
1670     return true;
1671 }
1672 
loadXmlAxisEG_AxShared_Title_Overlay(QXmlStreamReader & reader,XlsxAxis * axis)1673 bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Overlay(QXmlStreamReader &reader, XlsxAxis* axis)
1674 {
1675     Q_UNUSED(axis);
1676     Q_ASSERT(reader.name() == QLatin1String("overlay"));
1677 
1678     while ( !reader.atEnd() )
1679     {
1680         reader.readNextStartElement();
1681         if ( reader.tokenType() == QXmlStreamReader::StartElement )
1682         {
1683         }
1684         else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
1685                   reader.name() == QLatin1String("overlay") )
1686         {
1687             break;
1688         }
1689     }
1690 
1691     return true;
1692 }
1693 
loadXmlAxisEG_AxShared_Title_Tx(QXmlStreamReader & reader,XlsxAxis * axis)1694 bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Tx(QXmlStreamReader &reader, XlsxAxis* axis)
1695 {
1696     Q_ASSERT(reader.name() == QLatin1String("tx"));
1697 
1698     while ( !reader.atEnd() )
1699     {
1700         reader.readNextStartElement();
1701         if ( reader.tokenType() == QXmlStreamReader::StartElement )
1702         {
1703             if ( reader.name() == QLatin1String("rich") )
1704             {
1705                 loadXmlAxisEG_AxShared_Title_Tx_Rich(reader, axis);
1706             }
1707             else
1708             {
1709             }
1710         }
1711         else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
1712                   reader.name() == QLatin1String("tx") )
1713         {
1714             break;
1715         }
1716     }
1717 
1718     return true;
1719 }
1720 
loadXmlAxisEG_AxShared_Title_Tx_Rich(QXmlStreamReader & reader,XlsxAxis * axis)1721 bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Tx_Rich(QXmlStreamReader &reader, XlsxAxis* axis)
1722 {
1723     Q_ASSERT(reader.name() == QLatin1String("rich"));
1724 
1725     while ( !reader.atEnd() )
1726     {
1727         reader.readNextStartElement();
1728         if ( reader.tokenType() == QXmlStreamReader::StartElement )
1729         {
1730             if ( reader.name() == QLatin1String("p") )
1731             {
1732                 loadXmlAxisEG_AxShared_Title_Tx_Rich_P(reader, axis);
1733             }
1734             else
1735             {
1736             }
1737         }
1738         else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
1739                   reader.name() == QLatin1String("rich") )
1740         {
1741             break;
1742         }
1743     }
1744 
1745     return true;
1746 }
1747 
loadXmlAxisEG_AxShared_Title_Tx_Rich_P(QXmlStreamReader & reader,XlsxAxis * axis)1748 bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Tx_Rich_P(QXmlStreamReader &reader, XlsxAxis* axis)
1749 {
1750     Q_ASSERT(reader.name() == QLatin1String("p"));
1751 
1752     while ( !reader.atEnd() )
1753     {
1754         reader.readNextStartElement();
1755         if ( reader.tokenType() == QXmlStreamReader::StartElement )
1756         {
1757             if ( reader.name() == QLatin1String("r") )
1758             {
1759                 loadXmlAxisEG_AxShared_Title_Tx_Rich_P_R(reader, axis);
1760             }
1761             else if ( reader.name() == QLatin1String("pPr") )
1762             {
1763                 loadXmlAxisEG_AxShared_Title_Tx_Rich_P_pPr(reader, axis);
1764             }
1765             else
1766             {
1767 
1768             }
1769         }
1770         else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
1771                   reader.name() == QLatin1String("p") )
1772         {
1773             break;
1774         }
1775     }
1776 
1777     return true;
1778 }
1779 
loadXmlAxisEG_AxShared_Title_Tx_Rich_P_pPr(QXmlStreamReader & reader,XlsxAxis * axis)1780 bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Tx_Rich_P_pPr(QXmlStreamReader &reader, XlsxAxis* axis)
1781 {
1782     Q_UNUSED(axis);
1783     Q_ASSERT(reader.name() == QLatin1String("pPr"));
1784 
1785     while ( !reader.atEnd() )
1786     {
1787         reader.readNextStartElement();
1788         if ( reader.tokenType() == QXmlStreamReader::StartElement )
1789         {
1790             if ( reader.name() == QLatin1String("defRPr") )
1791             {
1792                 reader.readElementText();
1793             }
1794             else
1795             {
1796             }
1797         }
1798         else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
1799                   reader.name() == QLatin1String("pPr") )
1800         {
1801             break;
1802         }
1803     }
1804 
1805     return true;
1806 }
1807 
loadXmlAxisEG_AxShared_Title_Tx_Rich_P_R(QXmlStreamReader & reader,XlsxAxis * axis)1808 bool ChartPrivate::loadXmlAxisEG_AxShared_Title_Tx_Rich_P_R(QXmlStreamReader &reader, XlsxAxis* axis)
1809 {
1810     Q_ASSERT(reader.name() == QLatin1String("r"));
1811 
1812     while ( !reader.atEnd() )
1813     {
1814         reader.readNextStartElement();
1815         if ( reader.tokenType() == QXmlStreamReader::StartElement )
1816         {
1817             if ( reader.name() == QLatin1String("t") )
1818             {
1819                 QString strAxisName = reader.readElementText();
1820                 XlsxAxis::AxisPos axisPos = axis->axisPos;
1821                 axis->axisNames[ axisPos ] = strAxisName;
1822             }
1823             else
1824             {
1825             }
1826         }
1827         else if ( reader.tokenType() == QXmlStreamReader::EndElement &&
1828                   reader.name() == QLatin1String("r") )
1829         {
1830             break;
1831         }
1832     }
1833 
1834     return true;
1835 }
1836 
1837 /*
1838 <xsd:complexType name="CT_PlotArea">
1839     <xsd:sequence>
1840         <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
1841         <xsd:choice minOccurs="1" maxOccurs="unbounded">
1842             <xsd:element name="areaChart" type="CT_AreaChart" minOccurs="1" maxOccurs="1"/>
1843             <xsd:element name="area3DChart" type="CT_Area3DChart" minOccurs="1" maxOccurs="1"/>
1844             <xsd:element name="lineChart" type="CT_LineChart" minOccurs="1" maxOccurs="1"/>
1845             <xsd:element name="line3DChart" type="CT_Line3DChart" minOccurs="1" maxOccurs="1"/>
1846             <xsd:element name="stockChart" type="CT_StockChart" minOccurs="1" maxOccurs="1"/>
1847             <xsd:element name="radarChart" type="CT_RadarChart" minOccurs="1" maxOccurs="1"/>
1848             <xsd:element name="scatterChart" type="CT_ScatterChart" minOccurs="1" maxOccurs="1"/>
1849             <xsd:element name="pieChart" type="CT_PieChart" minOccurs="1" maxOccurs="1"/>
1850             <xsd:element name="pie3DChart" type="CT_Pie3DChart" minOccurs="1" maxOccurs="1"/>
1851             <xsd:element name="doughnutChart" type="CT_DoughnutChart" minOccurs="1" maxOccurs="1"/>
1852             <xsd:element name="barChart" type="CT_BarChart" minOccurs="1" maxOccurs="1"/>
1853             <xsd:element name="bar3DChart" type="CT_Bar3DChart" minOccurs="1" maxOccurs="1"/>
1854             <xsd:element name="ofPieChart" type="CT_OfPieChart" minOccurs="1" maxOccurs="1"/>
1855             <xsd:element name="surfaceChart" type="CT_SurfaceChart" minOccurs="1" maxOccurs="1"/>
1856             <xsd:element name="surface3DChart" type="CT_Surface3DChart" minOccurs="1" maxOccurs="1"/>
1857             <xsd:element name="bubbleChart" type="CT_BubbleChart" minOccurs="1" maxOccurs="1"/>
1858         </xsd:choice>
1859         <xsd:choice minOccurs="0" maxOccurs="unbounded">
1860             <xsd:element name="valAx" type="CT_ValAx" minOccurs="1" maxOccurs="1"/>
1861             <xsd:element name="catAx" type="CT_CatAx" minOccurs="1" maxOccurs="1"/>
1862             <xsd:element name="dateAx" type="CT_DateAx" minOccurs="1" maxOccurs="1"/>
1863             <xsd:element name="serAx" type="CT_SerAx" minOccurs="1" maxOccurs="1"/>
1864         </xsd:choice>
1865         <xsd:element name="dTable" type="CT_DTable" minOccurs="0" maxOccurs="1"/>
1866         <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
1867         <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1868     </xsd:sequence>
1869 </xsd:complexType>
1870 */
1871 
1872 /*
1873 <xsd:complexType name="CT_CatAx">
1874     <xsd:sequence>
1875         <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
1876         <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
1877         <xsd:element name="lblAlgn" type="CT_LblAlgn" minOccurs="0" maxOccurs="1"/>
1878         <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/>
1879         <xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
1880         <xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
1881         <xsd:element name="noMultiLvlLbl" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
1882         <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1883     </xsd:sequence>
1884 </xsd:complexType>
1885 <!----------------------------------------------------------------------------->
1886 <xsd:complexType name="CT_DateAx">
1887     <xsd:sequence>
1888         <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
1889         <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
1890         <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/>
1891         <xsd:element name="baseTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
1892         <xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
1893         <xsd:element name="majorTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
1894         <xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
1895         <xsd:element name="minorTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
1896         <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1897     </xsd:sequence>
1898 </xsd:complexType>
1899 <!----------------------------------------------------------------------------->
1900 <xsd:complexType name="CT_SerAx">
1901     <xsd:sequence>
1902     <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
1903         <xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
1904         <xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
1905         <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1906     </xsd:sequence>
1907 </xsd:complexType>
1908 <!----------------------------------------------------------------------------->
1909 <xsd:complexType name="CT_ValAx">
1910     <xsd:sequence>
1911         <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
1912         <xsd:element name="crossBetween" type="CT_CrossBetween" minOccurs="0" maxOccurs="1"/>
1913         <xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
1914         <xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
1915         <xsd:element name="dispUnits" type="CT_DispUnits" minOccurs="0" maxOccurs="1"/>
1916         <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1917     </xsd:sequence>
1918 </xsd:complexType>
1919 */
1920 
saveXmlAxis(QXmlStreamWriter & writer) const1921 void ChartPrivate::saveXmlAxis(QXmlStreamWriter &writer) const
1922 {
1923     for ( int i = 0 ; i < axisList.size() ; ++i )
1924     {
1925         XlsxAxis* axis = axisList[i].data();
1926         if ( NULL == axis )
1927             continue;
1928 
1929         if ( axis->type == XlsxAxis::T_Cat  ) { saveXmlAxisCatAx( writer, axis ); }
1930         if ( axis->type == XlsxAxis::T_Val  ) { saveXmlAxisValAx( writer, axis ); }
1931         if ( axis->type == XlsxAxis::T_Ser  ) { saveXmlAxisSerAx( writer, axis ); }
1932         if ( axis->type == XlsxAxis::T_Date ) { saveXmlAxisDateAx( writer, axis ); }
1933     }
1934 
1935 }
1936 
saveXmlAxisCatAx(QXmlStreamWriter & writer,XlsxAxis * axis) const1937 void ChartPrivate::saveXmlAxisCatAx(QXmlStreamWriter &writer, XlsxAxis* axis) const
1938 {
1939 /*
1940 <xsd:complexType name="CT_CatAx">
1941     <xsd:sequence>
1942         <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
1943         <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
1944         <xsd:element name="lblAlgn" type="CT_LblAlgn" minOccurs="0" maxOccurs="1"/>
1945         <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/>
1946         <xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
1947         <xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
1948         <xsd:element name="noMultiLvlLbl" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
1949         <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1950     </xsd:sequence>
1951 </xsd:complexType>
1952 */
1953 
1954     writer.writeStartElement(QStringLiteral("c:catAx"));
1955 
1956     saveXmlAxisEG_AxShared(writer, axis); // EG_AxShared
1957 
1958     //!TODO: write element
1959     // auto
1960     // lblAlgn
1961     // lblOffset
1962     // tickLblSkip
1963     // tickMarkSkip
1964     // noMultiLvlLbl
1965     // extLst
1966 
1967     writer.writeEndElement(); // c:catAx
1968 }
1969 
saveXmlAxisDateAx(QXmlStreamWriter & writer,XlsxAxis * axis) const1970 void ChartPrivate::saveXmlAxisDateAx(QXmlStreamWriter &writer, XlsxAxis* axis) const
1971 {
1972 /*
1973 <xsd:complexType name="CT_DateAx">
1974     <xsd:sequence>
1975         <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
1976         <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
1977         <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/>
1978         <xsd:element name="baseTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
1979         <xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
1980         <xsd:element name="majorTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
1981         <xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
1982         <xsd:element name="minorTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
1983         <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1984     </xsd:sequence>
1985 </xsd:complexType>
1986 */
1987 
1988     writer.writeStartElement(QStringLiteral("c:dateAx"));
1989 
1990     saveXmlAxisEG_AxShared(writer, axis); // EG_AxShared
1991 
1992     //!TODO: write element
1993     // auto
1994     // lblOffset
1995     // baseTimeUnit
1996     // majorUnit
1997     // majorTimeUnit
1998     // minorUnit
1999     // minorTimeUnit
2000     // extLst
2001 
2002     writer.writeEndElement(); // c:dateAx
2003 }
2004 
saveXmlAxisSerAx(QXmlStreamWriter & writer,XlsxAxis * axis) const2005 void ChartPrivate::saveXmlAxisSerAx(QXmlStreamWriter &writer, XlsxAxis* axis) const
2006 {
2007 /*
2008 <xsd:complexType name="CT_SerAx">
2009     <xsd:sequence>
2010     <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
2011         <xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
2012         <xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
2013         <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2014     </xsd:sequence>
2015 </xsd:complexType>
2016 */
2017 
2018     writer.writeStartElement(QStringLiteral("c:serAx"));
2019 
2020     saveXmlAxisEG_AxShared(writer, axis); // EG_AxShared
2021 
2022     //!TODO: write element
2023     // tickLblSkip
2024     // tickMarkSkip
2025     // extLst
2026 
2027     writer.writeEndElement(); // c:serAx
2028 }
2029 
saveXmlAxisValAx(QXmlStreamWriter & writer,XlsxAxis * axis) const2030 void ChartPrivate::saveXmlAxisValAx(QXmlStreamWriter &writer, XlsxAxis* axis) const
2031 {
2032 /*
2033 <xsd:complexType name="CT_ValAx">
2034     <xsd:sequence>
2035         <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
2036         <xsd:element name="crossBetween" type="CT_CrossBetween" minOccurs="0" maxOccurs="1"/>
2037         <xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
2038         <xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
2039         <xsd:element name="dispUnits" type="CT_DispUnits" minOccurs="0" maxOccurs="1"/>
2040         <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2041     </xsd:sequence>
2042 </xsd:complexType>
2043 */
2044 
2045     writer.writeStartElement(QStringLiteral("c:valAx"));
2046 
2047     saveXmlAxisEG_AxShared(writer, axis); // EG_AxShared
2048 
2049     //!TODO: write element
2050     // crossBetween
2051     // majorUnit
2052     // minorUnit
2053     // dispUnits
2054     // extLst
2055 
2056     writer.writeEndElement(); // c:valAx
2057 }
2058 
saveXmlAxisEG_AxShared(QXmlStreamWriter & writer,XlsxAxis * axis) const2059 void ChartPrivate::saveXmlAxisEG_AxShared(QXmlStreamWriter &writer, XlsxAxis* axis) const
2060 {
2061     /*
2062     <xsd:group name="EG_AxShared">
2063         <xsd:sequence>
2064             <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> (*)
2065             <xsd:element name="scaling" type="CT_Scaling" minOccurs="1" maxOccurs="1"/> (*)
2066             <xsd:element name="delete" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2067             <xsd:element name="axPos" type="CT_AxPos" minOccurs="1" maxOccurs="1"/> (*)
2068             <xsd:element name="majorGridlines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/>
2069             <xsd:element name="minorGridlines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/>
2070             <xsd:element name="title" type="CT_Title" minOccurs="0" maxOccurs="1"/> (***********************)
2071             <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0" maxOccurs="1"/>
2072             <xsd:element name="majorTickMark" type="CT_TickMark" minOccurs="0" maxOccurs="1"/>
2073             <xsd:element name="minorTickMark" type="CT_TickMark" minOccurs="0" maxOccurs="1"/>
2074             <xsd:element name="tickLblPos" type="CT_TickLblPos" minOccurs="0" maxOccurs="1"/>
2075             <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
2076             <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
2077             <xsd:element name="crossAx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> (*)
2078             <xsd:choice minOccurs="0" maxOccurs="1">
2079                 <xsd:element name="crosses" type="CT_Crosses" minOccurs="1" maxOccurs="1"/>
2080                 <xsd:element name="crossesAt" type="CT_Double" minOccurs="1" maxOccurs="1"/>
2081             </xsd:choice>
2082         </xsd:sequence>
2083     </xsd:group>
2084     */
2085 
2086     writer.writeEmptyElement(QStringLiteral("c:axId")); // 21.2.2.9. axId (Axis ID) (mandatory value)
2087         writer.writeAttribute(QStringLiteral("val"), QString::number(axis->axisId));
2088 
2089     writer.writeStartElement(QStringLiteral("c:scaling")); // CT_Scaling (mandatory value)
2090         writer.writeEmptyElement(QStringLiteral("c:orientation")); // CT_Orientation
2091             writer.writeAttribute(QStringLiteral("val"), QStringLiteral("minMax")); // ST_Orientation
2092     writer.writeEndElement(); // c:scaling
2093 
2094     writer.writeEmptyElement(QStringLiteral("c:axPos")); // axPos CT_AxPos (mandatory value)
2095         QString pos = GetAxisPosString( axis->axisPos );
2096         if ( !pos.isEmpty() )
2097         {
2098             writer.writeAttribute(QStringLiteral("val"), pos); // ST_AxPos
2099         }
2100 
2101     if( majorGridlinesEnabled )
2102     {
2103         writer.writeEmptyElement(QStringLiteral("c:majorGridlines"));
2104     }
2105     if( minorGridlinesEnabled )
2106     {
2107         writer.writeEmptyElement(QStringLiteral("c:minorGridlines"));
2108     }
2109 
2110     saveXmlAxisEG_AxShared_Title(writer, axis); // "c:title" CT_Title
2111 
2112     writer.writeEmptyElement(QStringLiteral("c:crossAx")); // crossAx (mandatory value)
2113         writer.writeAttribute(QStringLiteral("val"), QString::number(axis->crossAx));
2114 
2115 }
2116 
saveXmlAxisEG_AxShared_Title(QXmlStreamWriter & writer,XlsxAxis * axis) const2117 void ChartPrivate::saveXmlAxisEG_AxShared_Title(QXmlStreamWriter &writer, XlsxAxis* axis) const
2118 {
2119     // CT_Title
2120 
2121     /*
2122     <xsd:complexType name="CT_Title">
2123         <xsd:sequence>
2124             <xsd:element name="tx" type="CT_Tx" minOccurs="0" maxOccurs="1"/>
2125             <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
2126             <xsd:element name="overlay" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2127             <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
2128             <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
2129             <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2130         </xsd:sequence>
2131     </xsd:complexType>
2132     */
2133     /*
2134     <xsd:complexType name="CT_Tx">
2135         <xsd:sequence>
2136             <xsd:choice minOccurs="1" maxOccurs="1">
2137                 <xsd:element name="strRef" type="CT_StrRef" minOccurs="1" maxOccurs="1"/>
2138                 <xsd:element name="rich" type="a:CT_TextBody" minOccurs="1" maxOccurs="1"/>
2139             </xsd:choice>
2140         </xsd:sequence>
2141     </xsd:complexType>
2142     */
2143     /*
2144     <xsd:complexType name="CT_StrRef">
2145         <xsd:sequence>
2146             <xsd:element name="f" type="xsd:string" minOccurs="1" maxOccurs="1"/>
2147             <xsd:element name="strCache" type="CT_StrData" minOccurs="0" maxOccurs="1"/>
2148             <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2149         </xsd:sequence>
2150     </xsd:complexType>
2151     */
2152     /*
2153     <xsd:complexType name="CT_TextBody">
2154         <xsd:sequence>
2155             <xsd:element name="bodyPr" type="CT_TextBodyProperties" minOccurs="1" maxOccurs="1"/>
2156             <xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0" maxOccurs="1"/>
2157             <xsd:element name="p" type="CT_TextParagraph" minOccurs="1" maxOccurs="unbounded"/>
2158         </xsd:sequence>
2159     </xsd:complexType>
2160     */
2161 
2162     writer.writeStartElement(QStringLiteral("c:title"));
2163 
2164     // CT_Tx {{
2165      writer.writeStartElement(QStringLiteral("c:tx"));
2166 
2167       writer.writeStartElement(QStringLiteral("c:rich")); // CT_TextBody
2168 
2169        writer.writeEmptyElement(QStringLiteral("a:bodyPr")); // CT_TextBodyProperties
2170 
2171        writer.writeEmptyElement(QStringLiteral("a:lstStyle")); // CT_TextListStyle
2172 
2173        writer.writeStartElement(QStringLiteral("a:p"));
2174 
2175         writer.writeStartElement(QStringLiteral("a:pPr"));
2176             writer.writeAttribute(QStringLiteral("lvl"), QString::number(0));
2177 
2178             writer.writeStartElement(QStringLiteral("a:defRPr"));
2179             writer.writeAttribute(QStringLiteral("b"), QString::number(0));
2180             writer.writeEndElement(); // a:defRPr
2181         writer.writeEndElement(); // a:pPr
2182 
2183         writer.writeStartElement(QStringLiteral("a:r"));
2184         QString strAxisName = GetAxisName(axis);
2185         writer.writeTextElement( QStringLiteral("a:t"), strAxisName );
2186         writer.writeEndElement(); // a:r
2187 
2188        writer.writeEndElement(); // a:p
2189 
2190       writer.writeEndElement(); // c:rich
2191 
2192      writer.writeEndElement(); // c:tx
2193      // CT_Tx }}
2194 
2195      writer.writeStartElement(QStringLiteral("c:overlay"));
2196         writer.writeAttribute(QStringLiteral("val"), QString::number(0)); // CT_Boolean
2197      writer.writeEndElement(); // c:overlay
2198 
2199     writer.writeEndElement(); // c:title
2200 
2201 }
2202 
GetAxisPosString(XlsxAxis::AxisPos axisPos) const2203 QString ChartPrivate::GetAxisPosString( XlsxAxis::AxisPos axisPos ) const
2204 {
2205     QString pos;
2206     switch ( axisPos )
2207     {
2208         case XlsxAxis::Top    : pos = QStringLiteral("t"); break;
2209         case XlsxAxis::Bottom : pos = QStringLiteral("b"); break;
2210         case XlsxAxis::Left   : pos = QStringLiteral("l"); break;
2211         case XlsxAxis::Right  : pos = QStringLiteral("r"); break;
2212         default: break; // ??
2213     }
2214 
2215     return pos;
2216 }
2217 
GetAxisName(XlsxAxis * axis) const2218 QString ChartPrivate::GetAxisName(XlsxAxis* axis) const
2219 {
2220     QString strAxisName;
2221     if ( NULL == axis )
2222         return strAxisName;
2223 
2224     QString pos = GetAxisPosString( axis->axisPos ); // l, t, r, b
2225     if ( pos.isEmpty() )
2226         return strAxisName;
2227 
2228     strAxisName = axis->axisNames[ axis->axisPos ];
2229     return strAxisName;
2230 }
2231 
2232 
2233 ///
2234 /// \brief ChartPrivate::readSubTree
2235 /// \param reader
2236 /// \return
2237 ///
readSubTree(QXmlStreamReader & reader)2238 QString ChartPrivate::readSubTree(QXmlStreamReader &reader)
2239 {
2240     QString treeString;
2241     QString prefix;
2242     const auto& treeName = reader.name();
2243 
2244     while (!reader.atEnd())
2245     {
2246         reader.readNextStartElement();
2247         if (reader.tokenType() == QXmlStreamReader::StartElement)
2248         {
2249             prefix = reader.prefix().toString();
2250 
2251             treeString += QLatin1String("<") + reader.qualifiedName().toString();
2252 
2253             const QXmlStreamAttributes attributes = reader.attributes();
2254             for (const QXmlStreamAttribute &attr : attributes) {
2255                 treeString += QLatin1String(" ") + attr.name().toString() + QLatin1String("=\"") + attr.value().toString() + QLatin1String("\"");
2256             }
2257             treeString += QStringLiteral(">");
2258         }
2259         else if (reader.tokenType() == QXmlStreamReader::EndElement )
2260         {
2261             if( reader.name() == treeName)
2262             {
2263                 break;
2264             }
2265             treeString += QLatin1String("</") + reader.qualifiedName().toString() + QLatin1String(">");
2266         }
2267     }
2268 
2269     return treeString;
2270 }
2271 
2272 
2273 ///
2274 /// \brief ChartPrivate::loadXmlChartLegend
2275 /// \param reader
2276 /// \return
2277 ///
loadXmlChartLegend(QXmlStreamReader & reader)2278 bool ChartPrivate::loadXmlChartLegend(QXmlStreamReader &reader)
2279 {
2280 
2281     Q_ASSERT(reader.name() == QLatin1String("legend"));
2282 
2283     while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement
2284                                 && reader.name() == QLatin1String("legend")))
2285     {
2286         if (reader.readNextStartElement())
2287         {
2288             if (reader.name() == QLatin1String("legendPos")) // c:legendPos
2289             {
2290                 QString pos = reader.attributes().value(QLatin1String("val")).toString();
2291                 if( pos.compare(QLatin1String("r"), Qt::CaseInsensitive) == 0)
2292                 {
2293                     // legendPos = Chart::ChartAxisPos::Right;
2294                     legendPos = Chart::Right;
2295                 }
2296                 else
2297                 if( pos.compare(QLatin1String("l"), Qt::CaseInsensitive) == 0)
2298                 {
2299                     // legendPos = Chart::ChartAxisPos::Left;
2300                     legendPos = Chart::Left;
2301                 }
2302                 else
2303                 if( pos.compare(QLatin1String("t"), Qt::CaseInsensitive) == 0)
2304                 {
2305                     // legendPos = Chart::ChartAxisPos::Top;
2306                     legendPos = Chart::Top;
2307                 }
2308                 else
2309                 if( pos.compare(QLatin1String("b"), Qt::CaseInsensitive) == 0)
2310                 {
2311                     // legendPos = Chart::ChartAxisPos::Bottom;
2312                     legendPos = Chart::Bottom;
2313                 }
2314                 else
2315                 {
2316                     // legendPos = Chart::ChartAxisPos::None;
2317                     legendPos = Chart::None;
2318                 }
2319             }
2320             else
2321             if (reader.name() == QLatin1String("overlay")) // c:legendPos
2322             {
2323                 QString pos = reader.attributes().value(QLatin1String("val")).toString();
2324                 if( pos.compare(QLatin1String("1"), Qt::CaseInsensitive) == 0 )
2325                 {
2326                     legendOverlay = true;
2327                 }
2328                 else
2329                 {
2330                     legendOverlay = false;
2331                 }
2332             }
2333         }
2334     }
2335 
2336     return false;
2337 }
2338 
2339 QT_END_NAMESPACE_XLSX
2340