Browse Source

Refactor QXlsx::Styles and QXlsx::Format

master
Debao Zhang 11 years ago
parent
commit
113f1c760b
  1. 2
      src/xlsx/xlsxdocument.cpp
  2. 123
      src/xlsx/xlsxformat.cpp
  3. 21
      src/xlsx/xlsxformat.h
  4. 14
      src/xlsx/xlsxformat_p.h
  5. 8
      src/xlsx/xlsxpackage.cpp
  6. 396
      src/xlsx/xlsxstyles.cpp
  7. 43
      src/xlsx/xlsxstyles_p.h
  8. 8
      src/xlsx/xlsxworkbook.cpp
  9. 2
      src/xlsx/xlsxworkbook.h
  10. 2
      src/xlsx/xlsxworkbook_p.h
  11. 14
      src/xlsx/xlsxworksheet.cpp
  12. 3
      tests/auto/auto.pro
  13. 13
      tests/auto/styles/styles.pro
  14. 46
      tests/auto/styles/tst_stylestest.cpp

2
src/xlsx/xlsxdocument.cpp

@ -63,7 +63,7 @@ Document::Document(QIODevice *device, QObject *parent) :
Format *Document::createFormat()
{
Q_D(Document);
return d->workbook->addFormat();
return d->workbook->createFormat();
}
int Document::write(const QString row_column, const QVariant &value, Format *format)

123
src/xlsx/xlsxformat.cpp

@ -29,9 +29,6 @@
namespace QXlsx {
QList<Format *> FormatPrivate::s_xfFormats;
QList<Format *> FormatPrivate::s_dxfFormats;
FormatPrivate::FormatPrivate(Format *p) :
q_ptr(p)
{
@ -40,6 +37,8 @@ FormatPrivate::FormatPrivate(Format *p) :
is_dxf_fomat = false;
xf_index = -1;
dxf_index = -1;
xf_indexValid = false;
dxf_indexValid = false;
theme = 0;
color_indexed = 0;
@ -186,16 +185,10 @@ void Format::setFontName(const QString &name)
d->fontData._dirty = true;
}
bool Format::hasFont() const
bool Format::fontIndexValid() const
{
Q_D(const Format);
return !d->fontData._redundant;
}
void Format::setFontRedundant(bool redundant)
{
Q_D(Format);
d->fontData._redundant = redundant;
return !d->fontData._dirty && d->fontData._indexValid;
}
int Format::fontIndex() const
@ -208,6 +201,7 @@ void Format::setFontIndex(int index)
{
Q_D(Format);
d->fontData._index = index;
d->fontData._indexValid = true;
}
int Format::fontFamily() const
@ -243,6 +237,7 @@ QByteArray Format::fontKey() const
const_cast<FormatPrivate*>(d)->fontData._key = key;
const_cast<FormatPrivate*>(d)->fontData._dirty = false;
const_cast<FormatPrivate*>(d)->fontData._indexValid = false; //must re-assign a new index
const_cast<FormatPrivate*>(d)->dirty = true; //Make sure formatKey() will be re-generated.
}
@ -579,16 +574,10 @@ void Format::setDiagonalBorderColor(const QColor &color)
d->borderData._dirty = true;
}
bool Format::hasBorders() const
bool Format::borderIndexValid() const
{
Q_D(const Format);
return !d->borderData._redundant;
}
void Format::setBorderRedundant(bool redundant)
{
Q_D(Format);
d->borderData._redundant = redundant;
return !d->borderData._dirty && d->borderData._indexValid;
}
int Format::borderIndex() const
@ -601,6 +590,7 @@ void Format::setBorderIndex(int index)
{
Q_D(Format);
d->borderData._index = index;
d->borderData._indexValid = true;
}
/* Internal
@ -618,6 +608,7 @@ QByteArray Format::borderKey() const
<<d->borderData.top<<d->borderData.topColor;
const_cast<FormatPrivate*>(d)->borderData._key = key;
const_cast<FormatPrivate*>(d)->borderData._dirty = false;
const_cast<FormatPrivate*>(d)->borderData._indexValid = false;
const_cast<FormatPrivate*>(d)->dirty = true; //Make sure formatKey() will be re-generated.
}
@ -667,16 +658,10 @@ void Format::setPatternBackgroundColor(const QColor &color)
d->fillData._dirty = true;
}
bool Format::hasFill() const
bool Format::fillIndexValid() const
{
Q_D(const Format);
return !d->fillData._redundant;
}
void Format::setFillRedundant(bool redundant)
{
Q_D(Format);
d->fillData._redundant = redundant;
return !d->fillData._dirty && d->fillData._indexValid;
}
int Format::fillIndex() const
@ -689,6 +674,7 @@ void Format::setFillIndex(int index)
{
Q_D(Format);
d->fillData._index = index;
d->fillData._indexValid = true;
}
/* Internal
@ -702,6 +688,7 @@ QByteArray Format::fillKey() const
stream<<d->fillData.bgColor<<d->fillData.fgColor<<d->fillData.pattern;
const_cast<FormatPrivate*>(d)->fillData._key = key;
const_cast<FormatPrivate*>(d)->fillData._dirty = false;
const_cast<FormatPrivate*>(d)->fillData._indexValid = false;
const_cast<FormatPrivate*>(d)->dirty = true; //Make sure formatKey() will be re-generated.
}
@ -747,83 +734,77 @@ QByteArray Format::formatKey() const
<<d->protectionData.hidden<<d->protectionData.locked;
const_cast<FormatPrivate*>(d)->formatKey = key;
const_cast<FormatPrivate*>(d)->dirty = false;
const_cast<FormatPrivate*>(d)->xf_indexValid = false;
const_cast<FormatPrivate*>(d)->dxf_indexValid = false;
}
return d->formatKey;
}
bool Format::operator ==(const Format &format) const
void Format::setXfIndex(int index)
{
return this->formatKey() == format.formatKey();
Q_D(Format);
d->xf_index = index;
d->xf_indexValid = true;
}
bool Format::operator !=(const Format &format) const
int Format::xfIndex() const
{
return this->formatKey() != format.formatKey();
Q_D(const Format);
return d->xf_index;
}
/* Internal
*
* This function will be called when wirte the cell contents of worksheet to xml files.
* Depending on the order of the Format used instead of the Format created, we assign a
* index to it.
*/
int Format::xfIndex(bool generateIfNotValid)
{
Q_D(Format);
if (d->xf_index == -1 && generateIfNotValid) { //Generate a valid xf_index for this format
int index = -1;
for (int i=0; i<d->s_xfFormats.size(); ++i) {
if (*d->s_xfFormats[i] == *this) {
index = i;
break;
}
}
if (index != -1) {
d->xf_index = index;
} else {
d->xf_index = d->s_xfFormats.size();
d->s_xfFormats.append(this);
}
}
return d->xf_index;
bool Format::xfIndexValid() const
{
Q_D(const Format);
return !d->dirty && d->xf_indexValid;
}
void Format::clearExtraInfos()
void Format::setDxfIndex(int index)
{
Q_D(Format);
d->xf_index = -1;
d->dxf_index = -1;
d->s_xfFormats.clear();
d->s_dxfFormats.clear();
d->dxf_index = index;
d->dxf_indexValid = true;
}
bool Format::isDxfFormat() const
int Format::dxfIndex() const
{
Q_D(const Format);
return d->is_dxf_fomat;
return d->dxf_index;
}
int Format::theme() const
bool Format::dxfIndexValid() const
{
Q_D(const Format);
return d->theme;
return !d->dirty && d->dxf_indexValid;
}
int Format::colorIndexed() const
bool Format::operator ==(const Format &format) const
{
return this->formatKey() == format.formatKey();
}
bool Format::operator !=(const Format &format) const
{
return this->formatKey() != format.formatKey();
}
bool Format::isDxfFormat() const
{
Q_D(const Format);
return d->color_indexed;
return d->is_dxf_fomat;
}
QList<Format *> Format::xfFormats()
int Format::theme() const
{
return FormatPrivate::s_xfFormats;
Q_D(const Format);
return d->theme;
}
QList<Format *> Format::dxfFormats()
int Format::colorIndexed() const
{
return FormatPrivate::s_dxfFormats;
Q_D(const Format);
return d->color_indexed;
}
} // namespace QXlsx

