Browse Source

Code refactor: Only create FormatPrivate when needed.

master
Debao Zhang 11 years ago
parent
commit
9c443c996d
  1. 129
      src/xlsx/xlsxformat.cpp
  2. 4
      src/xlsx/xlsxformat.h
  3. 5
      src/xlsx/xlsxformat_p.h
  4. 115
      src/xlsx/xlsxstyles.cpp
  5. 2
      src/xlsx/xlsxstyles_p.h
  6. 5
      tests/auto/document/tst_documenttest.cpp
  7. 3
      tests/auto/styles/tst_stylestest.cpp

129
src/xlsx/xlsxformat.cpp

@ -68,12 +68,11 @@ FormatPrivate::~FormatPrivate()
/*!
* Creates a new format.
* Creates a new invalid format.
*/
Format::Format() :
d(new FormatPrivate)
Format::Format()
{
//The d pointer is initialized with a null pointer
}
/*!
@ -168,7 +167,8 @@ bool Format::isDateTimeFormat() const
}
/*!
* Set a custom num \a format with the given \a id.
\internal
Set a custom num \a format with the given \a id.
*/
void Format::setNumberFormat(int id, const QString &format)
{
@ -176,6 +176,22 @@ void Format::setNumberFormat(int id, const QString &format)
setProperty(FormatPrivate::P_NumFmt_FormatCode, format);
}
/*!
\internal
Return true if the format has number format.
*/
bool Format::hasNumFmtData() const
{
if (!d)
return false;
if (hasProperty(FormatPrivate::P_NumFmt_Id)
|| hasProperty(FormatPrivate::P_NumFmt_FormatCode)) {
return true;
}
return false;
}
/*!
* Return the size of the font in points.
*/
@ -330,9 +346,13 @@ void Format::setFontName(const QString &name)
/*!
* \internal
* When the format has font data, when need to assign a valid index for it.
* The index value is depend on the order <fonts > in styles.xml
*/
bool Format::fontIndexValid() const
{
if (!hasFontData())
return false;
return d->font_index_valid;
}
@ -360,6 +380,9 @@ void Format::setFontIndex(int index)
*/
QByteArray Format::fontKey() const
{
if (isEmpty())
return QByteArray();
if (d->font_dirty) {
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
@ -375,8 +398,15 @@ QByteArray Format::fontKey() const
return d->font_key;
}
/*!
\internal
Return true if the format has font format, otherwise return false.
*/
bool Format::hasFontData() const
{
if (!d)
return false;
for (int i=FormatPrivate::P_Font_STARTID; i<FormatPrivate::P_Font_ENDID; ++i) {
if (hasProperty(i))
return true;
@ -515,6 +545,9 @@ void Format::setShrinkToFit(bool shink)
*/
bool Format::hasAlignmentData() const
{
if (!d)
return false;
for (int i=FormatPrivate::P_Alignment_STARTID; i<FormatPrivate::P_Alignment_ENDID; ++i) {
if (hasProperty(i))
return true;
@ -665,6 +698,8 @@ void Format::setDiagonalBorderColor(const QColor &color)
bool Format::borderIndexValid() const
{
if (!hasBorderData())
return false;
return d->border_index_valid;
}
@ -682,6 +717,9 @@ void Format::setBorderIndex(int index)
*/
QByteArray Format::borderKey() const
{
if (isEmpty())
return QByteArray();
if (d->border_dirty) {
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
@ -697,6 +735,22 @@ QByteArray Format::borderKey() const
return d->border_key;
}
/*!
\internal
Return true if the format has border format, otherwise return false.
*/
bool Format::hasBorderData() const
{
if (!d)
return false;
for (int i=FormatPrivate::P_Border_STARTID; i<FormatPrivate::P_Border_ENDID; ++i) {
if (hasProperty(i))
return true;
}
return false;
}
Format::FillPattern Format::fillPattern() const
{
return static_cast<FillPattern>(intProperty(FormatPrivate::P_Fill_Pattern));
@ -733,11 +787,15 @@ void Format::setPatternBackgroundColor(const QColor &color)
bool Format::fillIndexValid() const
{
if (!hasFillData())
return false;
return d->fill_index_valid;
}
int Format::fillIndex() const
{
if (!d)
return 0;
return d->fill_index;
}
@ -750,6 +808,9 @@ void Format::setFillIndex(int index)
*/
QByteArray Format::fillKey() const
{
if (isEmpty())
return QByteArray();
if (d->fill_dirty) {
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
@ -765,6 +826,22 @@ QByteArray Format::fillKey() const
return d->fill_key;
}
/*!
\internal
Return true if the format has fill format, otherwise return false.
*/
bool Format::hasFillData() const
{
if (!d)
return false;
for (int i=FormatPrivate::P_Fill_STARTID; i<FormatPrivate::P_Fill_ENDID; ++i) {
if (hasProperty(i))
return true;
}
return false;
}
bool Format::hidden() const
{
return boolProperty(FormatPrivate::P_Protection_Hidden);
@ -785,14 +862,24 @@ void Format::setLocked(bool locked)
setProperty(FormatPrivate::P_Protection_Locked, locked);
}
bool Format::hasProtectionData() const
{
if (!d)
return false;
if (hasProperty(FormatPrivate::P_Protection_Hidden)
|| FormatPrivate::P_Protection_Locked) {
return true;
}
return false;
}
/*!
Returns true if the format is valid; otherwise returns false.
*/
bool Format::isValid() const
{
if (!d->property.isEmpty())
return true;
if (d->xf_indexValid || d->font_index_valid || d->fill_index_valid || d->border_index_valid)
if (d)
return true;
return false;
}
@ -802,19 +889,26 @@ bool Format::isValid() const
*/
bool Format::isEmpty() const
{
if (!d)
return true;
return d->property.isEmpty();
}
QByteArray Format::formatKey() const
{
if (isEmpty())
return QByteArray();
if (d->dirty) {
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
stream<<fontKey()<<borderKey()<<fillKey()<<numberFormatIndex();
for (int i=FormatPrivate::P_OTHER_STARTID; i<FormatPrivate::P_OTHER_ENDID; ++i) {
if (d->property.contains(i))
stream<<i<<d->property[i];
QHashIterator<int, QVariant> i(d->property);
while (i.hasNext()) {
i.next();
stream<<i.key()<<i.value();
}
d->formatKey = key;
d->dirty = false;
}
@ -835,6 +929,8 @@ int Format::xfIndex() const
bool Format::xfIndexValid() const
{
if (!d)
return false;
return d->xf_indexValid;
}
@ -851,6 +947,8 @@ int Format::dxfIndex() const
bool Format::dxfIndexValid() const
{
if (!d)
return false;
return d->dxf_indexValid;
}
@ -866,6 +964,8 @@ bool Format::operator !=(const Format &format) const
bool Format::isDxfFormat() const
{
if (!d)
return false;
return d->is_dxf_fomat;
}
@ -889,6 +989,9 @@ QVariant Format::property(int propertyId) const
*/
void Format::setProperty(int propertyId, const QVariant &value)
{
if (!d)
d = new FormatPrivate;
if (value.isValid()) {
if (d->property.contains(propertyId) && d->property[propertyId] == value)
return;
@ -930,6 +1033,8 @@ void Format::clearProperty(int propertyId)
*/
bool Format::hasProperty(int propertyId) const
{
if (!d)
return false;
return d->property.contains(propertyId);
}

4
src/xlsx/xlsxformat.h

@ -243,8 +243,12 @@ private:
void setFontIndex(int index);
QByteArray fontKey() const;
bool hasNumFmtData() const;
bool hasFontData() const;
bool hasFillData() const;
bool hasBorderData() const;
bool hasAlignmentData() const;
bool hasProtectionData() const;
bool borderIndexValid() const;
QByteArray borderKey() const;

5
src/xlsx/xlsxformat_p.h

@ -45,6 +45,8 @@ public:
};
enum Property {
P_STARTID,
//numFmt
P_NumFmt_Id,
P_NumFmt_FormatCode,
@ -98,7 +100,6 @@ public:
P_Fill_FgThemeColor,
P_Fill_ENDID,
P_OTHER_STARTID,
//alignment
P_Alignment_STARTID,
P_Alignment_AlignH = P_Alignment_STARTID,
@ -113,7 +114,7 @@ public:
P_Protection_Locked,
P_Protection_Hidden,
P_OTHER_ENDID
P_ENDID
};
FormatPrivate();

115
src/xlsx/xlsxstyles.cpp

@ -38,11 +38,12 @@ namespace QXlsx {
/*
When loading from existing .xlsx file. we should create a clean styles object.
otherwise, default formats should be added.
*/
Styles::Styles(bool createEmpty)
: m_nextCustomNumFmtId(176), m_emptyFormatAdded(false)
{
//!Fix me. Should the custom num fmt Id starts with 164 or 176 or others??
m_nextCustomNumFmtId = 176;
if (!createEmpty) {
//Add default Format
@ -78,8 +79,15 @@ Format Styles::xfFormat(int idx) const
*/
void Styles::addFormat(const Format &format, bool force)
{
if (format.isEmpty()) {
//Try do something for empty Format.
if (m_emptyFormatAdded)
return;
m_emptyFormatAdded = true;
}
//numFmt
if (format.hasProperty(FormatPrivate::P_NumFmt_FormatCode) && !format.hasProperty(FormatPrivate::P_NumFmt_Id)) {
if (format.hasNumFmtData() && !format.hasProperty(FormatPrivate::P_NumFmt_Id)) {
if (m_builtinNumFmtsHash.isEmpty()) {
m_builtinNumFmtsHash.insert(QStringLiteral("General"), 0);
m_builtinNumFmtsHash.insert(QStringLiteral("0"), 1);
@ -140,60 +148,70 @@ void Styles::addFormat(const Format &format, bool force)
}
//Font
if (!format.fontIndexValid()) {
if (format.hasFontData() && !format.fontIndexValid()) {
//Assign proper font index, if has font data.
if (!m_fontsHash.contains(format.fontKey()))
const_cast<Format *>(&format)->setFontIndex(m_fontsList.size());
else
const_cast<Format *>(&format)->setFontIndex(m_fontsHash[format.fontKey()].fontIndex());
}
if (!m_fontsHash.contains(format.fontKey())) {
const_cast<Format *>(&format)->setFontIndex(m_fontsList.size()); //Assign proper index
//Still a valid font if the format has no fontData. (All font properties are default)
m_fontsList.append(format);
m_fontsHash[format.fontKey()] = format;
} else {
const_cast<Format *>(&format)->setFontIndex(m_fontsHash[format.fontKey()].fontIndex());
}
}
//Fill
if (!format.fillIndexValid()) {
if (format.hasFillData() && !format.fillIndexValid()) {
//Assign proper fill index, if has fill data.
if (!m_fillsHash.contains(format.fillKey()))
const_cast<Format *>(&format)->setFillIndex(m_fillsList.size());
else
const_cast<Format *>(&format)->setFillIndex(m_fillsHash[format.fillKey()].fillIndex());
}
if (!m_fillsHash.contains(format.fillKey())) {
const_cast<Format *>(&format)->setFillIndex(m_fillsList.size()); //Assign proper index
//Still a valid fill if the format has no fillData. (All fill properties are default)
m_fillsList.append(format);
m_fillsHash[format.fillKey()] = format;
} else {
const_cast<Format *>(&format)->setFillIndex(m_fillsHash[format.fillKey()].fillIndex());
}
}
//Border
if (!format.borderIndexValid()) {
if (format.hasBorderData() && !format.borderIndexValid()) {
//Assign proper border index, if has border data.
if (!m_bordersHash.contains(format.borderKey()))
const_cast<Format *>(&format)->setBorderIndex(m_bordersList.size());
else
const_cast<Format *>(&format)->setBorderIndex(m_bordersHash[format.borderKey()].borderIndex());
}
if (!m_bordersHash.contains(format.borderKey())) {
const_cast<Format *>(&format)->setBorderIndex(m_bordersList.size()); //Assign proper index
//Still a valid border if the format has no borderData. (All border properties are default)
m_bordersList.append(format);
m_bordersHash[format.borderKey()] = format;
} else {
const_cast<Format *>(&format)->setBorderIndex(m_bordersHash[format.borderKey()].borderIndex());
}
}
//Format
if (format.isDxfFormat()) {
if (!format.dxfIndexValid()) {
if (!m_dxf_formatsHash.contains(format.formatKey())) {
const_cast<Format *>(&format)->setDxfIndex(m_dxf_formatsList.size());
m_dxf_formatsList.append(format);
m_dxf_formatsHash[format.formatKey()] = format;
} else {
const_cast<Format *>(&format)->setDxfIndex(m_dxf_formatsHash[format.formatKey()].dxfIndex());
}
// if (format.isDxfFormat()) {
// if (!format.dxfIndexValid()) {
// if (!m_dxf_formatsHash.contains(format.formatKey())) {
// const_cast<Format *>(&format)->setDxfIndex(m_dxf_formatsList.size());
// m_dxf_formatsList.append(format);
// m_dxf_formatsHash[format.formatKey()] = format;
// } else {
// const_cast<Format *>(&format)->setDxfIndex(m_dxf_formatsHash[format.formatKey()].dxfIndex());
// }
// }
// } else {
if (!format.isEmpty() && !format.xfIndexValid()) {
if (m_xf_formatsHash.contains(format.formatKey()))
const_cast<Format *>(&format)->setXfIndex(m_xf_formatsHash[format.formatKey()].xfIndex());
else
const_cast<Format *>(&format)->setXfIndex(m_xf_formatsList.size());
}
} else {
if (!format.xfIndexValid()) {
if (!m_xf_formatsHash.contains(format.formatKey()) || force) {
const_cast<Format *>(&format)->setXfIndex(m_xf_formatsList.size());
m_xf_formatsList.append(format);
m_xf_formatsHash[format.formatKey()] = format;
} else {
const_cast<Format *>(&format)->setXfIndex(m_xf_formatsHash[format.formatKey()].xfIndex());
}
}
}
// }
}
QByteArray Styles::saveToXmlData()
@ -512,24 +530,24 @@ void Styles::writeCellXfs(XmlStreamWriter &writer)
writer.writeStartElement(QStringLiteral("cellXfs"));
writer.writeAttribute(QStringLiteral("count"), QString::number(m_xf_formatsList.size()));
foreach (const Format &format, m_xf_formatsList) {
int num_fmt_id = format.numberFormatIndex();
int font_id = format.fontIndex();
int fill_id = format.fillIndex();
int border_id = format.borderIndex();
int xf_id = 0;
writer.writeStartElement(QStringLiteral("xf"));
writer.writeAttribute(QStringLiteral("numFmtId"), QString::number(num_fmt_id));
writer.writeAttribute(QStringLiteral("fontId"), QString::number(font_id));
writer.writeAttribute(QStringLiteral("fillId"), QString::number(fill_id));
writer.writeAttribute(QStringLiteral("borderId"), QString::number(border_id));
if (format.hasNumFmtData())
writer.writeAttribute(QStringLiteral("numFmtId"), QString::number(format.numberFormatIndex()));
if (format.hasFontData())
writer.writeAttribute(QStringLiteral("fontId"), QString::number(format.fontIndex()));
if (format.hasFillData())
writer.writeAttribute(QStringLiteral("fillId"), QString::number(format.fillIndex()));
if (format.hasBorderData())
writer.writeAttribute(QStringLiteral("borderId"), QString::number(format.borderIndex()));
writer.writeAttribute(QStringLiteral("xfId"), QString::number(xf_id));
if (format.numberFormatIndex() > 0)
if (format.hasNumFmtData())
writer.writeAttribute(QStringLiteral("applyNumberFormat"), QStringLiteral("1"));
if (format.fontIndex() > 0)
if (format.hasFontData())
writer.writeAttribute(QStringLiteral("applyFont"), QStringLiteral("1"));
if (format.borderIndex() > 0)
if (format.hasBorderData())
writer.writeAttribute(QStringLiteral("applyBorder"), QStringLiteral("1"));
if (format.fillIndex() > 0)
if (format.hasFillData())
writer.writeAttribute(QStringLiteral("applyFill"), QStringLiteral("1"));
if (format.hasAlignmentData())
writer.writeAttribute(QStringLiteral("applyAlignment"), QStringLiteral("1"));
@ -707,6 +725,7 @@ bool Styles::readFonts(XmlStreamReader &reader)
}
m_fontsList.append(format);
m_fontsHash.insert(format.fontKey(), format);
if (format.isValid())
format.setFontIndex(m_fontsList.size()-1);
}
return true;
@ -804,7 +823,8 @@ bool Styles::readFill(XmlStreamReader &reader)
m_fillsList.append(fill);
m_fillsHash.insert(fill.fillKey(), fill);
fill.setFillIndex(m_fillsList.size()-1);//first call key(), then setIndex()
if (fill.isValid())
fill.setFillIndex(m_fillsList.size()-1);
return true;
}
@ -889,7 +909,8 @@ bool Styles::readBorder(XmlStreamReader &reader)
m_bordersList.append(border);
m_bordersHash.insert(border.borderKey(), border);
border.setBorderIndex(m_bordersList.size()-1);//first call key(), then setIndex()
if (border.isValid())
border.setBorderIndex(m_bordersList.size()-1);
return true;
}

2
src/xlsx/xlsxstyles_p.h

@ -108,6 +108,8 @@ private:
QList<Format> m_dxf_formatsList;
QHash<QByteArray, Format> m_dxf_formatsHash;
bool m_emptyFormatAdded;
};
}

5
tests/auto/document/tst_documenttest.cpp

@ -58,7 +58,10 @@ void DocumentTest::testReadWriteString()
QCOMPARE(xlsx2.cellAt("A2")->dataType(), Cell::String);
QCOMPARE(xlsx2.cellAt("A2")->value().toString(), QString("Hello Qt again!"));
QVERIFY(xlsx2.cellAt("A2")->format().isValid());
QCOMPARE(xlsx2.cellAt("A2")->format(), format);
QCOMPARE(xlsx2.cellAt("A2")->format().fontColor(), format.fontColor());
QCOMPARE(xlsx2.cellAt("A2")->format().leftBorderStyle(), format.leftBorderStyle());
QCOMPARE(xlsx2.cellAt("A2")->format().fillPattern(), format.fillPattern());
// QCOMPARE(xlsx2.cellAt("A2")->format(), format);
QFile::remove("test.xlsx");
}

3
tests/auto/styles/tst_stylestest.cpp

@ -35,7 +35,8 @@ 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");
// QVERIFY2(xmlData.contains("<cellXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/></cellXfs>"), "Must have one cell style");
QVERIFY2(xmlData.contains("<cellXfs count=\"1\"><xf xfId=\"0\"/></cellXfs>"), "Must have one cell style");
}
void StylesTest::testAddFormat()

Loading…
Cancel
Save