Fix Issue1: Add insert_image() function

This commit is contained in:
Debao Zhang
2013-09-04 11:35:02 +08:00
parent 7f7fa7e9fa
commit b9dc02b79e
15 changed files with 692 additions and 12 deletions
+219
View File
@@ -29,6 +29,7 @@
#include "xlsxutility_p.h"
#include "xlsxsharedstrings_p.h"
#include "xlsxxmlwriter_p.h"
#include "xlsxdrawing_p.h"
#include <QVariant>
#include <QDateTime>
@@ -45,6 +46,8 @@ namespace QXlsx {
WorksheetPrivate::WorksheetPrivate(Worksheet *p) :
q_ptr(p)
{
drawing = 0;
xls_rowmax = 1048576;
xls_colmax = 16384;
xls_strmax = 32767;
@@ -264,6 +267,18 @@ QStringList Worksheet::externUrlList() const
return d->externUrlList;
}
QStringList Worksheet::externDrawingList() const
{
Q_D(const Worksheet);
return d->externDrawingList;
}
QList<QPair<QString, QString> > Worksheet::drawingLinks() const
{
Q_D(const Worksheet);
return d->drawingLinks;
}
int Worksheet::write(int row, int column, const QVariant &value, Format *format)
{
Q_D(Worksheet);
@@ -461,6 +476,14 @@ int Worksheet::writeUrl(int row, int column, const QUrl &url, Format *format, co
return error;
}
int Worksheet::insertImage(int row, int column, const QImage &image, const QPointF &offset, double xScale, double yScale)
{
Q_D(Worksheet);
d->imageList.append(new XlsxImageData(row, column, image, offset, xScale, yScale));
return 0;
}
void Worksheet::saveToXmlFile(QIODevice *device)
{
Q_D(Worksheet);
@@ -533,6 +556,7 @@ void Worksheet::saveToXmlFile(QIODevice *device)
writer.writeEndElement();//sheetData
d->writeHyperlinks(writer);
d->writeDrawings(writer);
writer.writeEndElement();//worksheet
writer.writeEndDocument();
@@ -681,6 +705,13 @@ void WorksheetPrivate::writeHyperlinks(XmlStreamWriter &writer)
writer.writeEndElement();//hyperlinks
}
void WorksheetPrivate::writeDrawings(XmlStreamWriter &writer)
{
int index = externUrlList.size() + 1;
writer.writeEmptyElement(QStringLiteral("drawing"));
writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(index));
}
/*
Sets row height and format. Row height measured in point size. If format
equals 0 then format is ignored.
@@ -729,4 +760,192 @@ bool Worksheet::setColumn(int colFirst, int colLast, double width, Format *forma
return true;
}
Drawing *Worksheet::drawing() const
{
Q_D(const Worksheet);
return d->drawing;
}
QList<XlsxImageData *> Worksheet::images() const
{
Q_D(const Worksheet);
return d->imageList;
}
void Worksheet::clearExtraDrawingInfo()
{
Q_D(Worksheet);
if (d->drawing) {
delete d->drawing;
d->drawing = 0;
d->externDrawingList.clear();
d->drawingLinks.clear();
}
}
void Worksheet::prepareImage(int index, int image_id, int drawing_id)
{
Q_D(Worksheet);
if (!d->drawing) {
d->drawing = new Drawing(this);
d->drawing->embedded = true;
d->externDrawingList.append(QStringLiteral("../drawings/drawing%1.xml").arg(drawing_id));
}
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)));
}
/*
Convert the height of a cell from user's units to pixels. If the
height hasn't been set by the user we use the default value. If
the row is hidden it has a value of zero.
*/
int WorksheetPrivate::rowPixelsSize(int row)
{
double height;
if (row_sizes.contains(row))
height = row_sizes[row];
else
height = default_row_height;
return static_cast<int>(4.0 / 3.0 *height);
}
/*
Convert the width of a cell from user's units to pixels. Excel rounds
the column width to the nearest pixel. If the width hasn't been set
by the user we use the default value. If the column is hidden it
has a value of zero.
*/
int WorksheetPrivate::colPixelsSize(int col)
{
double max_digit_width = 7.0; //For Calabri 11
double padding = 5.0;
int pixels = 0;
if (col_sizes.contains(col)) {
double width = col_sizes[col];
if (width < 1)
pixels = static_cast<int>(width * (max_digit_width + padding) + 0.5);
else
pixels = static_cast<int>(width * max_digit_width + 0.5) + padding;
} else {
pixels = 64;
}
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)
{
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)
{
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;
}
} //namespace