21
src/xlsx/xlsxformat.h

@ -210,8 +210,7 @@ private:
friend class WorksheetPrivate;
Format();
bool hasFont() const;
void setFontRedundant(bool redundant);
bool fontIndexValid() const;
int fontIndex() const;
void setFontIndex(int index);
QByteArray fontKey() const;
@ -223,26 +222,24 @@ private:
QString horizontalAlignmentString() const;
QString verticalAlignmentString() const;
bool borderIndexValid() const;
QByteArray borderKey() const;
bool hasBorders() const;
void setBorderRedundant(bool redundant);
int borderIndex() const;
void setBorderIndex(int index);
bool fillIndexValid() const;
QByteArray fillKey() const;
bool hasFill() const;
void setFillRedundant(bool redundant);
int fillIndex() const;
void setFillIndex(int index);
QByteArray formatKey() const;
static QList<Format *> xfFormats();
static QList<Format *> dxfFormats();
int xfIndex(bool generateIfNotValid=true); //Generate index when first called.
void clearExtraInfos();
bool xfIndexValid() const;
int xfIndex() const;
void setXfIndex(int index);
bool isDxfFormat() const;
bool dxfIndexValid() const;
int dxfIndex() const;
void setDxfIndex(int index);
int theme() const;
int colorIndexed() const;

14
src/xlsx/xlsxformat_p.h

