Mercurial > clickerconvert
comparison src/xlsx/xlsxchart.cpp @ 1:93d3106bb9a4
Add qt xlsx library
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Tue, 22 Mar 2016 10:38:08 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:49cd5cc0b072 | 1:93d3106bb9a4 |
---|---|
1 /**************************************************************************** | |
2 ** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me> | |
3 ** All right reserved. | |
4 ** | |
5 ** Permission is hereby granted, free of charge, to any person obtaining | |
6 ** a copy of this software and associated documentation files (the | |
7 ** "Software"), to deal in the Software without restriction, including | |
8 ** without limitation the rights to use, copy, modify, merge, publish, | |
9 ** distribute, sublicense, and/or sell copies of the Software, and to | |
10 ** permit persons to whom the Software is furnished to do so, subject to | |
11 ** the following conditions: | |
12 ** | |
13 ** The above copyright notice and this permission notice shall be | |
14 ** included in all copies or substantial portions of the Software. | |
15 ** | |
16 ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
17 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
19 ** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
20 ** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
21 ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
22 ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
23 ** | |
24 ****************************************************************************/ | |
25 | |
26 #include "xlsxchart_p.h" | |
27 #include "xlsxworksheet.h" | |
28 #include "xlsxcellrange.h" | |
29 #include "xlsxutility_p.h" | |
30 | |
31 #include <QIODevice> | |
32 #include <QXmlStreamReader> | |
33 #include <QXmlStreamWriter> | |
34 #include <QDebug> | |
35 | |
36 QT_BEGIN_NAMESPACE_XLSX | |
37 | |
38 ChartPrivate::ChartPrivate(Chart *q, Chart::CreateFlag flag) | |
39 :AbstractOOXmlFilePrivate(q, flag), chartType(static_cast<Chart::ChartType>(0)) | |
40 { | |
41 | |
42 } | |
43 | |
44 ChartPrivate::~ChartPrivate() | |
45 { | |
46 | |
47 } | |
48 | |
49 /*! | |
50 * \class Chart | |
51 * \inmodule QtXlsx | |
52 * \brief Main class for the charts. | |
53 */ | |
54 | |
55 /*! | |
56 \enum Chart::ChartType | |
57 | |
58 \value CT_Area | |
59 \value CT_Area3D, | |
60 \value CT_Line, | |
61 \value CT_Line3D, | |
62 \value CT_Scatter, | |
63 \value CT_Pie, | |
64 \value CT_Pie3D, | |
65 \value CT_Doughnut, | |
66 \value CT_Bar, | |
67 \value CT_Bar3D, | |
68 | |
69 \omitvalue CT_Stock, | |
70 \omitvalue CT_Radar, | |
71 \omitvalue CT_OfPie, | |
72 \omitvalue CT_Surface, | |
73 \omitvalue CT_Surface3D, | |
74 \omitvalue CT_Bubble | |
75 */ | |
76 | |
77 /*! | |
78 * \internal | |
79 */ | |
80 Chart::Chart(AbstractSheet *parent, CreateFlag flag) | |
81 :AbstractOOXmlFile(new ChartPrivate(this, flag)) | |
82 { | |
83 d_func()->sheet = parent; | |
84 } | |
85 | |
86 /*! | |
87 * Destroys the chart. | |
88 */ | |
89 Chart::~Chart() | |
90 { | |
91 } | |
92 | |
93 /*! | |
94 * Add the data series which is in the range \a range of the \a sheet. | |
95 */ | |
96 void Chart::addSeries(const CellRange &range, AbstractSheet *sheet) | |
97 { | |
98 Q_D(Chart); | |
99 if (!range.isValid()) | |
100 return; | |
101 if (sheet && sheet->sheetType() != AbstractSheet::ST_WorkSheet) | |
102 return; | |
103 if (!sheet && d->sheet->sheetType() != AbstractSheet::ST_WorkSheet) | |
104 return; | |
105 | |
106 QString sheetName = sheet ? sheet->sheetName() : d->sheet->sheetName(); | |
107 //In case sheetName contains space or ' | |
108 sheetName = escapeSheetName(sheetName); | |
109 | |
110 if (range.columnCount() == 1 || range.rowCount() == 1) { | |
111 QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries); | |
112 series->numberDataSource_numRef = sheetName + QLatin1String("!") + range.toString(true, true); | |
113 d->seriesList.append(series); | |
114 } else if (range.columnCount() < range.rowCount()) { | |
115 //Column based series | |
116 int firstDataColumn = range.firstColumn(); | |
117 QString axDataSouruce_numRef; | |
118 if (d->chartType == CT_Scatter || d->chartType == CT_Bubble) { | |
119 firstDataColumn += 1; | |
120 CellRange subRange(range.firstRow(), range.firstColumn(), range.lastRow(), range.firstColumn()); | |
121 axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); | |
122 } | |
123 | |
124 for (int col=firstDataColumn; col<=range.lastColumn(); ++col) { | |
125 CellRange subRange(range.firstRow(), col, range.lastRow(), col); | |
126 QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries); | |
127 series->axDataSource_numRef = axDataSouruce_numRef; | |
128 series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); | |
129 d->seriesList.append(series); | |
130 } | |
131 | |
132 } else { | |
133 //Row based series | |
134 int firstDataRow = range.firstRow(); | |
135 QString axDataSouruce_numRef; | |
136 if (d->chartType == CT_Scatter || d->chartType == CT_Bubble) { | |
137 firstDataRow += 1; | |
138 CellRange subRange(range.firstRow(), range.firstColumn(), range.firstRow(), range.lastColumn()); | |
139 axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); | |
140 } | |
141 | |
142 for (int row=firstDataRow; row<=range.lastRow(); ++row) { | |
143 CellRange subRange(row, range.firstColumn(), row, range.lastColumn()); | |
144 QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries); | |
145 series->axDataSource_numRef = axDataSouruce_numRef; | |
146 series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); | |
147 d->seriesList.append(series); | |
148 } | |
149 } | |
150 } | |
151 | |
152 /*! | |
153 * Set the type of the chart to \a type | |
154 */ | |
155 void Chart::setChartType(ChartType type) | |
156 { | |
157 Q_D(Chart); | |
158 d->chartType = type; | |
159 } | |
160 | |
161 /*! | |
162 * \internal | |
163 * | |
164 */ | |
165 void Chart::setChartStyle(int id) | |
166 { | |
167 Q_UNUSED(id) | |
168 //!Todo | |
169 } | |
170 | |
171 /*! | |
172 * \internal | |
173 */ | |
174 void Chart::saveToXmlFile(QIODevice *device) const | |
175 { | |
176 Q_D(const Chart); | |
177 | |
178 QXmlStreamWriter writer(device); | |
179 | |
180 writer.writeStartDocument(QStringLiteral("1.0"), true); | |
181 writer.writeStartElement(QStringLiteral("c:chartSpace")); | |
182 writer.writeAttribute(QStringLiteral("xmlns:c"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart")); | |
183 writer.writeAttribute(QStringLiteral("xmlns:a"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/main")); | |
184 writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships")); | |
185 | |
186 d->saveXmlChart(writer); | |
187 | |
188 writer.writeEndElement();//c:chartSpace | |
189 writer.writeEndDocument(); | |
190 } | |
191 | |
192 /*! | |
193 * \internal | |
194 */ | |
195 bool Chart::loadFromXmlFile(QIODevice *device) | |
196 { | |
197 Q_D(Chart); | |
198 | |
199 QXmlStreamReader reader(device); | |
200 while (!reader.atEnd()) { | |
201 reader.readNextStartElement(); | |
202 if (reader.tokenType() == QXmlStreamReader::StartElement) { | |
203 if (reader.name() == QLatin1String("chart")) { | |
204 if (!d->loadXmlChart(reader)) | |
205 return false; | |
206 } | |
207 } | |
208 } | |
209 return true; | |
210 } | |
211 | |
212 bool ChartPrivate::loadXmlChart(QXmlStreamReader &reader) | |
213 { | |
214 Q_ASSERT(reader.name() == QLatin1String("chart")); | |
215 | |
216 while (!reader.atEnd()) { | |
217 reader.readNextStartElement(); | |
218 if (reader.tokenType() == QXmlStreamReader::StartElement) { | |
219 if (reader.name() == QLatin1String("plotArea")) { | |
220 if (!loadXmlPlotArea(reader)) | |
221 return false; | |
222 } else if (reader.name() == QLatin1String("legend")) { | |
223 //!Todo | |
224 } | |
225 } else if (reader.tokenType() == QXmlStreamReader::EndElement && | |
226 reader.name() == QLatin1String("chart")) { | |
227 break; | |
228 } | |
229 } | |
230 return true; | |
231 } | |
232 | |
233 bool ChartPrivate::loadXmlPlotArea(QXmlStreamReader &reader) | |
234 { | |
235 Q_ASSERT(reader.name() == QLatin1String("plotArea")); | |
236 | |
237 while (!reader.atEnd()) { | |
238 reader.readNextStartElement(); | |
239 if (reader.tokenType() == QXmlStreamReader::StartElement) { | |
240 if (reader.name() == QLatin1String("layout")) { | |
241 //!ToDo | |
242 } else if (reader.name().endsWith(QLatin1String("Chart"))) { | |
243 //For pieChart, barChart, ... | |
244 loadXmlXxxChart(reader); | |
245 } else if (reader.name().endsWith(QLatin1String("Ax"))) { | |
246 //For valAx, catAx, serAx, dateAx | |
247 loadXmlAxis(reader); | |
248 } | |
249 | |
250 } else if (reader.tokenType() == QXmlStreamReader::EndElement && | |
251 reader.name() == QLatin1String("plotArea")) { | |
252 break; | |
253 } | |
254 } | |
255 return true; | |
256 } | |
257 | |
258 bool ChartPrivate::loadXmlXxxChart(QXmlStreamReader &reader) | |
259 { | |
260 QStringRef name = reader.name(); | |
261 if (name == QLatin1String("pieChart")) chartType = Chart::CT_Pie; | |
262 else if (name == QLatin1String("pie3DChart")) chartType = Chart::CT_Pie3D; | |
263 else if (name == QLatin1String("barChart")) chartType = Chart::CT_Bar; | |
264 else if (name == QLatin1String("bar3DChart")) chartType = Chart::CT_Bar3D; | |
265 else if (name == QLatin1String("lineChart")) chartType = Chart::CT_Line; | |
266 else if (name == QLatin1String("line3DChart")) chartType = Chart::CT_Line3D; | |
267 else if (name == QLatin1String("scatterChart")) chartType = Chart::CT_Scatter; | |
268 else if (name == QLatin1String("areaChart")) chartType = Chart::CT_Area; | |
269 else if (name == QLatin1String("area3DChart")) chartType = Chart::CT_Area3D; | |
270 else if (name == QLatin1String("doughnutChart")) chartType = Chart::CT_Doughnut; | |
271 else qDebug()<<"Cann't load chart: "<<name; | |
272 | |
273 while (!reader.atEnd()) { | |
274 reader.readNextStartElement(); | |
275 if (reader.tokenType() == QXmlStreamReader::StartElement) { | |
276 if (reader.name() == QLatin1String("ser")) { | |
277 loadXmlSer(reader); | |
278 } else if (reader.name() == QLatin1String("axId")) { | |
279 | |
280 } | |
281 } else if (reader.tokenType() == QXmlStreamReader::EndElement | |
282 && reader.name() == name) { | |
283 break; | |
284 } | |
285 } | |
286 return true; | |
287 } | |
288 | |
289 bool ChartPrivate::loadXmlSer(QXmlStreamReader &reader) | |
290 { | |
291 Q_ASSERT(reader.name() == QLatin1String("ser")); | |
292 | |
293 QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries); | |
294 seriesList.append(series); | |
295 | |
296 while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement | |
297 && reader.name() == QLatin1String("ser"))) { | |
298 if (reader.readNextStartElement()) { | |
299 QStringRef name = reader.name(); | |
300 if (name == QLatin1String("cat") || name == QLatin1String("xVal")) { | |
301 while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement | |
302 && reader.name() == name)) { | |
303 if (reader.readNextStartElement()) { | |
304 if (reader.name() == QLatin1String("numRef")) | |
305 series->axDataSource_numRef = loadXmlNumRef(reader); | |
306 } | |
307 } | |
308 } else if (name == QLatin1String("val") || name == QLatin1String("yVal")) { | |
309 while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement | |
310 && reader.name() == name)) { | |
311 if (reader.readNextStartElement()) { | |
312 if (reader.name() == QLatin1String("numRef")) | |
313 series->numberDataSource_numRef = loadXmlNumRef(reader); | |
314 } | |
315 } | |
316 } else if (name == QLatin1String("extLst")) { | |
317 while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement | |
318 && reader.name() == name)) { | |
319 reader.readNextStartElement(); | |
320 } | |
321 } | |
322 } | |
323 } | |
324 | |
325 return true; | |
326 } | |
327 | |
328 | |
329 QString ChartPrivate::loadXmlNumRef(QXmlStreamReader &reader) | |
330 { | |
331 Q_ASSERT(reader.name() == QLatin1String("numRef")); | |
332 | |
333 while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement | |
334 && reader.name() == QLatin1String("numRef"))) { | |
335 if (reader.readNextStartElement()) { | |
336 if (reader.name() == QLatin1String("f")) | |
337 return reader.readElementText(); | |
338 } | |
339 } | |
340 | |
341 return QString(); | |
342 } | |
343 | |
344 void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const | |
345 { | |
346 writer.writeStartElement(QStringLiteral("c:chart")); | |
347 writer.writeStartElement(QStringLiteral("c:plotArea")); | |
348 switch (chartType) { | |
349 case Chart::CT_Pie: | |
350 case Chart::CT_Pie3D: | |
351 saveXmlPieChart(writer); | |
352 break; | |
353 case Chart::CT_Bar: | |
354 case Chart::CT_Bar3D: | |
355 saveXmlBarChart(writer); | |
356 break; | |
357 case Chart::CT_Line: | |
358 case Chart::CT_Line3D: | |
359 saveXmlLineChart(writer); | |
360 break; | |
361 case Chart::CT_Scatter: | |
362 saveXmlScatterChart(writer); | |
363 break; | |
364 case Chart::CT_Area: | |
365 case Chart::CT_Area3D: | |
366 saveXmlAreaChart(writer); | |
367 break; | |
368 case Chart::CT_Doughnut: | |
369 saveXmlDoughnutChart(writer); | |
370 break; | |
371 default: | |
372 break; | |
373 } | |
374 saveXmlAxes(writer); | |
375 writer.writeEndElement(); //plotArea | |
376 | |
377 // saveXmlLegend(writer); | |
378 | |
379 writer.writeEndElement(); //chart | |
380 } | |
381 | |
382 void ChartPrivate::saveXmlPieChart(QXmlStreamWriter &writer) const | |
383 { | |
384 QString name = chartType==Chart::CT_Pie ? QStringLiteral("c:pieChart") : QStringLiteral("c:pie3DChart"); | |
385 | |
386 writer.writeStartElement(name); | |
387 | |
388 //Do the same behavior as Excel, Pie prefer varyColors | |
389 writer.writeEmptyElement(QStringLiteral("c:varyColors")); | |
390 writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1")); | |
391 | |
392 for (int i=0; i<seriesList.size(); ++i) | |
393 saveXmlSer(writer, seriesList[i].data(), i); | |
394 | |
395 writer.writeEndElement(); //pieChart, pie3DChart | |
396 } | |
397 | |
398 void ChartPrivate::saveXmlBarChart(QXmlStreamWriter &writer) const | |
399 { | |
400 QString name = chartType==Chart::CT_Bar ? QStringLiteral("c:barChart") : QStringLiteral("c:bar3DChart"); | |
401 | |
402 writer.writeStartElement(name); | |
403 | |
404 writer.writeEmptyElement(QStringLiteral("c:barDir")); | |
405 writer.writeAttribute(QStringLiteral("val"), QStringLiteral("col")); | |
406 | |
407 for (int i=0; i<seriesList.size(); ++i) | |
408 saveXmlSer(writer, seriesList[i].data(), i); | |
409 | |
410 if (axisList.isEmpty()) { | |
411 //The order the axes?? | |
412 const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1))); | |
413 const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0))); | |
414 } | |
415 | |
416 //Note: Bar3D have 2~3 axes | |
417 Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Bar3D)); | |
418 | |
419 for (int i=0; i<axisList.size(); ++i) { | |
420 writer.writeEmptyElement(QStringLiteral("c:axId")); | |
421 writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId)); | |
422 } | |
423 | |
424 writer.writeEndElement(); //barChart, bar3DChart | |
425 } | |
426 | |
427 void ChartPrivate::saveXmlLineChart(QXmlStreamWriter &writer) const | |
428 { | |
429 QString name = chartType==Chart::CT_Line ? QStringLiteral("c:lineChart") : QStringLiteral("c:line3DChart"); | |
430 | |
431 writer.writeStartElement(name); | |
432 | |
433 writer.writeEmptyElement(QStringLiteral("grouping")); | |
434 | |
435 for (int i=0; i<seriesList.size(); ++i) | |
436 saveXmlSer(writer, seriesList[i].data(), i); | |
437 | |
438 if (axisList.isEmpty()) { | |
439 const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1))); | |
440 const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0))); | |
441 if (chartType==Chart::CT_Line3D) | |
442 const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Ser, XlsxAxis::Bottom, 2, 0))); | |
443 } | |
444 | |
445 Q_ASSERT((axisList.size()==2||chartType==Chart::CT_Line)|| (axisList.size()==3 && chartType==Chart::CT_Line3D)); | |
446 | |
447 for (int i=0; i<axisList.size(); ++i) { | |
448 writer.writeEmptyElement(QStringLiteral("c:axId")); | |
449 writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId)); | |
450 } | |
451 | |
452 writer.writeEndElement(); //lineChart, line3DChart | |
453 } | |
454 | |
455 void ChartPrivate::saveXmlScatterChart(QXmlStreamWriter &writer) const | |
456 { | |
457 const QString name = QStringLiteral("c:scatterChart"); | |
458 | |
459 writer.writeStartElement(name); | |
460 | |
461 writer.writeEmptyElement(QStringLiteral("c:scatterStyle")); | |
462 | |
463 for (int i=0; i<seriesList.size(); ++i) | |
464 saveXmlSer(writer, seriesList[i].data(), i); | |
465 | |
466 if (axisList.isEmpty()) { | |
467 const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Bottom, 0, 1))); | |
468 const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0))); | |
469 } | |
470 | |
471 Q_ASSERT(axisList.size()==2); | |
472 | |
473 for (int i=0; i<axisList.size(); ++i) { | |
474 writer.writeEmptyElement(QStringLiteral("c:axId")); | |
475 writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId)); | |
476 } | |
477 | |
478 writer.writeEndElement(); //c:scatterChart | |
479 } | |
480 | |
481 void ChartPrivate::saveXmlAreaChart(QXmlStreamWriter &writer) const | |
482 { | |
483 QString name = chartType==Chart::CT_Area ? QStringLiteral("c:areaChart") : QStringLiteral("c:area3DChart"); | |
484 | |
485 writer.writeStartElement(name); | |
486 | |
487 writer.writeEmptyElement(QStringLiteral("grouping")); | |
488 | |
489 for (int i=0; i<seriesList.size(); ++i) | |
490 saveXmlSer(writer, seriesList[i].data(), i); | |
491 | |
492 if (axisList.isEmpty()) { | |
493 const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1))); | |
494 const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0))); | |
495 } | |
496 | |
497 //Note: Area3D have 2~3 axes | |
498 Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Area3D)); | |
499 | |
500 for (int i=0; i<axisList.size(); ++i) { | |
501 writer.writeEmptyElement(QStringLiteral("c:axId")); | |
502 writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId)); | |
503 } | |
504 | |
505 writer.writeEndElement(); //lineChart, line3DChart | |
506 } | |
507 | |
508 void ChartPrivate::saveXmlDoughnutChart(QXmlStreamWriter &writer) const | |
509 { | |
510 QString name = QStringLiteral("c:doughnutChart"); | |
511 | |
512 writer.writeStartElement(name); | |
513 | |
514 writer.writeEmptyElement(QStringLiteral("c:varyColors")); | |
515 writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1")); | |
516 | |
517 for (int i=0; i<seriesList.size(); ++i) | |
518 saveXmlSer(writer, seriesList[i].data(), i); | |
519 | |
520 writer.writeStartElement(QStringLiteral("c:holeSize")); | |
521 writer.writeAttribute(QStringLiteral("val"), QString::number(50)); | |
522 | |
523 writer.writeEndElement(); | |
524 } | |
525 | |
526 void ChartPrivate::saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const | |
527 { | |
528 writer.writeStartElement(QStringLiteral("c:ser")); | |
529 writer.writeEmptyElement(QStringLiteral("c:idx")); | |
530 writer.writeAttribute(QStringLiteral("val"), QString::number(id)); | |
531 writer.writeEmptyElement(QStringLiteral("c:order")); | |
532 writer.writeAttribute(QStringLiteral("val"), QString::number(id)); | |
533 | |
534 if (!ser->axDataSource_numRef.isEmpty()) { | |
535 if (chartType == Chart::CT_Scatter || chartType == Chart::CT_Bubble) | |
536 writer.writeStartElement(QStringLiteral("c:xVal")); | |
537 else | |
538 writer.writeStartElement(QStringLiteral("c:cat")); | |
539 writer.writeStartElement(QStringLiteral("c:numRef")); | |
540 writer.writeTextElement(QStringLiteral("c:f"), ser->axDataSource_numRef); | |
541 writer.writeEndElement();//c:numRef | |
542 writer.writeEndElement();//c:cat or c:xVal | |
543 } | |
544 | |
545 if (!ser->numberDataSource_numRef.isEmpty()) { | |
546 if (chartType == Chart::CT_Scatter || chartType == Chart::CT_Bubble) | |
547 writer.writeStartElement(QStringLiteral("c:yVal")); | |
548 else | |
549 writer.writeStartElement(QStringLiteral("c:val")); | |
550 writer.writeStartElement(QStringLiteral("c:numRef")); | |
551 writer.writeTextElement(QStringLiteral("c:f"), ser->numberDataSource_numRef); | |
552 writer.writeEndElement();//c:numRef | |
553 writer.writeEndElement();//c:val or c:yVal | |
554 } | |
555 | |
556 writer.writeEndElement();//c:ser | |
557 } | |
558 | |
559 bool ChartPrivate::loadXmlAxis(QXmlStreamReader &reader) | |
560 { | |
561 Q_ASSERT(reader.name().endsWith(QLatin1String("Ax"))); | |
562 QString name = reader.name().toString(); | |
563 | |
564 XlsxAxis *axis = new XlsxAxis; | |
565 if (name == QLatin1String("valAx")) | |
566 axis->type = XlsxAxis::T_Val; | |
567 else if (name == QLatin1String("catAx")) | |
568 axis->type = XlsxAxis::T_Cat; | |
569 else if (name == QLatin1String("serAx")) | |
570 axis->type = XlsxAxis::T_Ser; | |
571 else | |
572 axis->type = XlsxAxis::T_Date; | |
573 | |
574 axisList.append(QSharedPointer<XlsxAxis>(axis)); | |
575 | |
576 while (!reader.atEnd()) { | |
577 reader.readNextStartElement(); | |
578 if (reader.tokenType() == QXmlStreamReader::StartElement) { | |
579 if (reader.name() == QLatin1String("axPos")) { | |
580 QXmlStreamAttributes attrs = reader.attributes(); | |
581 QStringRef pos = attrs.value(QLatin1String("val")); | |
582 if (pos==QLatin1String("l")) | |
583 axis->axisPos = XlsxAxis::Left; | |
584 else if (pos==QLatin1String("r")) | |
585 axis->axisPos = XlsxAxis::Right; | |
586 else if (pos==QLatin1String("b")) | |
587 axis->axisPos = XlsxAxis::Bottom; | |
588 else | |
589 axis->axisPos = XlsxAxis::Top; | |
590 } else if (reader.name() == QLatin1String("axId")) { | |
591 axis->axisId = reader.attributes().value(QLatin1String("val")).toString().toInt(); | |
592 } else if (reader.name() == QLatin1String("crossAx")) { | |
593 axis->crossAx = reader.attributes().value(QLatin1String("val")).toString().toInt(); | |
594 } | |
595 } else if (reader.tokenType() == QXmlStreamReader::EndElement | |
596 && reader.name() == name) { | |
597 break; | |
598 } | |
599 } | |
600 | |
601 return true; | |
602 } | |
603 | |
604 void ChartPrivate::saveXmlAxes(QXmlStreamWriter &writer) const | |
605 { | |
606 for (int i=0; i<axisList.size(); ++i) { | |
607 XlsxAxis *axis = axisList[i].data(); | |
608 QString name; | |
609 switch (axis->type) { | |
610 case XlsxAxis::T_Cat: name = QStringLiteral("c:catAx"); break; | |
611 case XlsxAxis::T_Val: name = QStringLiteral("c:valAx"); break; | |
612 case XlsxAxis::T_Ser: name = QStringLiteral("c:serAx"); break; | |
613 case XlsxAxis::T_Date: name = QStringLiteral("c:dateAx"); break; | |
614 default: break; | |
615 } | |
616 | |
617 QString pos; | |
618 switch (axis->axisPos) { | |
619 case XlsxAxis::Top: pos = QStringLiteral("t"); break; | |
620 case XlsxAxis::Bottom: pos = QStringLiteral("b"); break; | |
621 case XlsxAxis::Left: pos = QStringLiteral("l"); break; | |
622 case XlsxAxis::Right: pos = QStringLiteral("r"); break; | |
623 default: break; | |
624 } | |
625 | |
626 writer.writeStartElement(name); | |
627 writer.writeEmptyElement(QStringLiteral("c:axId")); | |
628 writer.writeAttribute(QStringLiteral("val"), QString::number(axis->axisId)); | |
629 | |
630 writer.writeStartElement(QStringLiteral("c:scaling")); | |
631 writer.writeEmptyElement(QStringLiteral("c:orientation")); | |
632 writer.writeAttribute(QStringLiteral("val"), QStringLiteral("minMax")); | |
633 writer.writeEndElement();//c:scaling | |
634 | |
635 writer.writeEmptyElement(QStringLiteral("c:axPos")); | |
636 writer.writeAttribute(QStringLiteral("val"), pos); | |
637 | |
638 writer.writeEmptyElement(QStringLiteral("c:crossAx")); | |
639 writer.writeAttribute(QStringLiteral("val"), QString::number(axis->crossAx)); | |
640 | |
641 writer.writeEndElement();//name | |
642 } | |
643 } | |
644 | |
645 QT_END_NAMESPACE_XLSX |