diff --git a/src/xlsx/xlsxformat.cpp b/src/xlsx/xlsxformat.cpp index d3a023f..05e01f6 100755 --- a/src/xlsx/xlsxformat.cpp +++ b/src/xlsx/xlsxformat.cpp @@ -33,6 +33,7 @@ QT_BEGIN_NAMESPACE_XLSX FormatPrivate::FormatPrivate() : dirty(true) , font_dirty(true), font_index_valid(false), font_index(-1) + , fill_dirty(true), fill_index_valid(false), fill_index(-1) , border_dirty(true), border_index_valid(false), border_index(-1) , xf_index(-1), xf_indexValid(false) , is_dxf_fomat(false), dxf_index(-1), dxf_indexValid(false) @@ -42,9 +43,10 @@ FormatPrivate::FormatPrivate() FormatPrivate::FormatPrivate(const FormatPrivate &other) : QSharedData(other) - , alignmentData(other.alignmentData) + , alignmentData(other.alignmentData) ,protectionData(other.protectionData) , dirty(other.dirty), formatKey(other.formatKey) , font_dirty(other.font_dirty), font_index_valid(other.font_index_valid), font_key(other.font_key), font_index(other.font_index) + , fill_dirty(other.fill_dirty), fill_index_valid(other.fill_index_valid), fill_key(other.fill_key), fill_index(other.fill_index) , border_dirty(other.border_dirty), border_index_valid(other.border_index_valid), border_key(other.border_key), border_index(other.border_index) , xf_index(other.xf_index), xf_indexValid(other.xf_indexValid) , is_dxf_fomat(other.is_dxf_fomat), dxf_index(other.dxf_index), dxf_indexValid(other.dxf_indexValid) @@ -745,64 +747,70 @@ QByteArray Format::borderKey() const Format::FillPattern Format::fillPattern() const { - return d->fillData.pattern; + return static_cast(intProperty(FormatPrivate::P_Fill_Pattern)); } void Format::setFillPattern(FillPattern pattern) { - d->fillData.pattern = pattern; - d->fillData._dirty = true; + setProperty(FormatPrivate::P_Fill_Pattern, pattern); } QColor Format::patternForegroundColor() const { - return d->fillData.fgColor; + return colorProperty(FormatPrivate::P_Fill_FgColor); } void Format::setPatternForegroundColor(const QColor &color) { - if (color.isValid() && d->fillData.pattern == PatternNone) - d->fillData.pattern = PatternSolid; - d->fillData.fgColor = color; - d->fillData._dirty = true; + if (color.isValid() && !hasProperty(FormatPrivate::P_Fill_Pattern)) + setFillPattern(PatternSolid); + setProperty(FormatPrivate::P_Fill_FgColor, color); } QColor Format::patternBackgroundColor() const { - return d->fillData.bgColor; + return colorProperty(FormatPrivate::P_Fill_BgColor); } void Format::setPatternBackgroundColor(const QColor &color) { - if (color.isValid() && d->fillData.pattern == PatternNone) - d->fillData.pattern = PatternSolid; - d->fillData.bgColor = color; - d->fillData._dirty = true; + if (color.isValid() && !hasProperty(FormatPrivate::P_Fill_Pattern)) + setFillPattern(PatternSolid); + setProperty(FormatPrivate::P_Fill_BgColor, color); } bool Format::fillIndexValid() const { - return d->fillData.indexValid(); + return d->fill_index_valid; } int Format::fillIndex() const { - return d->fillData.index(); + return d->fill_index; } void Format::setFillIndex(int index) { - d->fillData.setIndex(index); + d->fill_index = index; } /* Internal */ QByteArray Format::fillKey() const { - if (d->fillData._dirty) - d->dirty = true; //Make sure formatKey() will be re-generated. + if (d->fill_dirty) { + QByteArray key; + QDataStream stream(&key, QIODevice::WriteOnly); + for (int i=FormatPrivate::P_Fill_STARTID; iproperty.contains(i)) + stream << i << d->property[i]; + }; - return d->fillData.key(); + const_cast(this)->d->fill_key = key; + const_cast(this)->d->fill_dirty = false; + } + + return d->fill_key; } bool Format::hidden() const @@ -829,7 +837,7 @@ void Format::setLocked(bool locked) QByteArray Format::formatKey() const { - if (d->dirty || d->fillData._dirty) { + if (d->dirty) { QByteArray key; QDataStream stream(&key, QIODevice::WriteOnly); stream<= FormatPrivate::P_Font_STARTID && propertyId < FormatPrivate::P_Font_ENDID) { d->font_dirty = true; d->font_index_valid = false; - } - - if (propertyId >= FormatPrivate::P_Border_STARTID && propertyId < FormatPrivate::P_Border_ENDID) { + } else if (propertyId >= FormatPrivate::P_Border_STARTID && propertyId < FormatPrivate::P_Border_ENDID) { d->border_dirty = true; d->border_index_valid = false; + } else if (propertyId >= FormatPrivate::P_Fill_STARTID && propertyId < FormatPrivate::P_Fill_ENDID) { + d->fill_dirty = true; + d->fill_index_valid = false; } } diff --git a/src/xlsx/xlsxformat_p.h b/src/xlsx/xlsxformat_p.h index 6048bdf..44ade75 100644 --- a/src/xlsx/xlsxformat_p.h +++ b/src/xlsx/xlsxformat_p.h @@ -45,58 +45,6 @@ struct XlsxFormatAlignmentData bool shinkToFit; }; -struct XlsxFormatFillData { - XlsxFormatFillData() : - pattern(Format::PatternNone) - ,_dirty(true), _indexValid(false), _index(-1) - {} - - Format::FillPattern pattern; - QColor bgColor; - QColor fgColor; - QString bgThemeColor; - QString fgThemeColor; - - QByteArray key() const - { - if (_dirty) { - QByteArray key; - QDataStream stream(&key, QIODevice::WriteOnly); - stream<< bgColor << bgThemeColor - << fgColor << fgThemeColor - << pattern; - const_cast(this)->_key = key; - const_cast(this)->_dirty = false; - const_cast(this)->_indexValid = false; - } - return _key; - } - - bool indexValid() const - { - return !_dirty && _indexValid; - } - - int index() const - { - return _index; - } - - void setIndex(int index) - { - _index = index; - _indexValid = true; - } - - //helper member - bool _dirty; //key re-generated and proper index assign is need. - -private: - QByteArray _key; - bool _indexValid; //has a valid index, so no need to assign a new one - int _index; //index in the border list -}; - struct XlsxFormatProtectionData { XlsxFormatProtectionData() : locked(false), hidden(false) @@ -166,7 +114,13 @@ public: P_Border_ENDID, //fill - P_Fill_, + P_Fill_STARTID, + P_Fill_Pattern = P_Fill_STARTID, + P_Fill_BgColor, + P_Fill_FgColor, + P_Fill_BgThemeColor, + P_Fill_FgThemeColor, + P_Fill_ENDID, //alignment P_Alignment_, @@ -180,7 +134,6 @@ public: ~FormatPrivate(); XlsxFormatAlignmentData alignmentData; - XlsxFormatFillData fillData; XlsxFormatProtectionData protectionData; bool dirty; //The key re-generation is need. @@ -191,6 +144,11 @@ public: QByteArray font_key; int font_index; + bool fill_dirty; + bool fill_index_valid; + QByteArray fill_key; + int fill_index; + bool border_dirty; bool border_index_valid; QByteArray border_key; diff --git a/src/xlsx/xlsxstyles.cpp b/src/xlsx/xlsxstyles.cpp index 19cead9..14c456a 100755 --- a/src/xlsx/xlsxstyles.cpp +++ b/src/xlsx/xlsxstyles.cpp @@ -48,10 +48,11 @@ Styles::Styles(bool createEmpty) //Add default Format addFormat(createFormat()); //Add another fill format - QSharedPointer fill = QSharedPointer(new XlsxFormatFillData); - fill->pattern = Format::PatternGray125; - m_fillsList.append(fill); - m_fillsHash[fill->key()] = fill; + Format *format = createFormat(); + format->setFillPattern(Format::PatternGray125); + + m_fillsList.append(format); + m_fillsHash.insert(format->fillKey(), format); } } @@ -162,12 +163,12 @@ void Styles::addFormat(Format *format, bool force) //Fill if (!format->fillIndexValid()) { if (!m_fillsHash.contains(format->fillKey())) { - QSharedPointer fill = QSharedPointer(new XlsxFormatFillData(format->d->fillData)); - fill->setIndex(m_fillsList.size()); //Assign proper index - m_fillsList.append(fill); - m_fillsHash[fill->key()] = fill; + format->setFillIndex(m_fillsList.size()); //Assign proper index + m_fillsList.append(format); + m_fillsHash[format->fillKey()] = format; + } else { + format->setFillIndex(m_fillsHash[format->fillKey()]->fillIndex()); } - format->setFillIndex(m_fillsHash[format->fillKey()]->index()); } //Border @@ -379,13 +380,13 @@ void Styles::writeFills(XmlStreamWriter &writer) writer.writeAttribute(QStringLiteral("count"), QString::number(m_fillsList.size())); for (int i=0; i fill = m_fillsList[i]; - writeFill(writer, fill.data()); + Format *fill = m_fillsList[i]; + writeFill(writer, fill); } writer.writeEndElement(); //fills } -void Styles::writeFill(XmlStreamWriter &writer, XlsxFormatFillData *fill) +void Styles::writeFill(XmlStreamWriter &writer, Format *fill) { static QMap patternStrings; if (patternStrings.isEmpty()) { @@ -412,24 +413,24 @@ void Styles::writeFill(XmlStreamWriter &writer, XlsxFormatFillData *fill) writer.writeStartElement(QStringLiteral("fill")); writer.writeStartElement(QStringLiteral("patternFill")); - writer.writeAttribute(QStringLiteral("patternType"), patternStrings[fill->pattern]); + writer.writeAttribute(QStringLiteral("patternType"), patternStrings[fill->fillPattern()]); // For a solid fill, Excel reverses the role of foreground and background colours - if (fill->fgColor.isValid()) { - writer.writeEmptyElement(fill->pattern == Format::PatternSolid ? QStringLiteral("bgColor") : QStringLiteral("fgColor")); - writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+fill->fgColor.name().mid(1)); - } else if (!fill->fgThemeColor.isEmpty()) { + if (fill->patternForegroundColor().isValid()) { + writer.writeEmptyElement(fill->fillPattern() == Format::PatternSolid ? QStringLiteral("bgColor") : QStringLiteral("fgColor")); + writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+fill->patternForegroundColor().name().mid(1)); + } else if (!fill->stringProperty(FormatPrivate::P_Fill_FgThemeColor).isEmpty()) { writer.writeEmptyElement(QStringLiteral("fgColor")); - QStringList themes = fill->fgThemeColor.split(QLatin1Char(':')); + QStringList themes = fill->stringProperty(FormatPrivate::P_Fill_FgThemeColor).split(QLatin1Char(':')); writer.writeAttribute(QStringLiteral("theme"), themes[0]); if (!themes[1].isEmpty()) writer.writeAttribute(QStringLiteral("tint"), themes[1]); } - if (fill->bgColor.isValid()) { - writer.writeEmptyElement(fill->pattern == Format::PatternSolid ? QStringLiteral("fgColor") : QStringLiteral("bgColor")); - writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+fill->bgColor.name().mid(1)); - } else if (!fill->bgThemeColor.isEmpty()) { + if (fill->patternBackgroundColor().isValid()) { + writer.writeEmptyElement(fill->fillPattern() == Format::PatternSolid ? QStringLiteral("fgColor") : QStringLiteral("bgColor")); + writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+fill->patternBackgroundColor().name().mid(1)); + } else if (!fill->stringProperty(FormatPrivate::P_Fill_BgThemeColor).isEmpty()) { writer.writeEmptyElement(QStringLiteral("bgColor")); - QStringList themes = fill->bgThemeColor.split(QLatin1Char(':')); + QStringList themes = fill->stringProperty(FormatPrivate::P_Fill_BgThemeColor).split(QLatin1Char(':')); writer.writeAttribute(QStringLiteral("theme"), themes[0]); if (!themes[1].isEmpty()) writer.writeAttribute(QStringLiteral("tint"), themes[1]); @@ -724,13 +725,15 @@ bool Styles::readFill(XmlStreamReader &reader) patternValues[QStringLiteral("lightGrid")] = Format::PatternLightGrid; } - QSharedPointer fill(new XlsxFormatFillData); + Format *fill = createFormat(); while((reader.readNextStartElement(), true)) { //read until fill endelement if (reader.tokenType() == QXmlStreamReader::StartElement) { if (reader.name() == QLatin1String("patternFill")) { QXmlStreamAttributes attributes = reader.attributes(); - QString pattern = attributes.value(QLatin1String("patternType")).toString(); - fill->pattern = patternValues.contains(pattern) ? patternValues[pattern] : Format::PatternNone; + if (attributes.hasAttribute(QLatin1String("patternType"))) { + QString pattern = attributes.value(QLatin1String("patternType")).toString(); + fill->setFillPattern(patternValues.contains(pattern) ? patternValues[pattern] : Format::PatternNone); + } } else if (reader.name() == QLatin1String("fgColor")) { QXmlStreamAttributes attributes = reader.attributes(); QColor c; @@ -741,12 +744,12 @@ bool Styles::readFill(XmlStreamReader &reader) } else if (attributes.hasAttribute(QLatin1String("theme"))) { QString theme = attributes.value(QLatin1String("theme")).toString(); QString tint = attributes.value(QLatin1String("tint")).toString(); - fill->fgThemeColor = theme + QLatin1Char(':') + tint; + fill->setProperty(FormatPrivate::P_Fill_FgThemeColor, QString(theme + QLatin1Char(':') + tint)); } - if (fill->pattern == Format::PatternSolid) - fill->bgColor = c; + if (fill->fillPattern() == Format::PatternSolid) + fill->setPatternBackgroundColor(c); else - fill->fgColor = c; + fill->setPatternForegroundColor(c); } else if (reader.name() == QLatin1String("bgColor")) { QXmlStreamAttributes attributes = reader.attributes(); QColor c; @@ -757,12 +760,12 @@ bool Styles::readFill(XmlStreamReader &reader) } else if (attributes.hasAttribute(QLatin1String("theme"))) { QString theme = attributes.value(QLatin1String("theme")).toString(); QString tint = attributes.value(QLatin1String("tint")).toString(); - fill->bgThemeColor = theme + QLatin1Char(':') + tint; + fill->setProperty(FormatPrivate::P_Fill_BgThemeColor, QString(theme + QLatin1Char(':') + tint)); } - if (fill->pattern == Format::PatternSolid) - fill->fgColor = c; + if (fill->fillPattern() == Format::PatternSolid) + fill->setPatternForegroundColor(c); else - fill->bgColor = c; + fill->setPatternBackgroundColor(c); } } @@ -771,8 +774,8 @@ bool Styles::readFill(XmlStreamReader &reader) } m_fillsList.append(fill); - m_fillsHash.insert(fill->key(), fill); - fill->setIndex(m_fillsList.size()-1);//first call key(), then setIndex() + m_fillsHash.insert(fill->fillKey(), fill); + fill->setFillIndex(m_fillsList.size()-1);//first call key(), then setIndex() return true; } @@ -960,7 +963,11 @@ bool Styles::readCellXfs(XmlStreamReader &reader) if (id >= m_fillsList.size()) { qDebug("Error read styles.xml, cellXfs fillId"); } else { - format->d->fillData = *m_fillsList[id]; + Format *fillFormat = m_fillsList[id]; + for (int i=FormatPrivate::P_Fill_STARTID; ihasProperty(i)) + format->setProperty(i, fillFormat->property(i)); + } } } diff --git a/src/xlsx/xlsxstyles_p.h b/src/xlsx/xlsxstyles_p.h index 2492134..e4c9ce4 100755 --- a/src/xlsx/xlsxstyles_p.h +++ b/src/xlsx/xlsxstyles_p.h @@ -40,7 +40,6 @@ class StylesTest; namespace QXlsx { class Format; -struct XlsxFormatFillData; class XmlStreamWriter; class XmlStreamReader; @@ -73,7 +72,7 @@ private: void writeNumFmts(XmlStreamWriter &writer); void writeFonts(XmlStreamWriter &writer); void writeFills(XmlStreamWriter &writer); - void writeFill(XmlStreamWriter &writer, XlsxFormatFillData *fill); + void writeFill(XmlStreamWriter &writer, Format *fill); void writeBorders(XmlStreamWriter &writer); void writeSubBorder(XmlStreamWriter &writer, const QString &type, int style, const QColor &color, const QString &themeColor); void writeCellXfs(XmlStreamWriter &writer); @@ -97,10 +96,10 @@ private: QHash > m_customNumFmtsHash; int m_nextCustomNumFmtId; QList m_fontsList; - QList > m_fillsList; //Keep a copy of unique fills - QList m_bordersList; //Keep a copy of unique borders + QList m_fillsList; + QList m_bordersList; QHash m_fontsHash; - QHash > m_fillsHash; + QHash m_fillsHash; QHash m_bordersHash; QVector m_indexedColors; diff --git a/tests/auto/styles/tst_stylestest.cpp b/tests/auto/styles/tst_stylestest.cpp index 6118984..7777379 100644 --- a/tests/auto/styles/tst_stylestest.cpp +++ b/tests/auto/styles/tst_stylestest.cpp @@ -34,7 +34,6 @@ void StylesTest::testEmptyStyle() { QXlsx::Styles styles; QByteArray xmlData = styles.saveToXmlData(); - qDebug()<"), "Must have one cell style"); } @@ -128,8 +127,8 @@ void StylesTest::testReadFills() styles.readFills(reader); QCOMPARE(styles.m_fillsList.size(), 4); - QCOMPARE(styles.m_fillsList[3]->pattern, QXlsx::Format::PatternSolid); - QCOMPARE(styles.m_fillsList[3]->bgColor, QColor(Qt::gray));//for solid pattern, bg vs. fg color! + QCOMPARE(styles.m_fillsList[3]->fillPattern(), QXlsx::Format::PatternSolid); + QCOMPARE(styles.m_fillsList[3]->patternBackgroundColor(), QColor(Qt::gray));//for solid pattern, bg vs. fg color! } void StylesTest::testReadBorders()