@ -42,7 +42,7 @@ struct FontData
, scirpt(Format::FontScriptNormal), underline(Format::FontUnderlineNone)
, outline(false), shadow(false), name(QStringLiteral("Calibri")), family(2), charset(0)
, scheme(QStringLiteral("minor")), condense(0), extend(0)
, _dirty(true), _redundant(false), _index(-1)
, _dirty(true), _indexValid(false), _index(-1)
{}
@ -65,7 +65,7 @@ struct FontData
//helper member
bool _dirty; //key re-generated is need.
QByteArray _key;
bool _redundant; //same font already used by some other Formats
bool _indexValid; //has a valid index, so no need to assign a new one
int _index; //index in the Font list
};
@ -90,7 +90,7 @@ struct BorderData
left(Format::BorderNone), right(Format::BorderNone), top(Format::BorderNone)
,bottom(Format::BorderNone), diagonal(Format::BorderNone)
,diagonalType(Format::DiagonalBorderNone)
,_dirty(true), _redundant(false), _index(-1)
,_dirty(true), _indexValid(false), _index(-1)
{}
Format::BorderStyle left;
@ -108,14 +108,14 @@ struct BorderData
//helper member
bool _dirty; //key re-generated is need.
QByteArray _key;
bool _redundant; //same border already used by some other Formats
bool _indexValid; //has a valid index, so no need to assign a new one
int _index; //index in the border list
};
struct FillData {
FillData() :
pattern(Format::PatternNone)
,_dirty(true), _redundant(false), _index(-1)
,_dirty(true), _indexValid(false), _index(-1)
{}
Format::FillPattern pattern;
@ -125,7 +125,7 @@ struct FillData {
//helper member
bool _dirty; //key re-generated is need.
QByteArray _key;
bool _redundant; //same border already used by some other Formats
bool _indexValid; //has a valid index, so no need to assign a new one
int _index; //index in the border list
};
@ -156,10 +156,12 @@ public:
static QList<Format *> s_xfFormats;
int xf_index;
bool xf_indexValid;
static QList<Format *> s_dxfFormats;
bool is_dxf_fomat;
int dxf_index;
bool dxf_indexValid;
int theme;
int color_indexed;

8
src/xlsx/xlsxpackage.cpp

@ -143,7 +143,6 @@ bool Package::createPackage(QIODevice *package)
if (zipWriter.error())
return false;
m_workbook->styles()->clearExtraFormatInfo(); //These info will be generated when write the worksheet data.
m_workbook->prepareDrawings();
writeWorksheetFiles(zipWriter);
@ -158,7 +157,6 @@ bool Package::createPackage(QIODevice *package)
writeDocPropsAppFile(zipWriter);
writeDocPropsCoreFile(zipWriter);
writeContentTypesFile(zipWriter);
m_workbook->styles()->prepareStyles();
writeStylesFiles(zipWriter);
writeThemeFile(zipWriter);
writeRootRelsFile(zipWriter);
@ -280,11 +278,7 @@ void Package::writeSharedStringsFile(ZipWriter &zipWriter)
void Package::writeStylesFiles(ZipWriter &zipWriter)
{
QByteArray data;
QBuffer buffer(&data);
buffer.open(QIODevice::WriteOnly);
m_workbook->styles()->saveToXmlFile(&buffer);
zipWriter.addFile(QStringLiteral("xl/styles.xml"), data);
zipWriter.addFile(QStringLiteral("xl/styles.xml"), m_workbook->styles()->saveToXmlData());
}
void Package::writeThemeFile(ZipWriter &zipWriter)

396
src/xlsx/xlsxstyles.cpp

@ -23,118 +23,113 @@
**
****************************************************************************/
#include "xlsxstyles_p.h"
#include "xlsxformat.h"
#include "xlsxxmlwriter_p.h"
#include "xlsxformat_p.h"
#include <QFile>
#include <QMap>
#include <QDataStream>
#include <QDebug>
#include <QBuffer>
namespace QXlsx {
Styles::Styles(QObject *parent) :
QObject(parent)
Styles::Styles()
{
m_fill_count = 0;
m_borders_count = 0;
m_font_count = 0;
//Add default Format
addFormat(createFormat());
//Add another fill format
QSharedPointer<FillData> fill = QSharedPointer<FillData>(new FillData);
fill->pattern = Format::PatternGray125;
m_fillsList.append(fill);
m_fillsHash[fill->_key] = fill;
}
Styles::~Styles()
{
qDeleteAll(m_formats);
}
Format *Styles::addFormat()
Format *Styles::createFormat()
{
Format *format = new Format();
m_createdFormatsList.append(QSharedPointer<Format>(format));
m_formats.append(format);
return format;
}
/*
* This function should be called after worksheet written finished,
* which means the order of the Formats used have been known to us.
*/
void Styles::prepareStyles()
Assign index to Font/Fill/Border and Format
*/
void Styles::addFormat(Format *format)
{
m_xf_formats = Format::xfFormats();
m_dxf_formats = Format::dxfFormats();
if (m_xf_formats.isEmpty())
m_xf_formats.append(this->addFormat());
//fonts
QMap<QByteArray, int> fontsKeyCache;
foreach (Format *format, m_xf_formats) {
const QByteArray &key = format->fontKey();
if (fontsKeyCache.contains(key)) {
//Font has already been used.
format->setFontIndex(fontsKeyCache[key]);
format->setFontRedundant(true);
} else {
int index = fontsKeyCache.size();
fontsKeyCache[key] = index;
format->setFontIndex(index);
format->setFontRedundant(false);
}
}
m_font_count = fontsKeyCache.size();
//borders
QMap<QByteArray, int> bordersKeyCache;
foreach (Format *format, m_xf_formats) {
const QByteArray &key = format->borderKey();
if (bordersKeyCache.contains(key)) {
//Border has already been used.
format->setBorderIndex(bordersKeyCache[key]);
format->setBorderRedundant(true);
} else {
int index = bordersKeyCache.size();
bordersKeyCache[key] = index;
format->setBorderIndex(index);
format->setBorderRedundant(false);
}
if (!format)
return;
//Font
if (!format->fontIndexValid()) {
if (!m_fontsHash.contains(format->fontKey())) {
QSharedPointer<FontData> font = QSharedPointer<FontData>(new FontData(format->d_func()->fontData));
font->_index = m_fontsList.size(); //Assign proper index
m_fontsList.append(font);
m_fontsHash[font->_key] = font;
}
format->setFontIndex(m_fontsHash[format->fontKey()]->_index);
}
m_borders_count = bordersKeyCache.size();
//fills
QMap<QByteArray, int> fillsKeyCache;
// The user defined fill properties start from 2 since there are 2
// default fills: patternType="none" and patternType="gray125".
{
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
stream<<QColor()<<QColor()<<Format::PatternNone;
fillsKeyCache[key] = 0;
//Fill
if (!format->fillIndexValid()) {
if (!m_fillsHash.contains(format->fillKey())) {
QSharedPointer<FillData> fill = QSharedPointer<FillData>(new FillData(format->d_func()->fillData));
fill->_index = m_fillsList.size(); //Assign proper index
m_fillsList.append(fill);
m_fillsHash[fill->_key] = fill;
}
format->setFillIndex(m_fillsHash[format->fillKey()]->_index);
}
{
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
stream<<QColor()<<QColor()<<Format::PatternGray125;
fillsKeyCache[key] = 1;
//Border
if (!format->borderIndexValid()) {
if (!m_bordersHash.contains(format->borderKey())) {
QSharedPointer<BorderData> border = QSharedPointer<BorderData>(new BorderData(format->d_func()->borderData));
border->_index = m_bordersList.size(); //Assign proper index
m_bordersList.append(border);
m_bordersHash[border->_key] = border;
}
format->setBorderIndex(m_bordersHash[format->borderKey()]->_index);
}
foreach (Format *format, m_xf_formats) {
const QByteArray &key = format->fillKey();
if (fillsKeyCache.contains(key)) {
//Border has already been used.
format->setFillIndex(fillsKeyCache[key]);
format->setFillRedundant(true);
} else {
int index = fillsKeyCache.size();
fillsKeyCache[key] = index;
format->setFillIndex(index);
format->setFillRedundant(false);
}
//Format
if (format->isDxfFormat()) {
if (!format->dxfIndexValid()) {
if (!m_dxf_formatsHash.contains(format->formatKey())) {
format->setDxfIndex(m_dxf_formatsList.size());
m_dxf_formatsList.append(format);
m_dxf_formatsHash[format->formatKey()] = format;
} else {
format->setDxfIndex(m_dxf_formatsHash[format->formatKey()]->dxfIndex());
}
}
} else {
if (!format->xfIndexValid()) {
if (!m_xf_formatsHash.contains(format->formatKey())) {
format->setXfIndex(m_xf_formatsList.size());
m_xf_formatsList.append(format);
m_xf_formatsHash[format->formatKey()] = format;
} else {
format->setXfIndex(m_xf_formatsHash[format->formatKey()]->xfIndex());
}
}
}
m_fill_count = fillsKeyCache.size();
}
void Styles::clearExtraFormatInfo()
QByteArray Styles::saveToXmlData()
{
foreach (Format *format, m_formats)
format->clearExtraInfos();
QByteArray data;
QBuffer buffer(&data);
buffer.open(QIODevice::WriteOnly);
saveToXmlFile(&buffer);
return data;
}
void Styles::saveToXmlFile(QIODevice *device)
@ -185,75 +180,94 @@ void Styles::saveToXmlFile(QIODevice *device)
writer.writeEndDocument();
}
/*
not consider dxf format.
*/
void Styles::writeFonts(XmlStreamWriter &writer)
{
writer.writeStartElement(QStringLiteral("fonts"));
writer.writeAttribute(QStringLiteral("count"), QString::number(m_font_count));
foreach (Format *format, m_xf_formats) {
if (format->hasFont()) {
writer.writeStartElement(QStringLiteral("font"));
if (format->fontBold())
writer.writeEmptyElement(QStringLiteral("b"));
if (format->fontItalic())
writer.writeEmptyElement(QStringLiteral("i"));
if (format->fontStrikeOut())
writer.writeEmptyElement(QStringLiteral("strike"));
if (format->fontOutline())
writer.writeEmptyElement(QStringLiteral("outline"));
if (format->fontShadow())
writer.writeEmptyElement(QStringLiteral("shadow"));
if (format->fontUnderline() != Format::FontUnderlineNone) {
writer.writeEmptyElement(QStringLiteral("u"));
if (format->fontUnderline() == Format::FontUnderlineDouble)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("double"));
else if (format->fontUnderline() == Format::FontUnderlineSingleAccounting)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("singleAccounting"));
else if (format->fontUnderline() == Format::FontUnderlineDoubleAccounting)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("doubleAccounting"));
}
if (format->fontScript() != Format::FontScriptNormal) {
writer.writeEmptyElement(QStringLiteral("vertAligh"));
if (format->fontScript() == Format::FontScriptSuper)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("superscript"));
else
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("subscript"));
}
writer.writeAttribute(QStringLiteral("count"), QString::number(m_fontsList.count()));
for (int i=0; i<m_fontsList.size(); ++i) {
QSharedPointer<FontData> font = m_fontsList[i];
writer.writeStartElement(QStringLiteral("font"));
if (font->bold)
writer.writeEmptyElement(QStringLiteral("b"));
if (font->italic)
writer.writeEmptyElement(QStringLiteral("i"));
if (font->strikeOut)
writer.writeEmptyElement(QStringLiteral("strike"));
if (font->outline)
writer.writeEmptyElement(QStringLiteral("outline"));
if (font->shadow)
writer.writeEmptyElement(QStringLiteral("shadow"));
if (font->underline != Format::FontUnderlineNone) {
writer.writeEmptyElement(QStringLiteral("u"));
if (font->underline == Format::FontUnderlineDouble)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("double"));
else if (font->underline == Format::FontUnderlineSingleAccounting)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("singleAccounting"));
else if (font->underline == Format::FontUnderlineDoubleAccounting)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("doubleAccounting"));
}
if (font->scirpt != Format::FontScriptNormal) {
writer.writeEmptyElement(QStringLiteral("vertAligh"));
if (font->scirpt == Format::FontScriptSuper)
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("superscript"));
else
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("subscript"));
}
if (!format->isDxfFormat()) {
writer.writeEmptyElement(QStringLiteral("sz"));
writer.writeAttribute(QStringLiteral("val"), QString::number(format->fontSize()));
}
writer.writeEmptyElement(QStringLiteral("sz"));
writer.writeAttribute(QStringLiteral("val"), QString::number(font->size));
//font color
if (format->theme()) {
writer.writeEmptyElement(QStringLiteral("color"));
writer.writeAttribute(QStringLiteral("theme"), QString::number(format->theme()));
} else if (format->colorIndexed()) {
writer.writeEmptyElement(QStringLiteral("color"));
writer.writeAttribute(QStringLiteral("indexed"), QString::number(format->colorIndexed()));
} else if (format->fontColor().isValid()) {
writer.writeEmptyElement(QStringLiteral("color"));
QString color = format->fontColor().name();
writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+color.mid(1));//remove #
} else if (!format->isDxfFormat()) {
writer.writeEmptyElement(QStringLiteral("color"));
writer.writeAttribute(QStringLiteral("theme"), QStringLiteral("1"));
}
if (!format->isDxfFormat()) {
writer.writeEmptyElement(QStringLiteral("name"));
writer.writeAttribute(QStringLiteral("val"), format->fontName());
writer.writeEmptyElement(QStringLiteral("family"));
writer.writeAttribute(QStringLiteral("val"), QString::number(format->fontFamily()));
if (format->fontName() == QLatin1String("Calibri")) {
writer.writeEmptyElement(QStringLiteral("scheme"));
writer.writeAttribute(QStringLiteral("val"), format->fontScheme());
}
}
if (font->color.isValid()) {
writer.writeEmptyElement(QStringLiteral("color"));
QString color = font->color.name();
writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+color.mid(1));//remove #
}
writer.writeEndElement(); //font
writer.writeEmptyElement(QStringLiteral("name"));
writer.writeAttribute(QStringLiteral("val"), font->name);
writer.writeEmptyElement(QStringLiteral("family"));
writer.writeAttribute(QStringLiteral("val"), QString::number(font->family));
if (font->name == QLatin1String("Calibri")) {
writer.writeEmptyElement(QStringLiteral("scheme"));
writer.writeAttribute(QStringLiteral("val"), font->scheme);
}
// if (!format->isDxfFormat()) {
// writer.writeEmptyElement(QStringLiteral("sz"));
// writer.writeAttribute(QStringLiteral("val"), QString::number(format->fontSize()));
// }
//
// //font color
// if (format->theme()) {
// writer.writeEmptyElement(QStringLiteral("color"));
// writer.writeAttribute(QStringLiteral("theme"), QString::number(format->theme()));
// } else if (format->colorIndexed()) {
// writer.writeEmptyElement(QStringLiteral("color"));
// writer.writeAttribute(QStringLiteral("indexed"), QString::number(format->colorIndexed()));
// } else if (format->fontColor().isValid()) {
// writer.writeEmptyElement(QStringLiteral("color"));
// QString color = format->fontColor().name();
// writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+color.mid(1));//remove #
// } else if (!format->isDxfFormat()) {
// writer.writeEmptyElement(QStringLiteral("color"));
// writer.writeAttribute(QStringLiteral("theme"), QStringLiteral("1"));
// }
// if (!format->isDxfFormat()) {
// writer.writeEmptyElement(QStringLiteral("name"));
// writer.writeAttribute(QStringLiteral("val"), format->fontName());
// writer.writeEmptyElement(QStringLiteral("family"));
// writer.writeAttribute(QStringLiteral("val"), QString::number(format->fontFamily()));
// if (format->fontName() == QLatin1String("Calibri")) {
// writer.writeEmptyElement(QStringLiteral("scheme"));
// writer.writeAttribute(QStringLiteral("val"), format->fontScheme());
// }
// }
writer.writeEndElement(); //font
}
writer.writeEndElement();//fonts
}
@ -261,25 +275,16 @@ void Styles::writeFonts(XmlStreamWriter &writer)
void Styles::writeFills(XmlStreamWriter &writer)
{
writer.writeStartElement(QStringLiteral("fills"));
writer.writeAttribute(QStringLiteral("count"), QString::number(m_fill_count));
//wirte two default fill first
writer.writeStartElement(QStringLiteral("fill"));
writer.writeEmptyElement(QStringLiteral("patternFill"));
writer.writeAttribute(QStringLiteral("patternType"), QStringLiteral("none"));
writer.writeEndElement();//fill
writer.writeStartElement(QStringLiteral("fill"));
writer.writeEmptyElement(QStringLiteral("patternFill"));
writer.writeAttribute(QStringLiteral("patternType"), QStringLiteral("gray125"));
writer.writeEndElement();//fill
foreach (Format *format, m_xf_formats) {
if (format->hasFill()) {
writeFill(writer, format);
}
writer.writeAttribute(QStringLiteral("count"), QString::number(m_fillsList.size()));
for (int i=0; i<m_fillsList.size(); ++i) {
QSharedPointer<FillData> fill = m_fillsList[i];
writeFill(writer, fill.data());
}
writer.writeEndElement(); //fills
}
void Styles::writeFill(XmlStreamWriter &writer, Format *format)
void Styles::writeFill(XmlStreamWriter &writer, FillData *fill)
{
static QMap<int, QString> patternStrings;
if (patternStrings.isEmpty()) {
@ -305,14 +310,14 @@ void Styles::writeFill(XmlStreamWriter &writer, Format *format)
writer.writeStartElement(QStringLiteral("fill"));
writer.writeStartElement(QStringLiteral("patternFill"));
writer.writeAttribute(QStringLiteral("patternType"), patternStrings[format->fillPattern()]);
if (format->patternForegroundColor().isValid()) {
writer.writeAttribute(QStringLiteral("patternType"), patternStrings[fill->pattern]);
if (fill->fgColor.isValid()) {
writer.writeEmptyElement(QStringLiteral("fgColor"));
writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+format->patternForegroundColor().name().mid(1));
writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+fill->fgColor.name().mid(1));
}
if (format->patternBackgroundColor().isValid()) {
if (fill->bgColor.isValid()) {
writer.writeEmptyElement(QStringLiteral("bgColor"));
writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+format->patternBackgroundColor().name().mid(1));
writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+fill->bgColor.name().mid(1));
}
writer.writeEndElement();//patternFill
@ -322,28 +327,28 @@ void Styles::writeFill(XmlStreamWriter &writer, Format *format)
void Styles::writeBorders(XmlStreamWriter &writer)
{
writer.writeStartElement(QStringLiteral("borders"));
writer.writeAttribute(QStringLiteral("count"), QString::number(m_borders_count));
foreach (Format *format, m_xf_formats) {
if (format->hasBorders()) {
writer.writeStartElement(QStringLiteral("border"));
if (format->diagonalBorderType() == Format::DiagonalBorderUp) {
writer.writeAttribute(QStringLiteral("diagonalUp"), QStringLiteral("1"));
} else if (format->diagonalBorderType() == Format::DiagonalBorderDown) {
writer.writeAttribute(QStringLiteral("diagonalDown"), QStringLiteral("1"));
} else if (format->DiagnoalBorderBoth) {
writer.writeAttribute(QStringLiteral("diagonalUp"), QStringLiteral("1"));
writer.writeAttribute(QStringLiteral("diagonalDown"), QStringLiteral("1"));
}
writeSubBorder(writer, QStringLiteral("left"), format->leftBorderStyle(), format->leftBorderColor());
writeSubBorder(writer, QStringLiteral("right"), format->rightBorderStyle(), format->rightBorderColor());
writeSubBorder(writer, QStringLiteral("top"), format->topBorderStyle(), format->topBorderColor());
writeSubBorder(writer, QStringLiteral("bottom"), format->bottomBorderStyle(), format->bottomBorderColor());
if (!format->isDxfFormat()) {
writeSubBorder(writer, QStringLiteral("diagonal"), format->diagonalBorderStyle(), format->diagonalBorderColor());
}
writer.writeEndElement();//border
writer.writeAttribute(QStringLiteral("count"), QString::number(m_bordersList.count()));
for (int i=0; i<m_bordersList.size(); ++i) {
QSharedPointer<BorderData> border = m_bordersList[i];
writer.writeStartElement(QStringLiteral("border"));
if (border->diagonalType == Format::DiagonalBorderUp) {
writer.writeAttribute(QStringLiteral("diagonalUp"), QStringLiteral("1"));
} else if (border->diagonalType == Format::DiagonalBorderDown) {
writer.writeAttribute(QStringLiteral("diagonalDown"), QStringLiteral("1"));
} else if (border->diagonalType == Format::DiagnoalBorderBoth) {
writer.writeAttribute(QStringLiteral("diagonalUp"), QStringLiteral("1"));
writer.writeAttribute(QStringLiteral("diagonalDown"), QStringLiteral("1"));
}
writeSubBorder(writer, QStringLiteral("left"), border->left, border->leftColor);
writeSubBorder(writer, QStringLiteral("right"), border->right, border->rightColor);
writeSubBorder(writer, QStringLiteral("top"), border->top, border->topColor);
writeSubBorder(writer, QStringLiteral("bottom"), border->bottom, border->bottomColor);
// if (!format->isDxfFormat()) {
writeSubBorder(writer, QStringLiteral("diagonal"), border->diagonal, border->diagonalColor);
// }
writer.writeEndElement();//border
}
writer.writeEndElement();//borders
}
@ -386,8 +391,8 @@ void Styles::writeSubBorder(XmlStreamWriter &writer, const QString &type, int st
void Styles::writeCellXfs(XmlStreamWriter &writer)
{
writer.writeStartElement(QStringLiteral("cellXfs"));
writer.writeAttribute(QStringLiteral("count"), QString::number(m_xf_formats.size()));
foreach (Format *format, m_xf_formats) {
writer.writeAttribute(QStringLiteral("count"), QString::number(m_xf_formatsList.size()));
foreach (Format *format, m_xf_formatsList) {
int num_fmt_id = format->numberFormat();
int font_id = format->fontIndex();
int fill_id = format->fillIndex();
@ -436,12 +441,27 @@ void Styles::writeCellXfs(XmlStreamWriter &writer)
void Styles::writeDxfs(XmlStreamWriter &writer)
{
writer.writeStartElement(QStringLiteral("dxfs"));
writer.writeAttribute(QStringLiteral("count"), QString::number(m_dxf_formats.size()));
foreach (Format *format, m_dxf_formats) {
writer.writeAttribute(QStringLiteral("count"), QString::number(m_dxf_formatsList.size()));
foreach (Format *format, m_dxf_formatsList) {
writer.writeStartElement(QStringLiteral("dxf"));
writer.writeEndElement();//dxf
}
writer.writeEndElement(); //dxfs
}
QSharedPointer<Styles> Styles::loadFromXmlFile(QIODevice *device)
{
return QSharedPointer<Styles>(new Styles);
}
QSharedPointer<Styles> Styles::loadFromXmlData(const QByteArray &data)
{
QBuffer buffer;
buffer.setData(data);
buffer.open(QIODevice::ReadOnly);
return loadFromXmlFile(&buffer);
}
} //namespace QXlsx

43
src/xlsx/xlsxstyles_p.h

@ -25,42 +25,59 @@
#ifndef XLSXSTYLES_H
#define XLSXSTYLES_H
#include <QObject>
#include "xlsxglobal.h"
#include <QSharedPointer>
#include <QHash>
#include <QList>
class QIODevice;
namespace QXlsx {
class Format;
struct FontData;
struct FillData;
struct BorderData;
class XmlStreamWriter;
class Styles : public QObject
class XLSX_AUTOTEST_EXPORT Styles : public QObject
{
public:
explicit Styles(QObject *parent=0);
Styles();
~Styles();
Format *addFormat();
Format *createFormat();
void addFormat(Format *format);
void prepareStyles();
void clearExtraFormatInfo();
QByteArray saveToXmlData();
void saveToXmlFile(QIODevice *device);
static QSharedPointer<Styles> loadFromXmlFile(QIODevice *device);
static QSharedPointer<Styles> loadFromXmlData(const QByteArray &data);
private:
friend class Format;
void writeFonts(XmlStreamWriter &writer);
void writeFills(XmlStreamWriter &writer);
void writeFill(XmlStreamWriter &writer, Format *format);
void writeFill(XmlStreamWriter &writer, FillData *fill);
void writeBorders(XmlStreamWriter &writer);
void writeSubBorder(XmlStreamWriter &writer, const QString &type, int style, const QColor &color);
void writeCellXfs(XmlStreamWriter &writer);
void writeDxfs(XmlStreamWriter &writer);
QList<Format *> m_formats;
QList<Format *> m_xf_formats;
QList<Format *> m_dxf_formats;
QList<QSharedPointer<FontData> > m_fontsList; //Keep a copy of unique fonts
QList<QSharedPointer<FillData> > m_fillsList; //Keep a copy of unique fills
QList<QSharedPointer<BorderData> > m_bordersList; //Keep a copy of unique borders
QHash<QByteArray, QSharedPointer<FontData> > m_fontsHash;
QHash<QByteArray, QSharedPointer<FillData> > m_fillsHash;
QHash<QByteArray, QSharedPointer<BorderData> > m_bordersHash;
QList<QSharedPointer<Format> > m_createdFormatsList; //All created formats
QList<Format *> m_xf_formatsList;
QHash<QByteArray, Format *> m_xf_formatsHash;
int m_font_count;
int m_fill_count;
int m_borders_count;
QList<Format *> m_dxf_formatsList;
QHash<QByteArray, Format *> m_dxf_formatsHash;
};
}

8
src/xlsx/xlsxworkbook.cpp

@ -41,7 +41,7 @@ WorkbookPrivate::WorkbookPrivate(Workbook *q) :
q_ptr(q)
{
sharedStrings = QSharedPointer<SharedStrings> (new SharedStrings);
styles = new Styles(q);
styles = QSharedPointer<Styles>(new Styles);
x_window = 240;
y_window = 15;
@ -161,10 +161,10 @@ void Workbook::setActivedWorksheet(int index)
d->activesheet = index;
}
Format *Workbook::addFormat()
Format *Workbook::createFormat()
{
Q_D(Workbook);
return d->styles->addFormat();
return d->styles->createFormat();
}
QList<Worksheet *> Workbook::worksheets() const
@ -182,7 +182,7 @@ SharedStrings *Workbook::sharedStrings()
Styles *Workbook::styles()
{
Q_D(Workbook);
return d->styles;
return d->styles.data();
}
QList<QImage> Workbook::images()

2
src/xlsx/xlsxworkbook.h

@ -58,7 +58,7 @@ public:
int activedWorksheet() const;
void setActivedWorksheet(int index);
Format *addFormat();
Format *createFormat();
// void addChart();
void defineName(const QString &name, const QString &formula);
bool isDate1904() const;

2
src/xlsx/xlsxworkbook_p.h

@ -39,7 +39,7 @@ public:
QSharedPointer<SharedStrings> sharedStrings;
QList<Worksheet *> worksheets;
Styles *styles;
QSharedPointer<Styles> styles;
QList<QImage> images;
QList<Drawing *> drawings;

14
src/xlsx/xlsxworksheet.cpp

@ -30,6 +30,7 @@
#include "xlsxsharedstrings_p.h"
#include "xlsxxmlwriter_p.h"
#include "xlsxdrawing_p.h"
#include "xlsxstyles_p.h"
#include <QVariant>
#include <QDateTime>
@ -354,6 +355,7 @@ int Worksheet::writeString(int row, int column, const QString &value, Format *fo
int index = sharedStrings->addSharedString(content);
d->cellTable[row][column] = new XlsxCellData(index, XlsxCellData::String, format);
d->workbook->styles()->addFormat(format);
return error;
}
@ -364,6 +366,7 @@ int Worksheet::writeNumber(int row, int column, double value, Format *format)
return -1;
d->cellTable[row][column] = new XlsxCellData(value, XlsxCellData::Number, format);
d->workbook->styles()->addFormat(format);
return 0;
}
@ -382,6 +385,7 @@ int Worksheet::writeFormula(int row, int column, const QString &content, Format
XlsxCellData *data = new XlsxCellData(result, XlsxCellData::Formula, format);
data->formula = formula;
d->cellTable[row][column] = data;
d->workbook->styles()->addFormat(format);
return error;
}
@ -393,6 +397,8 @@ int Worksheet::writeBlank(int row, int column, Format *format)
return -1;
d->cellTable[row][column] = new XlsxCellData(QVariant(), XlsxCellData::Blank, format);
d->workbook->styles()->addFormat(format);
return 0;
}
@ -403,6 +409,8 @@ int Worksheet::writeBool(int row, int column, bool value, Format *format)
return -1;
d->cellTable[row][column] = new XlsxCellData(value, XlsxCellData::Boolean, format);
d->workbook->styles()->addFormat(format);
return 0;
}
@ -413,6 +421,8 @@ int Worksheet::writeDateTime(int row, int column, const QDateTime &dt, Format *f
return -1;
d->cellTable[row][column] = new XlsxCellData(dt, XlsxCellData::DateTime, format);
d->workbook->styles()->addFormat(format);
return 0;
}
@ -476,6 +486,7 @@ int Worksheet::writeUrl(int row, int column, const QUrl &url, Format *format, co
//Store the hyperlink data in sa separate table
d->urlTable[row][column] = new XlsxUrlData(link_type, urlString, locationString, tip);
d->workbook->styles()->addFormat(format);
return error;
}
@ -825,6 +836,7 @@ bool Worksheet::setRow(int row, double height, Format *format, bool hidden)
} else {
d->rowsInfo[row] = new XlsxRowInfo(height, format, hidden);
}
d->workbook->styles()->addFormat(format);
return true;
}
@ -851,6 +863,8 @@ bool Worksheet::setColumn(int colFirst, int colLast, double width, Format *forma
for (int col=colFirst; col<=colLast; ++col)
d->colsInfoHelper[col] = info;
d->workbook->styles()->addFormat(format);
return true;
}

3
tests/auto/auto.pro

@ -7,4 +7,5 @@ SUBDIRS=\
propscore \
propsapp \
readdocument \
sharedstrings
sharedstrings \
styles

13
tests/auto/styles/styles.pro

@ -0,0 +1,13 @@
QT += testlib xlsx xlsx-private
CONFIG += testcase
DEFINES += XLSX_TEST
TARGET = tst_stylestest
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += tst_stylestest.cpp
DEFINES += SRCDIR=\\\"$$PWD/\\\"

46
tests/auto/styles/tst_stylestest.cpp

@ -0,0 +1,46 @@
#include "private/xlsxstyles_p.h"
#include "xlsxformat.h"
#include <QString>
#include <QtTest>
class StylesTest : public QObject
{
Q_OBJECT
public:
StylesTest();
private Q_SLOTS:
void testEmptyStyle();
void testAddFormat();
};
StylesTest::StylesTest()
{
}
void StylesTest::testEmptyStyle()
{
QXlsx::Styles styles;
QByteArray xmlData = styles.saveToXmlData();
QVERIFY2(xmlData.contains("<cellXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/></cellXfs>"), "Must have one cell style");
}
void StylesTest::testAddFormat()
{
QXlsx::Styles styles;
for (int i=0; i<10; ++i) {
QXlsx::Format *format = styles.createFormat();
format->setFontBold(true);
styles.addFormat(format);
}
QByteArray xmlData = styles.saveToXmlData();
QVERIFY2(xmlData.contains("<cellXfs count=\"2\">"), ""); //Note we have a default one
}
QTEST_APPLESS_MAIN(StylesTest)
#include "tst_stylestest.moc"
Loading…
Cancel
Save