Code refactoring: Improve picture support
Don't lost picture information when edit existing .xlsx files
This commit is contained in:
+6
-2
@@ -34,7 +34,9 @@ HEADERS += $$PWD/xlsxdocpropscore_p.h \
|
||||
$$PWD/xlsxconditionalformatting.h \
|
||||
$$PWD/xlsxconditionalformatting_p.h \
|
||||
$$PWD/xlsxcolor_p.h \
|
||||
$$PWD/xlsxnumformatparser_p.h
|
||||
$$PWD/xlsxnumformatparser_p.h \
|
||||
$$PWD/xlsxdrawinganchor_p.h \
|
||||
$$PWD/xlsxmediafile_p.h
|
||||
|
||||
SOURCES += $$PWD/xlsxdocpropscore.cpp \
|
||||
$$PWD/xlsxdocpropsapp.cpp \
|
||||
@@ -57,4 +59,6 @@ SOURCES += $$PWD/xlsxdocpropscore.cpp \
|
||||
$$PWD/xlsxrichstring.cpp \
|
||||
$$PWD/xlsxconditionalformatting.cpp \
|
||||
$$PWD/xlsxcolor.cpp \
|
||||
$$PWD/xlsxnumformatparser.cpp
|
||||
$$PWD/xlsxnumformatparser.cpp \
|
||||
$$PWD/xlsxdrawinganchor.cpp \
|
||||
$$PWD/xlsxmediafile.cpp
|
||||
|
||||
+32
-28
@@ -37,12 +37,14 @@
|
||||
#include "xlsxutility_p.h"
|
||||
#include "xlsxworkbook_p.h"
|
||||
#include "xlsxdrawing_p.h"
|
||||
#include "xlsxmediafile_p.h"
|
||||
#include "xlsxzipreader_p.h"
|
||||
#include "xlsxzipwriter_p.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QPointF>
|
||||
#include <QBuffer>
|
||||
#include <QDir>
|
||||
|
||||
QT_BEGIN_NAMESPACE_XLSX
|
||||
|
||||
@@ -189,6 +191,27 @@ bool DocumentPrivate::loadPackage(QIODevice *device)
|
||||
if (zipReader.filePaths().contains(rel_path))
|
||||
sheet->relationships().loadFromXmlData(zipReader.fileData(rel_path));
|
||||
sheet->loadFromXmlData(zipReader.fileData(worksheet_path));
|
||||
|
||||
//load drawing if exists
|
||||
if (!sheet->drawingPath().isEmpty()) {
|
||||
QString drawingPath = QDir::cleanPath(splitPath(worksheet_path)[0] + QLatin1String("/") + sheet->drawingPath());
|
||||
Drawing *drawing = new Drawing(workbook.data());
|
||||
drawing->pathInPackage = drawingPath;
|
||||
QString drawing_rel_path = getRelFilePath(drawingPath);
|
||||
if (zipReader.filePaths().contains(drawing_rel_path))
|
||||
drawing->relationships.loadFromXmlData(zipReader.fileData(drawing_rel_path));
|
||||
drawing->loadFromXmlData(zipReader.fileData(drawingPath));
|
||||
sheet->setDrawing(drawing);
|
||||
}
|
||||
}
|
||||
|
||||
//load media files
|
||||
QList<QSharedPointer<MediaFile> > mediaFileToLoad = workbook->mediaFiles();
|
||||
for (int i=0; i<mediaFileToLoad.size(); ++i) {
|
||||
QSharedPointer<MediaFile> mf = mediaFileToLoad[i];
|
||||
const QString path = mf->fileName();
|
||||
const QString suffix = path.mid(path.lastIndexOf(QLatin1Char('.'))+1);
|
||||
mf->set(zipReader.fileData(path), suffix);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -206,9 +229,6 @@ bool DocumentPrivate::savePackage(QIODevice *device) const
|
||||
DocPropsApp docPropsApp;
|
||||
DocPropsCore docPropsCore;
|
||||
|
||||
//: Todo
|
||||
workbook->prepareDrawings();
|
||||
|
||||
// save worksheet xml files
|
||||
for (int i=0; i<workbook->worksheetCount(); ++i) {
|
||||
Worksheet *sheet = workbook->worksheet(i);
|
||||
@@ -232,19 +252,8 @@ bool DocumentPrivate::savePackage(QIODevice *device) const
|
||||
|
||||
Drawing *drawing = workbook->drawings()[i];
|
||||
zipWriter.addFile(QStringLiteral("xl/drawings/drawing%1.xml").arg(i+1), drawing->saveToXmlData());
|
||||
}
|
||||
|
||||
for (int i=0; i<workbook->worksheetCount(); ++i) {
|
||||
Worksheet *sheet = workbook->worksheet(i);
|
||||
if (sheet->drawingLinks().size() == 0)
|
||||
continue;
|
||||
Relationships rels;
|
||||
|
||||
typedef QPair<QString, QString> PairType;
|
||||
foreach (PairType pair, sheet->drawingLinks())
|
||||
rels.addDocumentRelationship(pair.first, pair.second);
|
||||
|
||||
zipWriter.addFile(QStringLiteral("xl/drawings/_rels/drawing%1.xml.rels").arg(i+1), rels.saveToXmlData());
|
||||
if (!drawing->relationships.isEmpty())
|
||||
zipWriter.addFile(QStringLiteral("xl/drawings/_rels/drawing%1.xml.rels").arg(i+1), drawing->relationships.saveToXmlData());
|
||||
}
|
||||
|
||||
// save docProps app/core xml file
|
||||
@@ -274,17 +283,12 @@ bool DocumentPrivate::savePackage(QIODevice *device) const
|
||||
zipWriter.addFile(QStringLiteral("xl/theme/theme1.xml"), workbook->theme()->saveToXmlData());
|
||||
|
||||
// save image files
|
||||
if (!workbook->images().isEmpty())
|
||||
contentTypes.addDefault(QStringLiteral("png"), QStringLiteral("image/png"));
|
||||
for (int i=0; i<workbook->mediaFiles().size(); ++i) {
|
||||
QSharedPointer<MediaFile> mf = workbook->mediaFiles()[i];
|
||||
if (!mf->mimeType().isEmpty())
|
||||
contentTypes.addDefault(mf->suffix(), mf->mimeType());
|
||||
|
||||
for (int i=0; i<workbook->images().size(); ++i) {
|
||||
QImage image = workbook->images()[i];
|
||||
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
image.save(&buffer, "png");
|
||||
zipWriter.addFile(QStringLiteral("xl/media/image%1.png").arg(i+1), data);
|
||||
zipWriter.addFile(QStringLiteral("xl/media/image%1.%2").arg(i+1).arg(mf->suffix()), mf->contents());
|
||||
}
|
||||
|
||||
// save root .rels xml file
|
||||
@@ -388,9 +392,9 @@ QVariant Document::read(int row, int col) const
|
||||
* \brief Insert an \a image to current active worksheet to the position \a row, \a column with the given
|
||||
* \a xOffset, \a yOffset, \a xScale and \a yScale.
|
||||
*/
|
||||
int Document::insertImage(int row, int column, const QImage &image, double xOffset, double yOffset, double xScale, double yScale)
|
||||
int Document::insertImage(int row, int column, const QImage &image, double /*xOffset*/, double /*yOffset*/, double /*xScale*/, double /*yScale*/)
|
||||
{
|
||||
return currentWorksheet()->insertImage(row, column, image, QPointF(xOffset, yOffset), xScale, yScale);
|
||||
return currentWorksheet()->insertImage(row, column, image);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
+35
-141
@@ -24,6 +24,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "xlsxdrawing_p.h"
|
||||
#include "xlsxdrawinganchor_p.h"
|
||||
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QXmlStreamReader>
|
||||
@@ -31,10 +32,15 @@
|
||||
|
||||
namespace QXlsx {
|
||||
|
||||
Drawing::Drawing()
|
||||
Drawing::Drawing(Workbook *workbook)
|
||||
:workbook(workbook)
|
||||
{
|
||||
embedded = false;
|
||||
orientation = 0;
|
||||
|
||||
}
|
||||
|
||||
Drawing::~Drawing()
|
||||
{
|
||||
qDeleteAll(anchors);
|
||||
}
|
||||
|
||||
QByteArray Drawing::saveToXmlData() const
|
||||
@@ -48,6 +54,8 @@ QByteArray Drawing::saveToXmlData() const
|
||||
|
||||
void Drawing::saveToXmlFile(QIODevice *device) const
|
||||
{
|
||||
relationships.clear();
|
||||
|
||||
QXmlStreamWriter writer(device);
|
||||
|
||||
writer.writeStartDocument(QStringLiteral("1.0"), true);
|
||||
@@ -55,156 +63,42 @@ void Drawing::saveToXmlFile(QIODevice *device) const
|
||||
writer.writeAttribute(QStringLiteral("xmlns:xdr"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"));
|
||||
writer.writeAttribute(QStringLiteral("xmlns:a"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/main"));
|
||||
|
||||
if (embedded) {
|
||||
int index = 1;
|
||||
foreach (XlsxDrawingDimensionData *dimension, dimensionList) {
|
||||
writeTwoCellAnchor(writer, index, dimension);
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
//write the xdr:absoluteAnchor element
|
||||
writeAbsoluteAnchor(writer, 1);
|
||||
}
|
||||
foreach (DrawingAnchor *anchor, anchors)
|
||||
anchor->saveToXml(writer);
|
||||
|
||||
writer.writeEndElement();//xdr:wsDr
|
||||
writer.writeEndDocument();
|
||||
}
|
||||
|
||||
void Drawing::writeTwoCellAnchor(QXmlStreamWriter &writer, int index, XlsxDrawingDimensionData *data) const
|
||||
bool Drawing::loadFromXmlFile(QIODevice *device)
|
||||
{
|
||||
writer.writeStartElement(QStringLiteral("xdr:twoCellAnchor"));
|
||||
if (data->drawing_type == 2)
|
||||
writer.writeAttribute(QStringLiteral("editAs"), QStringLiteral("oneCell"));
|
||||
// if (shape)
|
||||
// writer.writeAttribute(QStringLiteral("editAs"), );
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:from"));
|
||||
writer.writeTextElement(QStringLiteral("xdr:col"), QString::number(data->col_from));
|
||||
writer.writeTextElement(QStringLiteral("xdr:colOff"), QString::number((int)data->col_from_offset));
|
||||
writer.writeTextElement(QStringLiteral("xdr:row"), QString::number(data->row_from));
|
||||
writer.writeTextElement(QStringLiteral("xdr:rowOff"), QString::number((int)data->row_from_offset));
|
||||
writer.writeEndElement(); //xdr:from
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:to"));
|
||||
writer.writeTextElement(QStringLiteral("xdr:col"), QString::number(data->col_to));
|
||||
writer.writeTextElement(QStringLiteral("xdr:colOff"), QString::number((int)data->col_to_offset));
|
||||
writer.writeTextElement(QStringLiteral("xdr:row"), QString::number(data->row_to));
|
||||
writer.writeTextElement(QStringLiteral("xdr:rowOff"), QString::number((int)data->row_to_offset));
|
||||
writer.writeEndElement(); //xdr:to
|
||||
|
||||
if (data->drawing_type == 1) {
|
||||
//Graphics frame, xdr:graphicFrame
|
||||
writeGraphicFrame(writer, index, data->description);
|
||||
} else if (data->drawing_type == 2) {
|
||||
//Image, xdr:pic
|
||||
writePicture(writer, index, data->col_absolute, data->row_absolute, data->width, data->height, data->description);
|
||||
} else {
|
||||
//Shape, xdr:sp
|
||||
QXmlStreamReader reader(device);
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("absoluteAnchor")) {
|
||||
DrawingAbsoluteAnchor * anchor = new DrawingAbsoluteAnchor(this);
|
||||
anchor->loadFromXml(reader);
|
||||
} else if (reader.name() == QLatin1String("oneCellAnchor")) {
|
||||
DrawingOneCellAnchor * anchor = new DrawingOneCellAnchor(this);
|
||||
anchor->loadFromXml(reader);
|
||||
} else if (reader.name() == QLatin1String("twoCellAnchor")) {
|
||||
DrawingTwoCellAnchor * anchor = new DrawingTwoCellAnchor(this);
|
||||
anchor->loadFromXml(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writer.writeEmptyElement(QStringLiteral("xdr:clientData"));
|
||||
writer.writeEndElement(); //xdr:twoCellAnchor
|
||||
return true;
|
||||
}
|
||||
|
||||
void Drawing::writeAbsoluteAnchor(QXmlStreamWriter &writer, int index) const
|
||||
bool Drawing::loadFromXmlData(const QByteArray &data)
|
||||
{
|
||||
writer.writeStartElement(QStringLiteral("xdr:absoluteAnchor"));
|
||||
if (orientation == 0) {
|
||||
writePos(writer, 0, 0);
|
||||
writeExt(writer, 9308969, 6078325);
|
||||
} else {
|
||||
writePos(writer, 0, -47625);
|
||||
writeExt(writer, 6162675, 6124575);
|
||||
}
|
||||
QBuffer buffer;
|
||||
buffer.setData(data);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
|
||||
writeGraphicFrame(writer, index);
|
||||
writer.writeEmptyElement(QStringLiteral("xdr:clientData"));
|
||||
|
||||
writer.writeEndElement(); //xdr:absoluteAnchor
|
||||
}
|
||||
|
||||
void Drawing::writePos(QXmlStreamWriter &writer, int x, int y) const
|
||||
{
|
||||
writer.writeEmptyElement(QStringLiteral("xdr:pos"));
|
||||
writer.writeAttribute(QStringLiteral("x"), QString::number(x));
|
||||
writer.writeAttribute(QStringLiteral("y"), QString::number(y));
|
||||
}
|
||||
|
||||
void Drawing::writeExt(QXmlStreamWriter &writer, int cx, int cy) const
|
||||
{
|
||||
writer.writeStartElement(QStringLiteral("xdr:ext"));
|
||||
writer.writeAttribute(QStringLiteral("cx"), QString::number(cx));
|
||||
writer.writeAttribute(QStringLiteral("cy"), QString::number(cy));
|
||||
}
|
||||
|
||||
void Drawing::writeGraphicFrame(QXmlStreamWriter &writer, int index, const QString &name) const
|
||||
{
|
||||
writer.writeStartElement(QStringLiteral("xdr:graphicFrame"));
|
||||
writer.writeAttribute(QStringLiteral("macro"), QString());
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:nvGraphicFramePr"));
|
||||
writer.writeEmptyElement(QStringLiteral("xdr:cNvPr"));
|
||||
writer.writeAttribute(QStringLiteral("id"), QString::number(index+1));
|
||||
writer.writeAttribute(QStringLiteral("name"), name.isEmpty() ? QStringLiteral("Chart%1").arg(index): name);
|
||||
if (embedded) {
|
||||
writer.writeEmptyElement(QStringLiteral("xdr:cNvGraphicFramePr"));
|
||||
} else {
|
||||
writer.writeStartElement(QStringLiteral("xdr:cNvGraphicFramePr"));
|
||||
writer.writeEmptyElement(QStringLiteral("a:graphicFrameLocks"));
|
||||
writer.writeAttribute(QStringLiteral("noGrp"), QStringLiteral("1"));
|
||||
writer.writeEndElement(); //xdr:cNvGraphicFramePr
|
||||
}
|
||||
|
||||
writer.writeEndElement();//xdr:nvGraphicFramePr
|
||||
writer.writeEndElement(); //xdr:graphicFrame
|
||||
}
|
||||
|
||||
void Drawing::writePicture(QXmlStreamWriter &writer, int index, double col_abs, double row_abs, int width, int height, const QString &description) const
|
||||
{
|
||||
writer.writeStartElement(QStringLiteral("xdr:pic"));
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:nvPicPr"));
|
||||
writer.writeEmptyElement(QStringLiteral("xdr:cNvPr"));
|
||||
writer.writeAttribute(QStringLiteral("id"), QString::number(index+1));
|
||||
writer.writeAttribute(QStringLiteral("name"), QStringLiteral("Picture%1").arg(index));
|
||||
if (!description.isEmpty())
|
||||
writer.writeAttribute(QStringLiteral("descr"), description);
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:cNvPicPr"));
|
||||
writer.writeEmptyElement(QStringLiteral("a:picLocks"));
|
||||
writer.writeAttribute(QStringLiteral("noChangeAspect"), QStringLiteral("1"));
|
||||
writer.writeEndElement(); //xdr:cNvPicPr
|
||||
|
||||
writer.writeEndElement(); //xdr:nvPicPr
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:blipFill"));
|
||||
writer.writeEmptyElement(QStringLiteral("a:blip"));
|
||||
writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
|
||||
writer.writeAttribute(QStringLiteral("r:embed"), QStringLiteral("rId%1").arg(index));
|
||||
writer.writeStartElement(QStringLiteral("a:stretch"));
|
||||
writer.writeEmptyElement(QStringLiteral("a:fillRect"));
|
||||
writer.writeEndElement(); //a:stretch
|
||||
writer.writeEndElement();//xdr:blipFill
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:spPr"));
|
||||
|
||||
writer.writeStartElement(QStringLiteral("a:xfrm"));
|
||||
writer.writeEmptyElement(QStringLiteral("a:off"));
|
||||
writer.writeAttribute(QStringLiteral("x"), QString::number((int)col_abs));
|
||||
writer.writeAttribute(QStringLiteral("y"), QString::number((int)row_abs));
|
||||
writer.writeEmptyElement(QStringLiteral("a:ext"));
|
||||
writer.writeAttribute(QStringLiteral("cx"), QString::number(width));
|
||||
writer.writeAttribute(QStringLiteral("cy"), QString::number(height));
|
||||
writer.writeEndElement(); //a:xfrm
|
||||
|
||||
writer.writeStartElement(QStringLiteral("a:prstGeom"));
|
||||
writer.writeAttribute(QStringLiteral("prst"), QStringLiteral("rect"));
|
||||
writer.writeEmptyElement(QStringLiteral("a:avLst"));
|
||||
writer.writeEndElement(); //a:prstGeom
|
||||
|
||||
writer.writeEndElement(); //xdr:spPr
|
||||
|
||||
writer.writeEndElement(); //xdr:pic
|
||||
return loadFromXmlFile(&buffer);
|
||||
}
|
||||
|
||||
} // namespace QXlsx
|
||||
|
||||
+14
-29
@@ -37,51 +37,36 @@
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "xlsxrelationships_p.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QSharedPointer>
|
||||
|
||||
class QIODevice;
|
||||
class QXmlStreamWriter;
|
||||
|
||||
namespace QXlsx {
|
||||
|
||||
struct XlsxDrawingDimensionData
|
||||
{
|
||||
int drawing_type;
|
||||
int col_from;
|
||||
int row_from;
|
||||
double col_from_offset;
|
||||
double row_from_offset;
|
||||
int col_to;
|
||||
int row_to;
|
||||
double col_to_offset;
|
||||
double row_to_offset;
|
||||
int col_absolute;
|
||||
int row_absolute;
|
||||
int width;
|
||||
int height;
|
||||
QString description;
|
||||
int shape;
|
||||
};
|
||||
class DrawingAnchor;
|
||||
class Workbook;
|
||||
class MediaFile;
|
||||
|
||||
class Drawing
|
||||
{
|
||||
public:
|
||||
Drawing();
|
||||
Drawing(Workbook *workbook);
|
||||
~Drawing();
|
||||
void saveToXmlFile(QIODevice *device) const;
|
||||
QByteArray saveToXmlData() const;
|
||||
bool loadFromXmlFile(QIODevice *device);
|
||||
bool loadFromXmlData(const QByteArray &data);
|
||||
|
||||
bool embedded;
|
||||
int orientation;
|
||||
QList <XlsxDrawingDimensionData *> dimensionList;
|
||||
Workbook *workbook;
|
||||
QList<DrawingAnchor *> anchors;
|
||||
mutable Relationships relationships;
|
||||
|
||||
private:
|
||||
void writeTwoCellAnchor(QXmlStreamWriter &writer, int index, XlsxDrawingDimensionData *data) const;
|
||||
void writeAbsoluteAnchor(QXmlStreamWriter &writer, int index) const;
|
||||
void writePos(QXmlStreamWriter &writer, int x, int y) const;
|
||||
void writeExt(QXmlStreamWriter &writer, int cx, int cy) const;
|
||||
void writeGraphicFrame(QXmlStreamWriter &writer, int index, const QString &name=QString()) const;
|
||||
void writePicture(QXmlStreamWriter &writer, int index, double col_abs, double row_abs, int width, int height, const QString &description) const;
|
||||
QString pathInPackage;
|
||||
};
|
||||
|
||||
} // namespace QXlsx
|
||||
|
||||
@@ -0,0 +1,457 @@
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
|
||||
** 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 "xlsxdrawinganchor_p.h"
|
||||
#include "xlsxdrawing_p.h"
|
||||
#include "xlsxmediafile_p.h"
|
||||
#include "xlsxworkbook.h"
|
||||
#include "xlsxutility_p.h"
|
||||
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QBuffer>
|
||||
#include <QDir>
|
||||
|
||||
namespace QXlsx {
|
||||
|
||||
/*
|
||||
The vertices that define the position of a graphical object
|
||||
within the worksheet in pixels.
|
||||
|
||||
+------------+------------+
|
||||
| A | B |
|
||||
+-----+------------+------------+
|
||||
| |(x1,y1) | |
|
||||
| 1 |(A1)._______|______ |
|
||||
| | | | |
|
||||
| | | | |
|
||||
+-----+----| OBJECT |-----+
|
||||
| | | | |
|
||||
| 2 | |______________. |
|
||||
| | | (B2)|
|
||||
| | | (x2,y2)|
|
||||
+---- +------------+------------+
|
||||
|
||||
Example of an object that covers some of the area from cell A1 to B2.
|
||||
|
||||
Based on the width and height of the object we need to calculate 8 vars:
|
||||
|
||||
col_start, row_start, col_end, row_end, x1, y1, x2, y2.
|
||||
|
||||
We also calculate the absolute x and y position of the top left vertex of
|
||||
the object. This is required for images.
|
||||
|
||||
The width and height of the cells that the object occupies can be
|
||||
variable and have to be taken into account.
|
||||
*/
|
||||
|
||||
//anchor
|
||||
|
||||
DrawingAnchor::DrawingAnchor(Drawing *drawing, ObjectType objectType)
|
||||
:m_drawing(drawing), m_objectType(objectType)
|
||||
{
|
||||
m_drawing->anchors.append(this);
|
||||
m_id = m_drawing->anchors.size();//must be unique in one drawing{x}.xml file.
|
||||
}
|
||||
|
||||
DrawingAnchor::~DrawingAnchor()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DrawingAnchor::setObjectPicture(const QImage &img)
|
||||
{
|
||||
QByteArray ba;
|
||||
QBuffer buffer(&ba);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
img.save(&buffer, "PNG");
|
||||
|
||||
m_pictureFile = QSharedPointer<MediaFile>(new MediaFile(ba, QStringLiteral("png"), QStringLiteral("image/png")));
|
||||
m_drawing->workbook->addMediaFile(m_pictureFile);
|
||||
}
|
||||
|
||||
QPoint DrawingAnchor::loadXmlPos(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("pos"));
|
||||
|
||||
QPoint pos;
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
pos.setX(attrs.value(QLatin1String("x")).toString().toInt());
|
||||
pos.setY(attrs.value(QLatin1String("y")).toString().toInt());
|
||||
return pos;
|
||||
}
|
||||
|
||||
QSize DrawingAnchor::loadXmlExt(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("ext"));
|
||||
|
||||
QSize size;
|
||||
QXmlStreamAttributes attrs = reader.attributes();
|
||||
size.setWidth(attrs.value(QLatin1String("cx")).toString().toInt());
|
||||
size.setHeight(attrs.value(QLatin1String("cy")).toString().toInt());
|
||||
return size;
|
||||
}
|
||||
|
||||
XlsxMarker DrawingAnchor::loadXmlMarker(QXmlStreamReader &reader, const QString &node)
|
||||
{
|
||||
Q_ASSERT(reader.name() == node);
|
||||
|
||||
int col, colOffset, row, rowOffset;
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("col")) {
|
||||
col = reader.readElementText().toInt();
|
||||
} else if (reader.name() == QLatin1String("colOff")) {
|
||||
colOffset = reader.readElementText().toInt();
|
||||
} else if (reader.name() == QLatin1String("row")) {
|
||||
row = reader.readElementText().toInt();
|
||||
} else if (reader.name() == QLatin1String("rowOff")) {
|
||||
rowOffset = reader.readElementText().toInt();
|
||||
}
|
||||
} else if (reader.tokenType() == QXmlStreamReader::EndElement
|
||||
&& reader.name() == node) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return XlsxMarker(row, col, rowOffset, colOffset);
|
||||
}
|
||||
|
||||
void DrawingAnchor::loadXmlObject(QXmlStreamReader &reader)
|
||||
{
|
||||
if (reader.name() == QLatin1String("sp")) {
|
||||
//Shape
|
||||
m_objectType = Shape;
|
||||
loadXmlObjectShape(reader);
|
||||
} else if (reader.name() == QLatin1String("grpSp")) {
|
||||
//Group Shape
|
||||
m_objectType = GroupShape;
|
||||
loadXmlObjectGroupShape(reader);
|
||||
} else if (reader.name() == QLatin1String("graphicFrame")) {
|
||||
//Graphic Frame
|
||||
m_objectType = GraphicFrame;
|
||||
loadXmlObjectGraphicFrame(reader);
|
||||
} else if (reader.name() == QLatin1String("cxnSp")) {
|
||||
//Connection Shape
|
||||
m_objectType = ConnectionShape;
|
||||
loadXmlObjectConnectionShape(reader);
|
||||
} else if (reader.name() == QLatin1String("pic")) {
|
||||
//Picture
|
||||
m_objectType = Picture;
|
||||
loadXmlObjectPicture(reader);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawingAnchor::loadXmlObjectConnectionShape(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_UNUSED(reader)
|
||||
}
|
||||
|
||||
void DrawingAnchor::loadXmlObjectGraphicFrame(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_UNUSED(reader)
|
||||
}
|
||||
|
||||
void DrawingAnchor::loadXmlObjectGroupShape(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_UNUSED(reader)
|
||||
}
|
||||
|
||||
void DrawingAnchor::loadXmlObjectPicture(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("pic"));
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("blip")) {
|
||||
QString rId = reader.attributes().value(QLatin1String("r:embed")).toString();
|
||||
QString name = m_drawing->relationships.getRelationshipById(rId).target;
|
||||
QString path = QDir::cleanPath(splitPath(m_drawing->pathInPackage)[0] + QLatin1String("/") + name);
|
||||
|
||||
bool exist = false;
|
||||
QList<QSharedPointer<MediaFile> > mfs = m_drawing->workbook->mediaFiles();
|
||||
for (int i=0; i<mfs.size(); ++i) {
|
||||
if (mfs[i]->fileName() == path) {
|
||||
//already exist
|
||||
exist = true;
|
||||
m_pictureFile = mfs[i];
|
||||
}
|
||||
}
|
||||
if (!exist) {
|
||||
m_pictureFile = QSharedPointer<MediaFile> (new MediaFile(path));
|
||||
m_drawing->workbook->addMediaFile(m_pictureFile, true);
|
||||
}
|
||||
}
|
||||
} else if (reader.tokenType() == QXmlStreamReader::EndElement
|
||||
&& reader.name() == QLatin1String("pic")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DrawingAnchor::loadXmlObjectShape(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_UNUSED(reader)
|
||||
}
|
||||
|
||||
void DrawingAnchor::saveXmlPos(QXmlStreamWriter &writer, const QPoint &pos) const
|
||||
{
|
||||
writer.writeEmptyElement(QStringLiteral("xdr:pos"));
|
||||
writer.writeAttribute(QStringLiteral("x"), QString::number(pos.x()));
|
||||
writer.writeAttribute(QStringLiteral("y"), QString::number(pos.y()));
|
||||
}
|
||||
|
||||
void DrawingAnchor::saveXmlExt(QXmlStreamWriter &writer, const QSize &ext) const
|
||||
{
|
||||
writer.writeStartElement(QStringLiteral("xdr:ext"));
|
||||
writer.writeAttribute(QStringLiteral("cx"), QString::number(ext.width()));
|
||||
writer.writeAttribute(QStringLiteral("cy"), QString::number(ext.height()));
|
||||
writer.writeEndElement(); //xdr:ext
|
||||
}
|
||||
|
||||
void DrawingAnchor::saveXmlMarker(QXmlStreamWriter &writer, const XlsxMarker &marker, const QString &node) const
|
||||
{
|
||||
writer.writeStartElement(node); //xdr:from or xdr:to
|
||||
writer.writeTextElement(QStringLiteral("xdr:col"), QString::number(marker.col()));
|
||||
writer.writeTextElement(QStringLiteral("xdr:colOff"), QString::number(marker.colOff()));
|
||||
writer.writeTextElement(QStringLiteral("xdr:row"), QString::number(marker.row()));
|
||||
writer.writeTextElement(QStringLiteral("xdr:rowOff"), QString::number(marker.rowOff()));
|
||||
writer.writeEndElement();
|
||||
}
|
||||
|
||||
void DrawingAnchor::saveXmlObject(QXmlStreamWriter &writer) const
|
||||
{
|
||||
if (m_objectType == Picture)
|
||||
saveXmlObjectPicture(writer);
|
||||
else if (m_objectType == ConnectionShape)
|
||||
saveXmlObjectConnectionShape(writer);
|
||||
else if (m_objectType == GraphicFrame)
|
||||
saveXmlObjectGraphicFrame(writer);
|
||||
else if (m_objectType == GroupShape)
|
||||
saveXmlObjectGroupShape(writer);
|
||||
else if (m_objectType == Shape)
|
||||
saveXmlObjectShape(writer);
|
||||
}
|
||||
|
||||
void DrawingAnchor::saveXmlObjectConnectionShape(QXmlStreamWriter &writer) const
|
||||
{
|
||||
Q_UNUSED(writer)
|
||||
}
|
||||
|
||||
void DrawingAnchor::saveXmlObjectGraphicFrame(QXmlStreamWriter &writer) const
|
||||
{
|
||||
Q_UNUSED(writer)
|
||||
}
|
||||
|
||||
void DrawingAnchor::saveXmlObjectGroupShape(QXmlStreamWriter &writer) const
|
||||
{
|
||||
Q_UNUSED(writer)
|
||||
}
|
||||
|
||||
void DrawingAnchor::saveXmlObjectPicture(QXmlStreamWriter &writer) const
|
||||
{
|
||||
Q_ASSERT(m_objectType == Picture && !m_pictureFile.isNull());
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:pic"));
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:nvPicPr"));
|
||||
writer.writeEmptyElement(QStringLiteral("xdr:cNvPr"));
|
||||
writer.writeAttribute(QStringLiteral("id"), QString::number(m_id));
|
||||
writer.writeAttribute(QStringLiteral("name"), QStringLiteral("Picture %1").arg(m_id));
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:cNvPicPr"));
|
||||
writer.writeEmptyElement(QStringLiteral("a:picLocks"));
|
||||
writer.writeAttribute(QStringLiteral("noChangeAspect"), QStringLiteral("1"));
|
||||
writer.writeEndElement(); //xdr:cNvPicPr
|
||||
|
||||
writer.writeEndElement(); //xdr:nvPicPr
|
||||
|
||||
m_drawing->relationships.addDocumentRelationship(QStringLiteral("/image"), QStringLiteral("../media/image%1.%2")
|
||||
.arg(m_pictureFile->index()+1)
|
||||
.arg(m_pictureFile->suffix()));
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:blipFill"));
|
||||
writer.writeEmptyElement(QStringLiteral("a:blip"));
|
||||
writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"));
|
||||
writer.writeAttribute(QStringLiteral("r:embed"), QStringLiteral("rId%1").arg(m_drawing->relationships.count()));
|
||||
writer.writeStartElement(QStringLiteral("a:stretch"));
|
||||
writer.writeEmptyElement(QStringLiteral("a:fillRect"));
|
||||
writer.writeEndElement(); //a:stretch
|
||||
writer.writeEndElement();//xdr:blipFill
|
||||
|
||||
writer.writeStartElement(QStringLiteral("xdr:spPr"));
|
||||
|
||||
writer.writeStartElement(QStringLiteral("a:prstGeom"));
|
||||
writer.writeAttribute(QStringLiteral("prst"), QStringLiteral("rect"));
|
||||
writer.writeEmptyElement(QStringLiteral("a:avLst"));
|
||||
writer.writeEndElement(); //a:prstGeom
|
||||
|
||||
writer.writeEndElement(); //xdr:spPr
|
||||
|
||||
writer.writeEndElement(); //xdr:pic
|
||||
}
|
||||
|
||||
void DrawingAnchor::saveXmlObjectShape(QXmlStreamWriter &writer) const
|
||||
{
|
||||
Q_UNUSED(writer)
|
||||
}
|
||||
|
||||
//absolute anchor
|
||||
|
||||
DrawingAbsoluteAnchor::DrawingAbsoluteAnchor(Drawing *drawing, ObjectType objectType)
|
||||
:DrawingAnchor(drawing, objectType)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool DrawingAbsoluteAnchor::loadFromXml(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("absoluteAnchor"));
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("pos")) {
|
||||
pos = loadXmlPos(reader);
|
||||
} else if (reader.name() == QLatin1String("ext")) {
|
||||
ext = loadXmlExt(reader);
|
||||
} else {
|
||||
loadXmlObject(reader);
|
||||
}
|
||||
} else if (reader.tokenType() == QXmlStreamReader::EndElement
|
||||
&& reader.name() == QLatin1String("absoluteAnchor")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DrawingAbsoluteAnchor::saveToXml(QXmlStreamWriter &writer) const
|
||||
{
|
||||
writer.writeStartElement(QStringLiteral("xdr:absoluteAnchor"));
|
||||
saveXmlPos(writer, pos);
|
||||
saveXmlExt(writer, ext);
|
||||
|
||||
saveXmlObject(writer);
|
||||
|
||||
writer.writeEmptyElement(QStringLiteral("xdr:clientData"));
|
||||
writer.writeEndElement(); //xdr:absoluteAnchor
|
||||
}
|
||||
|
||||
//one cell anchor
|
||||
|
||||
DrawingOneCellAnchor::DrawingOneCellAnchor(Drawing *drawing, ObjectType objectType)
|
||||
:DrawingAnchor(drawing, objectType)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool DrawingOneCellAnchor::loadFromXml(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("oneCellAnchor"));
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("from")) {
|
||||
from = loadXmlMarker(reader, QLatin1String("from"));
|
||||
} else if (reader.name() == QLatin1String("ext")) {
|
||||
ext = loadXmlExt(reader);
|
||||
} else {
|
||||
loadXmlObject(reader);
|
||||
}
|
||||
} else if (reader.tokenType() == QXmlStreamReader::EndElement
|
||||
&& reader.name() == QLatin1String("oneCellAnchor")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DrawingOneCellAnchor::saveToXml(QXmlStreamWriter &writer) const
|
||||
{
|
||||
writer.writeStartElement(QStringLiteral("xdr:oneCellAnchor"));
|
||||
|
||||
saveXmlMarker(writer, from, QStringLiteral("xdr:from"));
|
||||
saveXmlExt(writer, ext);
|
||||
|
||||
saveXmlObject(writer);
|
||||
|
||||
writer.writeEmptyElement(QStringLiteral("xdr:clientData"));
|
||||
writer.writeEndElement(); //xdr:oneCellAnchor
|
||||
}
|
||||
|
||||
/*
|
||||
Two cell anchor
|
||||
|
||||
This class specifies a two cell anchor placeholder for a group
|
||||
, a shape, or a drawing element. It moves with
|
||||
cells and its extents are in EMU units.
|
||||
*/
|
||||
DrawingTwoCellAnchor::DrawingTwoCellAnchor(Drawing *drawing, ObjectType objectType)
|
||||
:DrawingAnchor(drawing, objectType)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool DrawingTwoCellAnchor::loadFromXml(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("twoCellAnchor"));
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNextStartElement();
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
if (reader.name() == QLatin1String("from")) {
|
||||
from = loadXmlMarker(reader, QLatin1String("from"));
|
||||
} else if (reader.name() == QLatin1String("to")) {
|
||||
to = loadXmlMarker(reader, QLatin1String("to"));
|
||||
} else {
|
||||
loadXmlObject(reader);
|
||||
}
|
||||
} else if (reader.tokenType() == QXmlStreamReader::EndElement
|
||||
&& reader.name() == QLatin1String("twoCellAnchor")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DrawingTwoCellAnchor::saveToXml(QXmlStreamWriter &writer) const
|
||||
{
|
||||
writer.writeStartElement(QStringLiteral("xdr:twoCellAnchor"));
|
||||
writer.writeAttribute(QStringLiteral("editAs"), QStringLiteral("oneCell"));
|
||||
|
||||
saveXmlMarker(writer, from, QStringLiteral("xdr:from"));
|
||||
saveXmlMarker(writer, to, QStringLiteral("xdr:to"));
|
||||
|
||||
saveXmlObject(writer);
|
||||
|
||||
writer.writeEmptyElement(QStringLiteral("xdr:clientData"));
|
||||
writer.writeEndElement(); //xdr:twoCellAnchor
|
||||
}
|
||||
|
||||
} // namespace QXlsx
|
||||
@@ -0,0 +1,148 @@
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
|
||||
** 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_XLSXDRAWINGANCHOR_P_H
|
||||
#define QXLSX_XLSXDRAWINGANCHOR_P_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QPoint>
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
#include <QSharedPointer>
|
||||
|
||||
class QXmlStreamReader;
|
||||
class QXmlStreamWriter;
|
||||
|
||||
namespace QXlsx {
|
||||
|
||||
class Drawing;
|
||||
class MediaFile;
|
||||
|
||||
//Helper class
|
||||
struct XlsxMarker
|
||||
{
|
||||
XlsxMarker(){}
|
||||
XlsxMarker(int row, int column, int rowOffset, int colOffset)
|
||||
:cell(QPoint(row, column)), offset(rowOffset, colOffset)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int row() const {return cell.x();}
|
||||
int col() const {return cell.y();}
|
||||
int rowOff() const {return offset.width();}
|
||||
int colOff() const {return offset.height();}
|
||||
|
||||
QPoint cell;
|
||||
QSize offset;
|
||||
};
|
||||
|
||||
class DrawingAnchor
|
||||
{
|
||||
public:
|
||||
enum ObjectType {
|
||||
GraphicFrame,
|
||||
Shape,
|
||||
GroupShape,
|
||||
ConnectionShape,
|
||||
Picture,
|
||||
Unknown
|
||||
};
|
||||
|
||||
DrawingAnchor(Drawing *drawing, ObjectType objectType);
|
||||
virtual ~DrawingAnchor();
|
||||
void setObjectPicture(const QImage &img);
|
||||
|
||||
virtual bool loadFromXml(QXmlStreamReader &reader) = 0;
|
||||
virtual void saveToXml(QXmlStreamWriter &writer) const = 0;
|
||||
|
||||
protected:
|
||||
QPoint loadXmlPos(QXmlStreamReader &reader);
|
||||
QSize loadXmlExt(QXmlStreamReader &reader);
|
||||
XlsxMarker loadXmlMarker(QXmlStreamReader &reader, const QString &node);
|
||||
void loadXmlObject(QXmlStreamReader &reader);
|
||||
void loadXmlObjectShape(QXmlStreamReader &reader);
|
||||
void loadXmlObjectGroupShape(QXmlStreamReader &reader);
|
||||
void loadXmlObjectGraphicFrame(QXmlStreamReader &reader);
|
||||
void loadXmlObjectConnectionShape(QXmlStreamReader &reader);
|
||||
void loadXmlObjectPicture(QXmlStreamReader &reader);
|
||||
|
||||
void saveXmlPos(QXmlStreamWriter &writer, const QPoint &pos) const;
|
||||
void saveXmlExt(QXmlStreamWriter &writer, const QSize &ext) const;
|
||||
void saveXmlMarker(QXmlStreamWriter &writer, const XlsxMarker &marker, const QString &node) const;
|
||||
void saveXmlObject(QXmlStreamWriter &writer) const;
|
||||
void saveXmlObjectShape(QXmlStreamWriter &writer) const;
|
||||
void saveXmlObjectGroupShape(QXmlStreamWriter &writer) const;
|
||||
void saveXmlObjectGraphicFrame(QXmlStreamWriter &writer) const;
|
||||
void saveXmlObjectConnectionShape(QXmlStreamWriter &writer) const;
|
||||
void saveXmlObjectPicture(QXmlStreamWriter &writer) const;
|
||||
|
||||
Drawing *m_drawing;
|
||||
ObjectType m_objectType;
|
||||
QSharedPointer<MediaFile> m_pictureFile;
|
||||
|
||||
int m_id;
|
||||
};
|
||||
|
||||
class DrawingAbsoluteAnchor : public DrawingAnchor
|
||||
{
|
||||
public:
|
||||
DrawingAbsoluteAnchor(Drawing *drawing, ObjectType objectType=Unknown);
|
||||
|
||||
QPoint pos;
|
||||
QSize ext;
|
||||
|
||||
bool loadFromXml(QXmlStreamReader &reader);
|
||||
void saveToXml(QXmlStreamWriter &writer) const;
|
||||
};
|
||||
|
||||
class DrawingOneCellAnchor : public DrawingAnchor
|
||||
{
|
||||
public:
|
||||
DrawingOneCellAnchor(Drawing *drawing, ObjectType objectType=Unknown);
|
||||
|
||||
XlsxMarker from;
|
||||
QSize ext;
|
||||
|
||||
bool loadFromXml(QXmlStreamReader &reader);
|
||||
void saveToXml(QXmlStreamWriter &writer) const;
|
||||
};
|
||||
|
||||
class DrawingTwoCellAnchor : public DrawingAnchor
|
||||
{
|
||||
public:
|
||||
DrawingTwoCellAnchor(Drawing *drawing, ObjectType objectType=Unknown);
|
||||
|
||||
XlsxMarker from;
|
||||
XlsxMarker to;
|
||||
|
||||
bool loadFromXml(QXmlStreamReader &reader);
|
||||
void saveToXml(QXmlStreamWriter &writer) const;
|
||||
};
|
||||
|
||||
} // namespace QXlsx
|
||||
|
||||
#endif // QXLSX_XLSXDRAWINGANCHOR_P_H
|
||||
@@ -0,0 +1,99 @@
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
|
||||
** 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 "xlsxmediafile_p.h"
|
||||
#include <QCryptographicHash>
|
||||
|
||||
namespace QXlsx {
|
||||
|
||||
MediaFile::MediaFile(const QByteArray &bytes, const QString &suffix, const QString &mimeType)
|
||||
: m_contents(bytes), m_suffix(suffix), m_mimeType(mimeType)
|
||||
, m_index(0), m_indexValid(false)
|
||||
{
|
||||
m_hashKey = QCryptographicHash::hash(m_contents, QCryptographicHash::Md5);
|
||||
}
|
||||
|
||||
MediaFile::MediaFile(const QString &fileName)
|
||||
:m_fileName(fileName), m_index(0), m_indexValid(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MediaFile::set(const QByteArray &bytes, const QString &suffix, const QString &mimeType)
|
||||
{
|
||||
m_contents = bytes;
|
||||
m_suffix = suffix;
|
||||
m_mimeType = mimeType;
|
||||
m_hashKey = QCryptographicHash::hash(m_contents, QCryptographicHash::Md5);
|
||||
m_indexValid = false;
|
||||
}
|
||||
|
||||
void MediaFile::setFileName(const QString &name)
|
||||
{
|
||||
m_fileName = name;
|
||||
}
|
||||
|
||||
QString MediaFile::fileName() const
|
||||
{
|
||||
return m_fileName;
|
||||
}
|
||||
|
||||
QString MediaFile::suffix() const
|
||||
{
|
||||
return m_suffix;
|
||||
}
|
||||
|
||||
QString MediaFile::mimeType() const
|
||||
{
|
||||
return m_mimeType;
|
||||
}
|
||||
|
||||
QByteArray MediaFile::contents() const
|
||||
{
|
||||
return m_contents;
|
||||
}
|
||||
|
||||
int MediaFile::index() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
bool MediaFile::isIndexValid() const
|
||||
{
|
||||
return m_indexValid;
|
||||
}
|
||||
|
||||
void MediaFile::setIndex(int idx)
|
||||
{
|
||||
m_index = idx;
|
||||
m_indexValid = true;
|
||||
}
|
||||
|
||||
QByteArray MediaFile::hashKey() const
|
||||
{
|
||||
return m_hashKey;
|
||||
}
|
||||
|
||||
} // namespace QXlsx
|
||||
@@ -0,0 +1,68 @@
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
|
||||
** 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_XLSXMEDIAFILE_H
|
||||
#define QXLSX_XLSXMEDIAFILE_H
|
||||
|
||||
#include "xlsxglobal.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
|
||||
namespace QXlsx {
|
||||
|
||||
class MediaFile
|
||||
{
|
||||
public:
|
||||
MediaFile(const QString &fileName);
|
||||
MediaFile(const QByteArray &bytes, const QString &suffix, const QString &mimeType=QString());
|
||||
|
||||
void set(const QByteArray &bytes, const QString &suffix, const QString &mimeType=QString());
|
||||
QString suffix() const;
|
||||
QString mimeType() const;
|
||||
QByteArray contents() const;
|
||||
|
||||
bool isIndexValid() const;
|
||||
int index() const;
|
||||
void setIndex(int idx);
|
||||
QByteArray hashKey() const;
|
||||
|
||||
void setFileName(const QString &name);
|
||||
QString fileName() const;
|
||||
|
||||
private:
|
||||
QString m_fileName; //...
|
||||
QByteArray m_contents;
|
||||
QString m_suffix;
|
||||
QString m_mimeType;
|
||||
|
||||
bool m_indexValid;
|
||||
int m_index;
|
||||
QByteArray m_hashKey;
|
||||
};
|
||||
|
||||
} // namespace QXlsx
|
||||
|
||||
#endif // QXLSX_XLSXMEDIAFILE_H
|
||||
+39
-29
@@ -30,6 +30,7 @@
|
||||
#include "xlsxformat.h"
|
||||
#include "xlsxworksheet_p.h"
|
||||
#include "xlsxformat_p.h"
|
||||
#include "xlsxmediafile_p.h"
|
||||
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QXmlStreamReader>
|
||||
@@ -370,41 +371,22 @@ Theme *Workbook::theme()
|
||||
return d->theme.data();
|
||||
}
|
||||
|
||||
QList<QImage> Workbook::images()
|
||||
{
|
||||
Q_D(Workbook);
|
||||
return d->images;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*
|
||||
* Unlike media files, drawing file is a property of the sheet.
|
||||
*/
|
||||
QList<Drawing *> Workbook::drawings()
|
||||
{
|
||||
Q_D(Workbook);
|
||||
return d->drawings;
|
||||
}
|
||||
|
||||
void Workbook::prepareDrawings()
|
||||
{
|
||||
Q_D(Workbook);
|
||||
int image_ref_id = 0;
|
||||
d->images.clear();
|
||||
d->drawings.clear();
|
||||
|
||||
QList<Drawing *> ds;
|
||||
for (int i=0; i<d->worksheets.size(); ++i) {
|
||||
QSharedPointer<Worksheet> sheet = d->worksheets[i];
|
||||
if (sheet->images().isEmpty()) //No drawing (such as Image, ...)
|
||||
continue;
|
||||
|
||||
sheet->clearExtraDrawingInfo();
|
||||
|
||||
//At present, only picture type supported
|
||||
for (int idx = 0; idx < sheet->images().size(); ++idx) {
|
||||
image_ref_id += 1;
|
||||
sheet->prepareImage(idx, image_ref_id);
|
||||
d->images.append(sheet->images()[idx]->image);
|
||||
}
|
||||
|
||||
d->drawings.append(sheet->drawing());
|
||||
if (sheet->drawing())
|
||||
ds.append(sheet->drawing());
|
||||
}
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
void Workbook::saveToXmlFile(QIODevice *device) const
|
||||
@@ -585,4 +567,32 @@ Relationships &Workbook::relationships()
|
||||
return d->relationships;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
QList<QSharedPointer<MediaFile> > Workbook::mediaFiles() const
|
||||
{
|
||||
Q_D(const Workbook);
|
||||
|
||||
return d->mediaFiles;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
void Workbook::addMediaFile(QSharedPointer<MediaFile> media, bool force)
|
||||
{
|
||||
Q_D(Workbook);
|
||||
if (!force) {
|
||||
for (int i=0; i<d->mediaFiles.size(); ++i) {
|
||||
if (d->mediaFiles[i]->hashKey() == media->hashKey()) {
|
||||
media->setIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
media->setIndex(d->mediaFiles.size());
|
||||
d->mediaFiles.append(media);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE_XLSX
|
||||
|
||||
@@ -42,6 +42,7 @@ class Document;
|
||||
class Theme;
|
||||
class Relationships;
|
||||
class DocumentPrivate;
|
||||
class MediaFile;
|
||||
|
||||
class WorkbookPrivate;
|
||||
class Q_XLSX_EXPORT Workbook
|
||||
@@ -75,6 +76,10 @@ public:
|
||||
QString defaultDateFormat() const;
|
||||
void setDefaultDateFormat(const QString &format);
|
||||
|
||||
//internal used member
|
||||
void addMediaFile(QSharedPointer<MediaFile> media, bool force=false);
|
||||
QList<QSharedPointer<MediaFile> > mediaFiles() const;
|
||||
|
||||
private:
|
||||
friend class Worksheet;
|
||||
friend class WorksheetPrivate;
|
||||
@@ -94,9 +99,9 @@ private:
|
||||
Theme *theme();
|
||||
QList<QImage> images();
|
||||
QList<Drawing *> drawings();
|
||||
void prepareDrawings();
|
||||
QStringList worksheetNames() const;
|
||||
Worksheet *addWorksheet(const QString &name, int sheetId);
|
||||
|
||||
WorkbookPrivate * const d_ptr;
|
||||
};
|
||||
|
||||
|
||||
@@ -87,8 +87,7 @@ public:
|
||||
QStringList worksheetNames;
|
||||
QSharedPointer<Styles> styles;
|
||||
QSharedPointer<Theme> theme;
|
||||
QList<QImage> images;
|
||||
QList<Drawing *> drawings;
|
||||
QList<QSharedPointer<MediaFile> > mediaFiles;
|
||||
QList<XlsxDefineNameData> definedNamesList;
|
||||
|
||||
QList<XlsxSheetItemInfo> sheetItemInfoList;//Data from xml file
|
||||
|
||||
+47
-141
@@ -36,6 +36,7 @@
|
||||
#include "xlsxcell_p.h"
|
||||
#include "xlsxcellrange.h"
|
||||
#include "xlsxconditionalformatting_p.h"
|
||||
#include "xlsxdrawinganchor_p.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include <QDateTime>
|
||||
@@ -455,12 +456,6 @@ void Worksheet::setWhiteSpaceVisible(bool visible)
|
||||
d->showWhiteSpace = visible;
|
||||
}
|
||||
|
||||
QList<QPair<QString, QString> > Worksheet::drawingLinks() const
|
||||
{
|
||||
Q_D(const Worksheet);
|
||||
return d->drawingLinks;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Write \a value to cell (\a row, \a column) with the \a format.
|
||||
* Both \a row and \a column are all 1-indexed value.
|
||||
@@ -1024,12 +1019,33 @@ bool Worksheet::addConditionalFormatting(const ConditionalFormatting &cf)
|
||||
return true;
|
||||
}
|
||||
|
||||
int Worksheet::insertImage(int row, int column, const QImage &image, const QPointF &offset, double xScale, double yScale)
|
||||
bool Worksheet::insertImage(int row, int column, const QImage &image)
|
||||
{
|
||||
Q_D(Worksheet);
|
||||
|
||||
d->imageList.append(new XlsxImageData(row, column, image, offset, xScale, yScale));
|
||||
return 0;
|
||||
if (image.isNull())
|
||||
return false;
|
||||
|
||||
if (!d->drawing)
|
||||
d->drawing = new Drawing(d->workbook);
|
||||
|
||||
DrawingOneCellAnchor *anchor = new DrawingOneCellAnchor(d->drawing, 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 = QSize(image.width() * 9525, image.height() * 9525);
|
||||
|
||||
anchor->setObjectPicture(image);
|
||||
return true;
|
||||
}
|
||||
|
||||
int Worksheet::insertImage(int row, int column, const QImage &image, const QPointF & /*offset*/, double /*xScale*/, double /*yScale*/)
|
||||
{
|
||||
return insertImage(row, column, image);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1678,61 +1694,38 @@ CellRange Worksheet::dimension() const
|
||||
return d->dimension;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
*/
|
||||
Drawing *Worksheet::drawing() const
|
||||
{
|
||||
Q_D(const Worksheet);
|
||||
return d->drawing;
|
||||
}
|
||||
|
||||
QList<XlsxImageData *> Worksheet::images() const
|
||||
/*!
|
||||
* \internal
|
||||
*
|
||||
* When loading the .xlsx package, the drawing{x}.xml file path
|
||||
* is extracted when we parse the sheet{x}.xml file.
|
||||
*/
|
||||
QString Worksheet::drawingPath() const
|
||||
{
|
||||
Q_D(const Worksheet);
|
||||
return d->imageList;
|
||||
return d->drawingPath_in_zip;
|
||||
}
|
||||
|
||||
void Worksheet::clearExtraDrawingInfo()
|
||||
/*!
|
||||
* \internal
|
||||
*
|
||||
* Note, the object will be managed by this sheet.
|
||||
*/
|
||||
void Worksheet::setDrawing(Drawing *draw)
|
||||
{
|
||||
Q_D(Worksheet);
|
||||
if (d->drawing) {
|
||||
delete d->drawing;
|
||||
d->drawing = 0;
|
||||
d->drawingLinks.clear();
|
||||
}
|
||||
}
|
||||
Q_ASSERT(!d->drawing);
|
||||
|
||||
void Worksheet::prepareImage(int index, int image_id)
|
||||
{
|
||||
Q_D(Worksheet);
|
||||
if (!d->drawing) {
|
||||
d->drawing = new Drawing;
|
||||
d->drawing->embedded = true;
|
||||
}
|
||||
|
||||
XlsxImageData *imageData = d->imageList[index];
|
||||
|
||||
XlsxDrawingDimensionData *data = new XlsxDrawingDimensionData;
|
||||
data->drawing_type = 2;
|
||||
|
||||
double width = imageData->image.width() * imageData->xScale;
|
||||
double height = imageData->image.height() * imageData->yScale;
|
||||
|
||||
XlsxObjectPositionData posData = d->pixelsToEMUs(d->objectPixelsPosition(imageData->col, imageData->row, imageData->offset.x(), imageData->offset.y(), width, height));
|
||||
data->col_from = posData.col_start;
|
||||
data->col_from_offset = posData.x1;
|
||||
data->row_from = posData.row_start;
|
||||
data->row_from_offset = posData.y1;
|
||||
data->col_to = posData.col_end;
|
||||
data->col_to_offset = posData.x2;
|
||||
data->row_to = posData.row_end;
|
||||
data->row_to_offset = posData.y2;
|
||||
data->width = posData.width;
|
||||
data->height = posData.height;
|
||||
data->col_absolute = posData.x_abs;
|
||||
data->row_absolute = posData.y_abs;
|
||||
|
||||
d->drawing->dimensionList.append(data);
|
||||
|
||||
d->drawingLinks.append(QPair<QString, QString>(QStringLiteral("/image"), QStringLiteral("../media/image%1.png").arg(image_id)));
|
||||
d->drawing = draw;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1774,96 +1767,6 @@ int WorksheetPrivate::colPixelsSize(int col) const
|
||||
return pixels;
|
||||
}
|
||||
|
||||
/*
|
||||
col_start Col containing upper left corner of object.
|
||||
x1 Distance to left side of object.
|
||||
row_start Row containing top left corner of object.
|
||||
y1 Distance to top of object.
|
||||
col_end Col containing lower right corner of object.
|
||||
x2 Distance to right side of object.
|
||||
row_end Row containing bottom right corner of object.
|
||||
y2 Distance to bottom of object.
|
||||
width Width of object frame.
|
||||
height Height of object frame.
|
||||
x_abs Absolute distance to left side of object.
|
||||
y_abs Absolute distance to top side of object.
|
||||
*/
|
||||
XlsxObjectPositionData WorksheetPrivate::objectPixelsPosition(int col_start, int row_start, double x1, double y1, double width, double height) const
|
||||
{
|
||||
double x_abs = 0;
|
||||
double y_abs = 0;
|
||||
for (int col_id = 1; col_id < col_start; ++col_id)
|
||||
x_abs += colPixelsSize(col_id);
|
||||
x_abs += x1;
|
||||
for (int row_id = 1; row_id < row_start; ++row_id)
|
||||
y_abs += rowPixelsSize(row_id);
|
||||
y_abs += y1;
|
||||
|
||||
// Adjust start column for offsets that are greater than the col width.
|
||||
while (x1 > colPixelsSize(col_start)) {
|
||||
x1 -= colPixelsSize(col_start);
|
||||
col_start += 1;
|
||||
}
|
||||
while (y1 > rowPixelsSize(row_start)) {
|
||||
y1 -= rowPixelsSize(row_start);
|
||||
row_start += 1;
|
||||
}
|
||||
|
||||
int col_end = col_start;
|
||||
int row_end = row_start;
|
||||
double x2 = width + x1;
|
||||
double y2 = height + y1;
|
||||
|
||||
while (x2 > colPixelsSize(col_end)) {
|
||||
x2 -= colPixelsSize(col_end);
|
||||
col_end += 1;
|
||||
}
|
||||
|
||||
while (y2 > rowPixelsSize(row_end)) {
|
||||
y2 -= rowPixelsSize(row_end);
|
||||
row_end += 1;
|
||||
}
|
||||
|
||||
XlsxObjectPositionData data;
|
||||
data.col_start = col_start;
|
||||
data.x1 = x1;
|
||||
data.row_start = row_start;
|
||||
data.y1 = y1;
|
||||
data.col_end = col_end;
|
||||
data.x2 = x2;
|
||||
data.row_end = row_end;
|
||||
data.y2 = y2;
|
||||
data.x_abs = x_abs;
|
||||
data.y_abs = y_abs;
|
||||
data.width = width;
|
||||
data.height = height;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate the vertices that define the position of a graphical
|
||||
object within the worksheet in EMUs.
|
||||
|
||||
The vertices are expressed as English Metric Units (EMUs). There are
|
||||
12,700 EMUs per point. Therefore, 12,700 * 3 /4 = 9,525 EMUs per
|
||||
pixel
|
||||
*/
|
||||
XlsxObjectPositionData WorksheetPrivate::pixelsToEMUs(const XlsxObjectPositionData &data) const
|
||||
{
|
||||
XlsxObjectPositionData result = data;
|
||||
result.x1 = static_cast<int>(data.x1 * 9525 + 0.5);
|
||||
result.y1 = static_cast<int>(data.y1 * 9525 + 0.5);
|
||||
result.x2 = static_cast<int>(data.x2 * 9525 + 0.5);
|
||||
result.y2 = static_cast<int>(data.y2 * 9525 + 0.5);
|
||||
result.x_abs = static_cast<int>(data.x_abs * 9525 + 0.5);
|
||||
result.y_abs = static_cast<int>(data.y_abs * 9525 + 0.5);
|
||||
result.width = static_cast<int>(data.width * 9525 + 0.5);
|
||||
result.height = static_cast<int>(data.height * 9525 + 0.5);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray Worksheet::saveToXmlData() const
|
||||
{
|
||||
QByteArray data;
|
||||
@@ -2220,6 +2123,9 @@ bool Worksheet::loadFromXmlFile(QIODevice *device)
|
||||
d->conditionalFormattingList.append(cf);
|
||||
} else if (reader.name() == QLatin1String("hyperlinks")) {
|
||||
d->loadXmlHyperlinks(reader);
|
||||
} else if (reader.name() == QLatin1String("drawing")) {
|
||||
QString rId = reader.attributes().value(QStringLiteral("r:id")).toString();
|
||||
d->drawingPath_in_zip = d->relationships.getRelationshipById(rId).target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,8 @@ public:
|
||||
Cell *cellAt(const QString &row_column) const;
|
||||
Cell *cellAt(int row, int column) const;
|
||||
|
||||
int insertImage(int row, int column, const QImage &image, const QPointF &offset=QPointF(), double xScale=1, double yScale=1);
|
||||
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);
|
||||
|
||||
int mergeCells(const QString &range, const Format &format=Format());
|
||||
int mergeCells(const CellRange &range, const Format &format=Format());
|
||||
@@ -149,11 +150,10 @@ private:
|
||||
bool isHidden() const;
|
||||
void setHidden(bool hidden);
|
||||
int sheetId() const;
|
||||
QList<QPair<QString, QString> > drawingLinks() const;
|
||||
|
||||
Drawing *drawing() const;
|
||||
QList<XlsxImageData *> images() const;
|
||||
void prepareImage(int index, int image_id);
|
||||
void clearExtraDrawingInfo();
|
||||
void setDrawing(Drawing *d);
|
||||
QString drawingPath() const;
|
||||
|
||||
WorksheetPrivate * const d_ptr;
|
||||
};
|
||||
|
||||
@@ -79,67 +79,6 @@ struct XlsxHyperlinkData
|
||||
QString tooltip;
|
||||
};
|
||||
|
||||
struct XlsxImageData
|
||||
{
|
||||
XlsxImageData(int row, int col, const QImage &image, const QPointF &offset, double xScale, double yScale) :
|
||||
row(row), col(col), image(image), offset(offset), xScale(xScale), yScale(yScale)
|
||||
{
|
||||
}
|
||||
|
||||
int row;
|
||||
int col;
|
||||
QImage image;
|
||||
QPointF offset;
|
||||
double xScale;
|
||||
double yScale;
|
||||
};
|
||||
|
||||
/*
|
||||
The vertices that define the position of a graphical object
|
||||
within the worksheet in pixels.
|
||||
|
||||
+------------+------------+
|
||||
| A | B |
|
||||
+-----+------------+------------+
|
||||
| |(x1,y1) | |
|
||||
| 1 |(A1)._______|______ |
|
||||
| | | | |
|
||||
| | | | |
|
||||
+-----+----| OBJECT |-----+
|
||||
| | | | |
|
||||
| 2 | |______________. |
|
||||
| | | (B2)|
|
||||
| | | (x2,y2)|
|
||||
+---- +------------+------------+
|
||||
|
||||
Example of an object that covers some of the area from cell A1 to B2.
|
||||
|
||||
Based on the width and height of the object we need to calculate 8 vars:
|
||||
|
||||
col_start, row_start, col_end, row_end, x1, y1, x2, y2.
|
||||
|
||||
We also calculate the absolute x and y position of the top left vertex of
|
||||
the object. This is required for images.
|
||||
|
||||
The width and height of the cells that the object occupies can be
|
||||
variable and have to be taken into account.
|
||||
*/
|
||||
struct XlsxObjectPositionData
|
||||
{
|
||||
int col_start;
|
||||
double x1;
|
||||
int row_start;
|
||||
double y1;
|
||||
int col_end;
|
||||
double x2;
|
||||
int row_end;
|
||||
double y2;
|
||||
double width;
|
||||
double height;
|
||||
double x_abs;
|
||||
double y_abs;
|
||||
};
|
||||
|
||||
struct XlsxRowInfo
|
||||
{
|
||||
XlsxRowInfo(double height=0, const Format &format=Format(), bool hidden=false) :
|
||||
@@ -193,8 +132,6 @@ public:
|
||||
void saveXmlDataValidations(QXmlStreamWriter &writer) const;
|
||||
int rowPixelsSize(int row) const;
|
||||
int colPixelsSize(int col) const;
|
||||
XlsxObjectPositionData objectPixelsPosition(int col_start, int row_start, double x1, double y1, double width, double height) const;
|
||||
XlsxObjectPositionData pixelsToEMUs(const XlsxObjectPositionData &data) const;
|
||||
|
||||
QSharedPointer<Cell> loadXmlNumericCellData(QXmlStreamReader &reader);
|
||||
void loadXmlSheetData(QXmlStreamReader &reader);
|
||||
@@ -210,15 +147,14 @@ public:
|
||||
Workbook *workbook;
|
||||
mutable Relationships relationships;
|
||||
Drawing *drawing;
|
||||
QString drawingPath_in_zip;
|
||||
QMap<int, QMap<int, QSharedPointer<Cell> > > cellTable;
|
||||
QMap<int, QMap<int, QString> > comments;
|
||||
QMap<int, QMap<int, QSharedPointer<XlsxHyperlinkData> > > urlTable;
|
||||
QList<CellRange> merges;
|
||||
QList<XlsxImageData *> imageList;
|
||||
QMap<int, QSharedPointer<XlsxRowInfo> > rowsInfo;
|
||||
QMap<int, QSharedPointer<XlsxColumnInfo> > colsInfo;
|
||||
QMap<int, QSharedPointer<XlsxColumnInfo> > colsInfoHelper;
|
||||
QList<QPair<QString, QString> > drawingLinks;
|
||||
|
||||
QList<DataValidation> dataValidationsList;
|
||||
QList<ConditionalFormatting> conditionalFormattingList;
|
||||
|
||||
Reference in New Issue
Block a user