From 327fa0b9b31827bffcded66bc86389c5f864a662 Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Thu, 16 Jan 2014 17:30:53 +0800 Subject: [PATCH] Add very basic chart support --- examples/xlsx/chart/chart.pro | 9 +++ examples/xlsx/chart/main.cpp | 31 +++++++++ examples/xlsx/xlsx.pro | 1 + src/xlsx/qtxlsx.pri | 10 ++- src/xlsx/xlsxabstractchart.cpp | 86 ++++++++++++++++++++++++ src/xlsx/xlsxabstractchart.h | 63 ++++++++++++++++++ src/xlsx/xlsxabstractchart_p.h | 66 +++++++++++++++++++ src/xlsx/xlsxchartfile.cpp | 103 ++++++++++++++++++++++++++++- src/xlsx/xlsxchartfile_p.h | 23 +++++++ src/xlsx/xlsxdocument.cpp | 1 + src/xlsx/xlsxdrawinganchor.cpp | 14 +++- src/xlsx/xlsxdrawinganchor_p.h | 1 + src/xlsx/xlsxpiechart.cpp | 115 +++++++++++++++++++++++++++++++++ src/xlsx/xlsxpiechart.h | 49 ++++++++++++++ src/xlsx/xlsxpiechart_p.h | 57 ++++++++++++++++ src/xlsx/xlsxworksheet.cpp | 31 ++++++++- src/xlsx/xlsxworksheet.h | 3 +- 17 files changed, 656 insertions(+), 7 deletions(-) create mode 100644 examples/xlsx/chart/chart.pro create mode 100644 examples/xlsx/chart/main.cpp create mode 100644 src/xlsx/xlsxabstractchart.cpp create mode 100644 src/xlsx/xlsxabstractchart.h create mode 100644 src/xlsx/xlsxabstractchart_p.h create mode 100644 src/xlsx/xlsxpiechart.cpp create mode 100644 src/xlsx/xlsxpiechart.h create mode 100644 src/xlsx/xlsxpiechart_p.h diff --git a/examples/xlsx/chart/chart.pro b/examples/xlsx/chart/chart.pro new file mode 100644 index 0000000..71348ad --- /dev/null +++ b/examples/xlsx/chart/chart.pro @@ -0,0 +1,9 @@ +TARGET = chart + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/examples/xlsx/chart/main.cpp b/examples/xlsx/chart/main.cpp new file mode 100644 index 0000000..8a2282c --- /dev/null +++ b/examples/xlsx/chart/main.cpp @@ -0,0 +1,31 @@ +#include +#include "xlsxdocument.h" +#include "xlsxpiechart.h" +#include "xlsxworksheet.h" + +using namespace QXlsx; + +int main() +{ + //![0] + Document xlsx; + + Worksheet *sheet = xlsx.currentWorksheet(); + for (int i=1; i<10; ++i) + sheet->write(i, 1, i*i); + //![0] + + //![1] + PieChart *chart = new PieChart; + chart->addSeries(CellRange("A1:A9"), sheet->sheetName()); + sheet->insertChart(3, 3, chart, QSize(300, 300)); + //![1] + + //![2] + xlsx.saveAs("Book1.xlsx"); + //![2] + + Document xlsx2("Book1.xlsx"); + xlsx2.saveAs("Book2.xlsx"); + return 0; +} diff --git a/examples/xlsx/xlsx.pro b/examples/xlsx/xlsx.pro index d92f5f9..d4e75da 100644 --- a/examples/xlsx/xlsx.pro +++ b/examples/xlsx/xlsx.pro @@ -14,6 +14,7 @@ SUBDIRS = hello \ conditionalformatting \ worksheetoperations \ hyperlinks \ + chart \ demo qtHaveModule(widgets): SUBDIRS += xlsxwidget diff --git a/src/xlsx/qtxlsx.pri b/src/xlsx/qtxlsx.pri index e993f9e..acbb57a 100755 --- a/src/xlsx/qtxlsx.pri +++ b/src/xlsx/qtxlsx.pri @@ -39,7 +39,11 @@ HEADERS += $$PWD/xlsxdocpropscore_p.h \ $$PWD/xlsxmediafile_p.h \ $$PWD/xlsxooxmlfile.h \ $$PWD/xlsxooxmlfile_p.h \ - $$PWD/xlsxchartfile_p.h + $$PWD/xlsxchartfile_p.h \ + $$PWD/xlsxabstractchart.h \ + $$PWD/xlsxabstractchart_p.h \ + $$PWD/xlsxpiechart.h \ + $$PWD/xlsxpiechart_p.h SOURCES += $$PWD/xlsxdocpropscore.cpp \ $$PWD/xlsxdocpropsapp.cpp \ @@ -66,4 +70,6 @@ SOURCES += $$PWD/xlsxdocpropscore.cpp \ $$PWD/xlsxdrawinganchor.cpp \ $$PWD/xlsxmediafile.cpp \ $$PWD/xlsxooxmlfile.cpp \ - $$PWD/xlsxchartfile.cpp + $$PWD/xlsxchartfile.cpp \ + $$PWD/xlsxabstractchart.cpp \ + $$PWD/xlsxpiechart.cpp diff --git a/src/xlsx/xlsxabstractchart.cpp b/src/xlsx/xlsxabstractchart.cpp new file mode 100644 index 0000000..7b39fab --- /dev/null +++ b/src/xlsx/xlsxabstractchart.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** All right reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "xlsxabstractchart.h" +#include "xlsxabstractchart_p.h" +#include "xlsxchartfile_p.h" +#include "xlsxcellrange.h" +#include "xlsxutility_p.h" + +QT_BEGIN_NAMESPACE_XLSX + +AbstractChartPrivate::AbstractChartPrivate(AbstractChart *chart) + :q_ptr(chart) +{ + +} + +AbstractChartPrivate::~AbstractChartPrivate() +{ + +} + +/*! + * \class AbstractChart + * + * Base class for all the charts. + */ + + +AbstractChart::AbstractChart() + :d_ptr(new AbstractChartPrivate(this)) +{ +} + +AbstractChart::AbstractChart(AbstractChartPrivate *d) + :d_ptr(d) +{ + +} + +AbstractChart::~AbstractChart() +{ + Q_D(AbstractChart); + if (d->cf) + d->cf->m_chart = 0; +} + +void AbstractChart::addSeries(const CellRange &range, const QString &sheet) +{ + Q_D(AbstractChart); + + QString serRef = sheet; + serRef += QLatin1String("!"); + serRef += xl_rowcol_to_cell(range.firstRow(), range.firstColumn(), true, true); + serRef += QLatin1String(":"); + serRef += xl_rowcol_to_cell(range.lastRow(), range.lastColumn(), true, true); + + XlsxSeries *series = new XlsxSeries; + series->numRef = serRef; + + d->seriesList.append(QSharedPointer(series)); +} + +QT_END_NAMESPACE_XLSX diff --git a/src/xlsx/xlsxabstractchart.h b/src/xlsx/xlsxabstractchart.h new file mode 100644 index 0000000..8c59896 --- /dev/null +++ b/src/xlsx/xlsxabstractchart.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** All right reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef QXLSX_XLSXABSTRACTCHART_H +#define QXLSX_XLSXABSTRACTCHART_H + +#include "xlsxglobal.h" + +#include + +class QXmlStreamReader; +class QXmlStreamWriter; + +QT_BEGIN_NAMESPACE_XLSX + +class ChartFile; +class AbstractChartPrivate; +class CellRange; + +class Q_XLSX_EXPORT AbstractChart +{ + Q_DECLARE_PRIVATE(AbstractChart) + +public: + AbstractChart(); + virtual ~AbstractChart(); + + void addSeries(const CellRange &range, const QString &sheet=QString()); + +protected: + friend class ChartFile; + AbstractChart(AbstractChartPrivate *d); + virtual bool loadFromXml(QXmlStreamReader &reader) = 0; + virtual void saveToXml(QXmlStreamWriter &writer) const = 0; + + AbstractChartPrivate * d_ptr; +}; + +QT_END_NAMESPACE_XLSX + +#endif // QXLSX_XLSXABSTRACTCHART_H diff --git a/src/xlsx/xlsxabstractchart_p.h b/src/xlsx/xlsxabstractchart_p.h new file mode 100644 index 0000000..8de858a --- /dev/null +++ b/src/xlsx/xlsxabstractchart_p.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** All right reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef XLSXABSTRACTCHART_P_H +#define XLSXABSTRACTCHART_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxabstractchart.h" +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +class XlsxSeries +{ +public: + + QString numRef; +}; + +class AbstractChartPrivate +{ + Q_DECLARE_PUBLIC(AbstractChart) +public: + AbstractChartPrivate(AbstractChart *chart); + virtual ~AbstractChartPrivate(); + + QList > seriesList; + ChartFile *cf; + AbstractChart *q_ptr; +}; + +QT_END_NAMESPACE_XLSX +#endif // XLSXABSTRACTCHART_P_H diff --git a/src/xlsx/xlsxchartfile.cpp b/src/xlsx/xlsxchartfile.cpp index 5649e6a..75d83a4 100644 --- a/src/xlsx/xlsxchartfile.cpp +++ b/src/xlsx/xlsxchartfile.cpp @@ -24,7 +24,9 @@ ****************************************************************************/ #include "xlsxchartfile_p.h" - +#include "xlsxabstractchart.h" +#include "xlsxabstractchart_p.h" +#include "xlsxpiechart.h" #include #include #include @@ -35,15 +37,112 @@ ChartFile::ChartFile() { } +ChartFile::~ChartFile() +{ + if (m_chart) + delete m_chart; +} + +AbstractChart* ChartFile::chart() const +{ + return m_chart; +} + +void ChartFile::setChart(AbstractChart *chart) +{ + m_chart = chart; + chart->d_func()->cf = this; +} + void ChartFile::saveToXmlFile(QIODevice *device) const { + QXmlStreamWriter writer(device); + writer.writeStartDocument(QStringLiteral("1.0"), true); + writer.writeStartElement(QStringLiteral("c:chartSpace")); + writer.writeAttribute(QStringLiteral("xmlns:c"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart")); + writer.writeAttribute(QStringLiteral("xmlns:a"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/main")); + writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships")); + + saveXmlChart(writer); + + writer.writeEndElement();//c:chartSpace + writer.writeEndDocument(); } bool ChartFile::loadFromXmlFile(QIODevice *device) { + QXmlStreamReader reader(device); + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("chart")) { + loadXmlChart(reader); + } + } + } + return true; +} + +bool ChartFile::loadXmlChart(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("chart")); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("plotArea")) { + loadXmlPlotArea(reader); + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement && + reader.name() == QLatin1String("chart")) { + break; + } + } + return true; +} + +bool ChartFile::loadXmlPlotArea(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("plotArea")); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + AbstractChart *chart = 0; + if (reader.name() == QLatin1String("layout")) { + //... + } else if (reader.name() == QLatin1String("pieChart")) { + chart = new PieChart; + chart->loadFromXml(reader); + } else if (reader.name() == QLatin1String("")) { + + } + + if (chart) { + chart->loadFromXml(reader); + setChart(chart); + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement && + reader.name() == QLatin1String("plotArea")) { + break; + } + } + return true; +} + +bool ChartFile::saveXmlChart(QXmlStreamWriter &writer) const +{ + writer.writeStartElement(QStringLiteral("c:chart")); + writer.writeStartElement(QStringLiteral("c:plotArea")); + m_chart->saveToXml(writer); + writer.writeEndElement(); //plotArea + +// writer.writeStartElement(QStringLiteral("c:legend")); +// writer.writeEndElement(); //legend - return false; + writer.writeEndElement(); //chart + return true; } } // namespace QXlsx diff --git a/src/xlsx/xlsxchartfile_p.h b/src/xlsx/xlsxchartfile_p.h index 5a3779f..dde044f 100644 --- a/src/xlsx/xlsxchartfile_p.h +++ b/src/xlsx/xlsxchartfile_p.h @@ -39,15 +39,38 @@ #include "xlsxooxmlfile.h" +#include + +class QXmlStreamReader; +class QXmlStreamWriter; + namespace QXlsx { +class AbstractChart; + class ChartFile : public OOXmlFile { public: ChartFile(); + ~ChartFile(); + + AbstractChart *chart() const; + void setChart(AbstractChart *chart); void saveToXmlFile(QIODevice *device) const; bool loadFromXmlFile(QIODevice *device); + +private: + bool loadXmlChart(QXmlStreamReader &reader); + bool loadXmlPlotArea(QXmlStreamReader &reader); + AbstractChart *loadXmlPieChart(QXmlStreamReader &reader); + + bool saveXmlChart(QXmlStreamWriter &writer) const; + + friend class AbstractChart; + // Don't use sharedpointer here, + // in case some users create AbstractChart in the stack. + AbstractChart *m_chart; }; } // namespace QXlsx diff --git a/src/xlsx/xlsxdocument.cpp b/src/xlsx/xlsxdocument.cpp index 2576029..0259260 100644 --- a/src/xlsx/xlsxdocument.cpp +++ b/src/xlsx/xlsxdocument.cpp @@ -284,6 +284,7 @@ bool DocumentPrivate::savePackage(QIODevice *device) const // save chart xml files for (int i=0; ichartFiles().size(); ++i) { + contentTypes.addChartName(QStringLiteral("chart%1").arg(i+1)); QSharedPointer cf = workbook->chartFiles()[i]; zipWriter.addFile(QStringLiteral("xl/charts/chart%1.xml").arg(i+1), cf->saveToXmlData()); } diff --git a/src/xlsx/xlsxdrawinganchor.cpp b/src/xlsx/xlsxdrawinganchor.cpp index 08dc267..1b4fbdb 100644 --- a/src/xlsx/xlsxdrawinganchor.cpp +++ b/src/xlsx/xlsxdrawinganchor.cpp @@ -91,6 +91,16 @@ void DrawingAnchor::setObjectPicture(const QImage &img) m_pictureFile = QSharedPointer(new MediaFile(ba, QStringLiteral("png"), QStringLiteral("image/png"))); m_drawing->workbook->addMediaFile(m_pictureFile); + + m_objectType = Picture; +} + +void DrawingAnchor::setObjectGraphicFrame(QSharedPointer chart) +{ + m_chartFile = chart; + m_drawing->workbook->addChartFile(chart); + + m_objectType = GraphicFrame; } QPoint DrawingAnchor::loadXmlPos(QXmlStreamReader &reader) @@ -316,13 +326,15 @@ void DrawingAnchor::saveXmlObjectGraphicFrame(QXmlStreamWriter &writer) const writer.writeAttribute(QStringLiteral("uri"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart")); int idx = m_drawing->workbook->chartFiles().indexOf(m_chartFile); - m_drawing->relationships.addDocumentRelationship(QStringLiteral("/chart"), QStringLiteral("../charts/chart%1.xml").arg(idx)); + m_drawing->relationships.addDocumentRelationship(QStringLiteral("/chart"), QStringLiteral("../charts/chart%1.xml").arg(idx+1)); writer.writeEmptyElement(QStringLiteral("c:chart")); writer.writeAttribute(QStringLiteral("xmlns:c"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart")); writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships")); writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(m_drawing->relationships.count())); + writer.writeEndElement(); //a:graphicData + writer.writeEndElement(); //a:graphic writer.writeEndElement(); //xdr:graphicFrame } diff --git a/src/xlsx/xlsxdrawinganchor_p.h b/src/xlsx/xlsxdrawinganchor_p.h index 73aa035..d2924a1 100644 --- a/src/xlsx/xlsxdrawinganchor_p.h +++ b/src/xlsx/xlsxdrawinganchor_p.h @@ -76,6 +76,7 @@ public: DrawingAnchor(Drawing *drawing, ObjectType objectType); virtual ~DrawingAnchor(); void setObjectPicture(const QImage &img); + void setObjectGraphicFrame(QSharedPointer chart); virtual bool loadFromXml(QXmlStreamReader &reader) = 0; virtual void saveToXml(QXmlStreamWriter &writer) const = 0; diff --git a/src/xlsx/xlsxpiechart.cpp b/src/xlsx/xlsxpiechart.cpp new file mode 100644 index 0000000..b6dd748 --- /dev/null +++ b/src/xlsx/xlsxpiechart.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** All right reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "xlsxpiechart.h" +#include "xlsxpiechart_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +PieChartPrivate::PieChartPrivate(PieChart *chart) + : AbstractChartPrivate(chart) +{ + +} + +/*! + * \class PieChart + */ + +PieChart::PieChart() + : AbstractChart(new PieChartPrivate(this)) +{ +} + +bool PieChart::loadFromXml(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("pieChart")); + + Q_D(PieChart); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("ser")) { + d->loadXmlSer(reader); + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("pieChart")) { + break; + } + } + return true; +} + +bool PieChartPrivate::loadXmlSer(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("ser")); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("f")) { + XlsxSeries *series = new XlsxSeries; + series->numRef = reader.readElementText(); + seriesList.append(QSharedPointer(series)); + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("ser")) { + break; + } + } + + return true; +} + +void PieChart::saveToXml(QXmlStreamWriter &writer) const +{ + Q_D(const PieChart); + + writer.writeStartElement(QStringLiteral("c:pieChart")); + writer.writeEmptyElement(QStringLiteral("c:varyColors")); + writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1")); + for (int i=0; iseriesList.size(); ++i) { + XlsxSeries *ser = d->seriesList[i].data(); + writer.writeStartElement(QStringLiteral("c:ser")); + writer.writeEmptyElement(QStringLiteral("c:idx")); + writer.writeAttribute(QStringLiteral("val"), QString::number(i)); + writer.writeEmptyElement(QStringLiteral("c:order")); + writer.writeAttribute(QStringLiteral("val"), QString::number(i)); + writer.writeStartElement(QStringLiteral("c:val")); + writer.writeStartElement(QStringLiteral("c:numRef")); + writer.writeTextElement(QStringLiteral("c:f"), ser->numRef); + writer.writeEndElement();//c:numRef + writer.writeEndElement();//c:val + writer.writeEndElement();//c:ser + } + + writer.writeEndElement(); //pieChart +} + +QT_END_NAMESPACE_XLSX diff --git a/src/xlsx/xlsxpiechart.h b/src/xlsx/xlsxpiechart.h new file mode 100644 index 0000000..36f82d7 --- /dev/null +++ b/src/xlsx/xlsxpiechart.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** All right reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef QXLSX_XLSXPIECHART_H +#define QXLSX_XLSXPIECHART_H + +#include "xlsxabstractchart.h" + +QT_BEGIN_NAMESPACE_XLSX + +class PieChartPrivate; + +class Q_XLSX_EXPORT PieChart : public AbstractChart +{ + Q_DECLARE_PRIVATE(PieChart) + +public: + PieChart(); + +protected: + bool loadFromXml(QXmlStreamReader &reader); + void saveToXml(QXmlStreamWriter &writer) const; +}; + +QT_END_NAMESPACE_XLSX + +#endif // QXLSX_XLSXPIECHART_H diff --git a/src/xlsx/xlsxpiechart_p.h b/src/xlsx/xlsxpiechart_p.h new file mode 100644 index 0000000..ccba799 --- /dev/null +++ b/src/xlsx/xlsxpiechart_p.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** All right reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#ifndef XLSXPIECHART_P_H +#define XLSXPIECHART_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxpiechart.h" +#include "xlsxabstractchart_p.h" + +QT_BEGIN_NAMESPACE_XLSX + +class PieChartPrivate : public AbstractChartPrivate +{ + Q_DECLARE_PUBLIC(PieChart) + +public: + PieChartPrivate(PieChart *chart); + + bool loadXmlSer(QXmlStreamReader &reader); +}; + +QT_END_NAMESPACE_XLSX + +#endif // XLSXPIECHART_P_H diff --git a/src/xlsx/xlsxworksheet.cpp b/src/xlsx/xlsxworksheet.cpp index 09d5cf8..3b21af4 100755 --- a/src/xlsx/xlsxworksheet.cpp +++ b/src/xlsx/xlsxworksheet.cpp @@ -37,6 +37,8 @@ #include "xlsxcellrange.h" #include "xlsxconditionalformatting_p.h" #include "xlsxdrawinganchor_p.h" +#include "xlsxabstractchart.h" +#include "xlsxchartfile_p.h" #include #include @@ -1044,6 +1046,33 @@ int Worksheet::insertImage(int row, int column, const QImage &image, const QPoin return insertImage(row, column, image); } +bool Worksheet::insertChart(int row, int column, AbstractChart *chart, const QSize &size) +{ + Q_D(Worksheet); + for (int i=0; i< d->workbook->chartFiles().size(); ++i) { + if (d->workbook->chartFiles()[i]->chart() == chart) + return false; + } + + if (!d->drawing) + d->drawing = QSharedPointer(new Drawing(d->workbook)); + + DrawingOneCellAnchor *anchor = new DrawingOneCellAnchor(d->drawing.data(), DrawingAnchor::Picture); + + /* + The size are expressed as English Metric Units (EMUs). There are + 12,700 EMUs per point. Therefore, 12,700 * 3 /4 = 9,525 EMUs per + pixel + */ + anchor->from = XlsxMarker(row, column, 0, 0); + anchor->ext = size * 9525; + + QSharedPointer chartFile = QSharedPointer(new ChartFile); + chartFile->setChart(chart); + anchor->setObjectGraphicFrame(chartFile); + return true; +} + /*! Merge a \a range of cells. The first cell should contain the data and the others should be blank. All cells will be applied the same style if a valid \a format is given. @@ -2089,7 +2118,7 @@ bool Worksheet::loadFromXmlFile(QIODevice *device) QString name = d->relationships.getRelationshipById(rId).target; QString path = QDir::cleanPath(splitPath(filePath())[0] + QLatin1String("/") + name); d->drawing = QSharedPointer(new Drawing(d->workbook)); - d->drawing->filePath() = path; + d->drawing->setFilePath(path); } } } diff --git a/src/xlsx/xlsxworksheet.h b/src/xlsx/xlsxworksheet.h index 1fe7a57..c5a9f86 100755 --- a/src/xlsx/xlsxworksheet.h +++ b/src/xlsx/xlsxworksheet.h @@ -48,9 +48,9 @@ class Drawing; class DataValidation; class ConditionalFormatting; class CellRange; -struct XlsxImageData; class RichString; class Relationships; +class AbstractChart; class WorksheetPrivate; class Q_XLSX_EXPORT Worksheet : public OOXmlFile @@ -93,6 +93,7 @@ public: bool insertImage(int row, int column, const QImage &image); Q_DECL_DEPRECATED int insertImage(int row, int column, const QImage &image, const QPointF &offset, double xScale=1, double yScale=1); + bool insertChart(int row, int column, AbstractChart *chart, const QSize &size); int mergeCells(const QString &range, const Format &format=Format()); int mergeCells(const CellRange &range, const Format &format=Format());