Add Fill & Border Style control for cell
This commit is contained in:
+379
-23
@@ -23,11 +23,18 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
#include "xlsxformat.h"
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
|
||||
namespace QXlsx {
|
||||
|
||||
QList<Format *> Format::s_xfFormats;
|
||||
QList<Format *> Format::s_dxfFormats;
|
||||
|
||||
Format::Format()
|
||||
{
|
||||
m_number.formatIndex = 0;
|
||||
|
||||
m_font.bold = false;
|
||||
m_font.color = QColor(Qt::black);
|
||||
m_font.italic = false;
|
||||
@@ -43,8 +50,9 @@ Format::Format()
|
||||
m_font.charset = 0;
|
||||
m_font.condense = 0;
|
||||
m_font.extend = 0;
|
||||
m_font.redundant = false;
|
||||
m_font.index = 0;
|
||||
m_font._dirty = true;
|
||||
m_font._redundant = false;
|
||||
m_font._index = -1;
|
||||
|
||||
m_alignment.alignH = AlignHGeneral;
|
||||
m_alignment.alignV = AlignBottom;
|
||||
@@ -53,20 +61,50 @@ Format::Format()
|
||||
m_alignment.indent = 0;
|
||||
m_alignment.shinkToFit = false;
|
||||
|
||||
m_border.left = BorderNone;
|
||||
m_border.right = BorderNone;
|
||||
m_border.top = BorderNone;
|
||||
m_border.bottom = BorderNone;
|
||||
m_border.diagonal = BorderNone;
|
||||
m_border.diagonalType = DiagonalBorderNone;
|
||||
m_border.leftColor = QColor();
|
||||
m_border.rightColor = QColor();
|
||||
m_border.topColor = QColor();
|
||||
m_border.bottomColor = QColor();
|
||||
m_border.diagonalColor = QColor();
|
||||
m_border._dirty = true;
|
||||
m_border._redundant = false;
|
||||
m_border._index = -1;
|
||||
|
||||
m_fill.pattern = PatternNone;
|
||||
m_fill.bgColor = QColor();
|
||||
m_fill.fgColor = QColor();
|
||||
m_fill._dirty = true;
|
||||
m_fill._redundant = false;
|
||||
m_fill._index = -1;
|
||||
|
||||
m_protection.locked = false;
|
||||
m_protection.hidden = false;
|
||||
|
||||
m_dirty = true;
|
||||
|
||||
m_is_dxf_fomat = false;
|
||||
m_xf_index = -1;
|
||||
m_dxf_index = -1;
|
||||
|
||||
m_xf_index = 0;
|
||||
m_dxf_index = 0;
|
||||
|
||||
m_num_format_index = 0;
|
||||
m_theme = 0;
|
||||
m_color_indexed = 0;
|
||||
}
|
||||
|
||||
m_has_fill = false;
|
||||
m_fill_index = 0;
|
||||
int Format::numberFormat() const
|
||||
{
|
||||
return m_number.formatIndex;
|
||||
}
|
||||
|
||||
m_has_borders = false;
|
||||
m_border_index = false;
|
||||
void Format::setNumberFormat(int format)
|
||||
{
|
||||
m_dirty = true;
|
||||
m_number.formatIndex = format;
|
||||
}
|
||||
|
||||
int Format::fontSize() const
|
||||
@@ -77,6 +115,7 @@ int Format::fontSize() const
|
||||
void Format::setFontSize(int size)
|
||||
{
|
||||
m_font.size = size;
|
||||
m_font._dirty = true;
|
||||
}
|
||||
|
||||
bool Format::fontItalic() const
|
||||
@@ -87,6 +126,7 @@ bool Format::fontItalic() const
|
||||
void Format::setFontItalic(bool italic)
|
||||
{
|
||||
m_font.italic = italic;
|
||||
m_font._dirty = true;
|
||||
}
|
||||
|
||||
bool Format::fontStrikeOut() const
|
||||
@@ -94,9 +134,10 @@ bool Format::fontStrikeOut() const
|
||||
return m_font.strikeOut;
|
||||
}
|
||||
|
||||
void Format::setFontStricOut(bool stricOut)
|
||||
void Format::setFontStrikeOut(bool strikeOut)
|
||||
{
|
||||
m_font.strikeOut = stricOut;
|
||||
m_font.strikeOut = strikeOut;
|
||||
m_font._dirty = true;
|
||||
}
|
||||
|
||||
QColor Format::fontColor() const
|
||||
@@ -107,6 +148,7 @@ QColor Format::fontColor() const
|
||||
void Format::setFontColor(const QColor &color)
|
||||
{
|
||||
m_font.color = color;
|
||||
m_font._dirty = true;
|
||||
}
|
||||
|
||||
bool Format::fontBold() const
|
||||
@@ -117,6 +159,7 @@ bool Format::fontBold() const
|
||||
void Format::setFontBold(bool bold)
|
||||
{
|
||||
m_font.bold = bold;
|
||||
m_font._dirty = true;
|
||||
}
|
||||
|
||||
Format::FontScript Format::fontScript() const
|
||||
@@ -127,6 +170,7 @@ Format::FontScript Format::fontScript() const
|
||||
void Format::setFontScript(FontScript script)
|
||||
{
|
||||
m_font.scirpt = script;
|
||||
m_font._dirty = true;
|
||||
}
|
||||
|
||||
Format::FontUnderline Format::fontUnderline() const
|
||||
@@ -137,6 +181,7 @@ Format::FontUnderline Format::fontUnderline() const
|
||||
void Format::setFontUnderline(FontUnderline underline)
|
||||
{
|
||||
m_font.underline = underline;
|
||||
m_font._dirty = true;
|
||||
}
|
||||
|
||||
bool Format::fontOutline() const
|
||||
@@ -147,6 +192,7 @@ bool Format::fontOutline() const
|
||||
void Format::setFontOutline(bool outline)
|
||||
{
|
||||
m_font.outline = outline;
|
||||
m_font._dirty = true;
|
||||
}
|
||||
|
||||
QString Format::fontName() const
|
||||
@@ -157,6 +203,27 @@ QString Format::fontName() const
|
||||
void Format::setFontName(const QString &name)
|
||||
{
|
||||
m_font.name = name;
|
||||
m_font._dirty = true;
|
||||
}
|
||||
|
||||
/* Internal
|
||||
*/
|
||||
QByteArray Format::fontKey() const
|
||||
{
|
||||
if (m_font._dirty) {
|
||||
QByteArray key;
|
||||
QDataStream stream(&key, QIODevice::WriteOnly);
|
||||
stream<<m_font.bold<<m_font.charset<<m_font.color<<m_font.condense
|
||||
<<m_font.extend<<m_font.family<<m_font.italic<<m_font.name
|
||||
<<m_font.outline<<m_font.scheme<<m_font.scirpt<<m_font.shadow
|
||||
<<m_font.size<<m_font.strikeOut<<m_font.underline;
|
||||
|
||||
const_cast<Format*>(this)->m_font._key = key;
|
||||
const_cast<Format*>(this)->m_font._dirty = false;
|
||||
const_cast<Format*>(this)->m_dirty = true; //Make sure formatKey() will be re-generated.
|
||||
}
|
||||
|
||||
return m_font._key;
|
||||
}
|
||||
|
||||
Format::HorizontalAlignment Format::horizontalAlignment() const
|
||||
@@ -177,6 +244,7 @@ void Format::setHorizontalAlignment(HorizontalAlignment align)
|
||||
}
|
||||
|
||||
m_alignment.alignH = align;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
Format::VerticalAlignment Format::verticalAlignment() const
|
||||
@@ -187,6 +255,7 @@ Format::VerticalAlignment Format::verticalAlignment() const
|
||||
void Format::setVerticalAlignment(VerticalAlignment align)
|
||||
{
|
||||
m_alignment.alignV = align;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
bool Format::textWrap() const
|
||||
@@ -200,6 +269,7 @@ void Format::setTextWarp(bool wrap)
|
||||
m_alignment.shinkToFit = false;
|
||||
|
||||
m_alignment.wrap = wrap;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
int Format::rotation() const
|
||||
@@ -210,6 +280,7 @@ int Format::rotation() const
|
||||
void Format::setRotation(int rotation)
|
||||
{
|
||||
m_alignment.rotation = rotation;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
int Format::indent() const
|
||||
@@ -226,6 +297,7 @@ void Format::setIndent(int indent)
|
||||
m_alignment.alignH = AlignLeft;
|
||||
}
|
||||
m_alignment.indent = indent;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
bool Format::shrinkToFit() const
|
||||
@@ -244,6 +316,7 @@ void Format::setShrinkToFit(bool shink)
|
||||
}
|
||||
|
||||
m_alignment.shinkToFit = shink;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
bool Format::alignmentChanged() const
|
||||
@@ -309,20 +382,303 @@ QString Format::verticalAlignmentString() const
|
||||
return align;
|
||||
}
|
||||
|
||||
void Format::setBorderStyle(BorderStyle style)
|
||||
{
|
||||
setLeftBorderStyle(style);
|
||||
setRightBorderStyle(style);
|
||||
setBottomBorderStyle(style);
|
||||
setTopBorderStyle(style);
|
||||
}
|
||||
|
||||
void Format::setBorderColor(const QColor &color)
|
||||
{
|
||||
setLeftBorderColor(color);
|
||||
setRightBorderColor(color);
|
||||
setTopBorderColor(color);
|
||||
setBottomBorderColor(color);
|
||||
}
|
||||
|
||||
Format::BorderStyle Format::leftBorderStyle() const
|
||||
{
|
||||
return m_border.left;
|
||||
}
|
||||
|
||||
void Format::setLeftBorderStyle(BorderStyle style)
|
||||
{
|
||||
m_border.left = style;
|
||||
m_border._dirty = true;
|
||||
}
|
||||
|
||||
QColor Format::leftBorderColor() const
|
||||
{
|
||||
return m_border.leftColor;
|
||||
}
|
||||
|
||||
void Format::setLeftBorderColor(const QColor &color)
|
||||
{
|
||||
m_border.leftColor = color;
|
||||
m_border._dirty = true;
|
||||
}
|
||||
|
||||
Format::BorderStyle Format::rightBorderStyle() const
|
||||
{
|
||||
return m_border.right;
|
||||
}
|
||||
|
||||
void Format::setRightBorderStyle(BorderStyle style)
|
||||
{
|
||||
m_border.right = style;
|
||||
m_border._dirty = true;
|
||||
}
|
||||
|
||||
QColor Format::rightBorderColor() const
|
||||
{
|
||||
return m_border.rightColor;
|
||||
}
|
||||
|
||||
void Format::setRightBorderColor(const QColor &color)
|
||||
{
|
||||
m_border.rightColor = color;
|
||||
m_border._dirty = true;
|
||||
}
|
||||
|
||||
Format::BorderStyle Format::topBorderStyle() const
|
||||
{
|
||||
return m_border.top;
|
||||
}
|
||||
|
||||
void Format::setTopBorderStyle(BorderStyle style)
|
||||
{
|
||||
m_border.top = style;
|
||||
m_border._dirty = true;
|
||||
}
|
||||
|
||||
QColor Format::topBorderColor() const
|
||||
{
|
||||
return m_border.topColor;
|
||||
}
|
||||
|
||||
void Format::setTopBorderColor(const QColor &color)
|
||||
{
|
||||
m_border.topColor = color;
|
||||
m_border._dirty = true;
|
||||
}
|
||||
|
||||
Format::BorderStyle Format::bottomBorderStyle() const
|
||||
{
|
||||
return m_border.bottom;
|
||||
}
|
||||
|
||||
void Format::setBottomBorderStyle(BorderStyle style)
|
||||
{
|
||||
m_border.bottom = style;
|
||||
m_border._dirty = true;
|
||||
}
|
||||
|
||||
QColor Format::bottomBorderColor() const
|
||||
{
|
||||
return m_border.bottomColor;
|
||||
}
|
||||
|
||||
void Format::setBottomBorderColor(const QColor &color)
|
||||
{
|
||||
m_border.bottomColor = color;
|
||||
m_border._dirty = true;
|
||||
}
|
||||
|
||||
Format::BorderStyle Format::diagonalBorderStyle() const
|
||||
{
|
||||
return m_border.diagonal;
|
||||
}
|
||||
|
||||
void Format::setDiagonalBorderStyle(BorderStyle style)
|
||||
{
|
||||
m_border.diagonal = style;
|
||||
m_border._dirty = true;
|
||||
}
|
||||
|
||||
Format::DiagonalBorderType Format::diagonalBorderType() const
|
||||
{
|
||||
return m_border.diagonalType;
|
||||
}
|
||||
|
||||
void Format::setDiagonalBorderType(DiagonalBorderType style)
|
||||
{
|
||||
m_border.diagonalType = style;
|
||||
m_border._dirty = true;
|
||||
}
|
||||
|
||||
QColor Format::diagonalBorderColor() const
|
||||
{
|
||||
return m_border.diagonalColor;
|
||||
}
|
||||
|
||||
void Format::setDiagonalBorderColor(const QColor &color)
|
||||
{
|
||||
m_border.diagonalColor = color;
|
||||
m_border._dirty = true;
|
||||
}
|
||||
|
||||
|
||||
/* Internal
|
||||
*/
|
||||
QByteArray Format::borderKey() const
|
||||
{
|
||||
if (m_border._dirty) {
|
||||
QByteArray key;
|
||||
QDataStream stream(&key, QIODevice::WriteOnly);
|
||||
stream<<m_border.bottom<<m_border.bottomColor
|
||||
<<m_border.diagonal<<m_border.diagonalColor<<m_border.diagonalType
|
||||
<<m_border.left<<m_border.leftColor
|
||||
<<m_border.right<<m_border.rightColor
|
||||
<<m_border.top<<m_border.topColor;
|
||||
const_cast<Format*>(this)->m_border._key = key;
|
||||
const_cast<Format*>(this)->m_border._dirty = false;
|
||||
const_cast<Format*>(this)->m_dirty = true; //Make sure formatKey() will be re-generated.
|
||||
}
|
||||
|
||||
return m_border._key;
|
||||
}
|
||||
|
||||
Format::FillPattern Format::fillPattern() const
|
||||
{
|
||||
return m_fill.pattern;
|
||||
}
|
||||
|
||||
void Format::setFillPattern(FillPattern pattern)
|
||||
{
|
||||
m_fill.pattern = pattern;
|
||||
m_fill._dirty = true;
|
||||
}
|
||||
|
||||
QColor Format::patternForegroundColor() const
|
||||
{
|
||||
return m_fill.fgColor;
|
||||
}
|
||||
|
||||
void Format::setPatternForegroundColor(const QColor &color)
|
||||
{
|
||||
if (color.isValid() && m_fill.pattern == PatternNone)
|
||||
m_fill.pattern = PatternSolid;
|
||||
m_fill.fgColor = color;
|
||||
m_fill._dirty = true;
|
||||
}
|
||||
|
||||
QColor Format::patternBackgroundColor() const
|
||||
{
|
||||
return m_fill.bgColor;
|
||||
}
|
||||
|
||||
void Format::setPatternBackgroundColor(const QColor &color)
|
||||
{
|
||||
if (color.isValid() && m_fill.pattern == PatternNone)
|
||||
m_fill.pattern = PatternSolid;
|
||||
m_fill.bgColor = color;
|
||||
m_fill._dirty = true;
|
||||
}
|
||||
|
||||
/* Internal
|
||||
*/
|
||||
QByteArray Format::fillKey() const
|
||||
{
|
||||
if (m_fill._dirty) {
|
||||
QByteArray key;
|
||||
QDataStream stream(&key, QIODevice::WriteOnly);
|
||||
stream<<m_fill.bgColor<<m_fill.fgColor<<m_fill.pattern;
|
||||
const_cast<Format*>(this)->m_fill._key = key;
|
||||
const_cast<Format*>(this)->m_fill._dirty = false;
|
||||
const_cast<Format*>(this)->m_dirty = true; //Make sure formatKey() will be re-generated.
|
||||
}
|
||||
|
||||
return m_fill._key;
|
||||
}
|
||||
|
||||
bool Format::hidden() const
|
||||
{
|
||||
return m_protection.hidden;
|
||||
}
|
||||
|
||||
void Format::setHidden(bool hidden)
|
||||
{
|
||||
m_protection.hidden = hidden;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
bool Format::locked() const
|
||||
{
|
||||
return m_protection.locked;
|
||||
}
|
||||
|
||||
void Format::setLocked(bool locked)
|
||||
{
|
||||
m_protection.locked = locked;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
QByteArray Format::formatKey() const
|
||||
{
|
||||
if (m_dirty || m_font._dirty || m_border._dirty || m_fill._dirty) {
|
||||
QByteArray key;
|
||||
QDataStream stream(&key, QIODevice::WriteOnly);
|
||||
stream<<fontKey()<<borderKey()<<fillKey()
|
||||
<<m_number.formatIndex
|
||||
<<m_alignment.alignH<<m_alignment.alignV<<m_alignment.indent
|
||||
<<m_alignment.rotation<<m_alignment.shinkToFit<<m_alignment.wrap
|
||||
<<m_protection.hidden<<m_protection.locked;
|
||||
const_cast<Format*>(this)->m_formatKey = key;
|
||||
const_cast<Format*>(this)->m_dirty = false;
|
||||
}
|
||||
|
||||
return m_formatKey;
|
||||
}
|
||||
|
||||
bool Format::operator ==(const Format &format) const
|
||||
{
|
||||
return this->formatKey() == format.formatKey();
|
||||
}
|
||||
|
||||
bool Format::operator !=(const Format &format) const
|
||||
{
|
||||
return this->formatKey() != format.formatKey();
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
if (m_xf_index == -1 && generateIfNotValid) { //Generate a valid xf_index for this format
|
||||
int index = -1;
|
||||
for (int i=0; i<s_xfFormats.size(); ++i) {
|
||||
if (*s_xfFormats[i] == *this) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index != -1) {
|
||||
m_xf_index = index;
|
||||
} else {
|
||||
m_xf_index = s_xfFormats.size();
|
||||
s_xfFormats.append(this);
|
||||
}
|
||||
}
|
||||
return m_xf_index;
|
||||
}
|
||||
|
||||
void Format::clearExtraInfos()
|
||||
{
|
||||
m_xf_index = -1;
|
||||
m_dxf_index = -1;
|
||||
s_xfFormats.clear();
|
||||
s_dxfFormats.clear();
|
||||
}
|
||||
|
||||
bool Format::isDxfFormat() const
|
||||
{
|
||||
return m_is_dxf_fomat;
|
||||
}
|
||||
|
||||
|
||||
void Format::setForegroundColor(const QColor &color)
|
||||
{
|
||||
m_fg_color = color;
|
||||
}
|
||||
|
||||
void Format::setBackgroundColor(const QColor &color)
|
||||
{
|
||||
m_bg_color = color;
|
||||
}
|
||||
|
||||
} // namespace QXlsx
|
||||
|
||||
+171
-44
@@ -27,6 +27,8 @@
|
||||
|
||||
#include <QFont>
|
||||
#include <QColor>
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
|
||||
namespace QXlsx {
|
||||
|
||||
@@ -73,12 +75,63 @@ public:
|
||||
AlignVDistributed
|
||||
};
|
||||
|
||||
enum BorderStyle
|
||||
{
|
||||
BorderNone,
|
||||
BorderThin,
|
||||
BorderMedium,
|
||||
BorderDashed,
|
||||
BorderDotted,
|
||||
BorderThick,
|
||||
BorderDouble,
|
||||
BorderHair,
|
||||
BorderMediumDashed,
|
||||
BorderDashDot,
|
||||
BorderMediumDashDot,
|
||||
BorderDashDotDot,
|
||||
BorderMediumDashDotDot,
|
||||
BorderSlantDashDot
|
||||
};
|
||||
|
||||
enum DiagonalBorderType
|
||||
{
|
||||
DiagonalBorderNone,
|
||||
DiagonalBorderDown,
|
||||
DiagonalBorderUp,
|
||||
DiagnoalBorderBoth
|
||||
};
|
||||
|
||||
enum FillPattern
|
||||
{
|
||||
PatternNone,
|
||||
PatternSolid,
|
||||
PatternMediumGray,
|
||||
PatternDarkGray,
|
||||
PatternLightGray,
|
||||
PatternDarkHorizontal,
|
||||
PatternDarkVertical,
|
||||
PatternDarkDown,
|
||||
PatternDarkUp,
|
||||
PatternDarkGrid,
|
||||
PatternDarkTrellis,
|
||||
PatternLightHorizontal,
|
||||
PatternLightVertical,
|
||||
PatternLightDown,
|
||||
PatternLightUp,
|
||||
PatternLightTrellis,
|
||||
PatternGray125,
|
||||
PatternGray0625
|
||||
};
|
||||
|
||||
int numberFormat() const;
|
||||
void setNumberFormat(int format);
|
||||
|
||||
int fontSize() const;
|
||||
void setFontSize(int size);
|
||||
bool fontItalic() const;
|
||||
void setFontItalic(bool italic);
|
||||
bool fontStrikeOut() const;
|
||||
void setFontStricOut(bool);
|
||||
void setFontStrikeOut(bool);
|
||||
QColor fontColor() const;
|
||||
void setFontColor(const QColor &);
|
||||
bool fontBold() const;
|
||||
@@ -105,14 +158,56 @@ public:
|
||||
bool shrinkToFit() const;
|
||||
void setShrinkToFit(bool shink);
|
||||
|
||||
void setForegroundColor(const QColor &color);
|
||||
void setBackgroundColor(const QColor &color);
|
||||
void setBorderStyle(BorderStyle style);
|
||||
void setBorderColor(const QColor &color);
|
||||
BorderStyle leftBorderStyle() const;
|
||||
void setLeftBorderStyle(BorderStyle style);
|
||||
QColor leftBorderColor() const;
|
||||
void setLeftBorderColor(const QColor &color);
|
||||
BorderStyle rightBorderStyle() const;
|
||||
void setRightBorderStyle(BorderStyle style);
|
||||
QColor rightBorderColor() const;
|
||||
void setRightBorderColor(const QColor &color);
|
||||
BorderStyle topBorderStyle() const;
|
||||
void setTopBorderStyle(BorderStyle style);
|
||||
QColor topBorderColor() const;
|
||||
void setTopBorderColor(const QColor &color);
|
||||
BorderStyle bottomBorderStyle() const;
|
||||
void setBottomBorderStyle(BorderStyle style);
|
||||
QColor bottomBorderColor() const;
|
||||
void setBottomBorderColor(const QColor &color);
|
||||
BorderStyle diagonalBorderStyle() const;
|
||||
void setDiagonalBorderStyle(BorderStyle style);
|
||||
DiagonalBorderType diagonalBorderType() const;
|
||||
void setDiagonalBorderType(DiagonalBorderType style);
|
||||
QColor diagonalBorderColor() const;
|
||||
void setDiagonalBorderColor(const QColor &color);
|
||||
|
||||
FillPattern fillPattern() const;
|
||||
void setFillPattern(FillPattern pattern);
|
||||
QColor patternForegroundColor() const;
|
||||
void setPatternForegroundColor(const QColor &color);
|
||||
QColor patternBackgroundColor() const;
|
||||
void setPatternBackgroundColor(const QColor &color);
|
||||
|
||||
bool locked() const;
|
||||
void setLocked(bool locked);
|
||||
bool hidden() const;
|
||||
void setHidden(bool hidden);
|
||||
|
||||
bool operator == (const Format &format) const;
|
||||
bool operator != (const Format &format) const;
|
||||
|
||||
private:
|
||||
friend class Styles;
|
||||
friend class Worksheet;
|
||||
Format();
|
||||
|
||||
struct NumberData
|
||||
{
|
||||
int formatIndex;
|
||||
} m_number;
|
||||
|
||||
struct FontData
|
||||
{
|
||||
int size;
|
||||
@@ -132,13 +227,16 @@ private:
|
||||
int extend;
|
||||
|
||||
//helper member
|
||||
bool redundant; //same with the fonts used by some other Formats
|
||||
int index; //index in the Font list
|
||||
bool _dirty; //key re-generated is need.
|
||||
QByteArray _key;
|
||||
bool _redundant; //same font already used by some other Formats
|
||||
int _index; //index in the Font list
|
||||
} m_font;
|
||||
|
||||
bool hasFont() const {return !m_font.redundant;}
|
||||
int fontIndex() const {return m_font.index;}
|
||||
void setFontIndex(int index) {m_font.index = index;}
|
||||
bool hasFont() const {return !m_font._redundant;}
|
||||
void setFontRedundant(bool redundant) {m_font._redundant = redundant;}
|
||||
int fontIndex() const {return m_font._index;}
|
||||
void setFontIndex(int index) {m_font._index = index;}
|
||||
QByteArray fontKey() const;
|
||||
int fontFamily() const{return m_font.family;}
|
||||
bool fontShadow() const {return m_font.shadow;}
|
||||
QString fontScheme() const {return m_font.scheme;}
|
||||
@@ -157,46 +255,75 @@ private:
|
||||
QString horizontalAlignmentString() const;
|
||||
QString verticalAlignmentString() const;
|
||||
|
||||
struct BorderData
|
||||
{
|
||||
BorderStyle left;
|
||||
BorderStyle right;
|
||||
BorderStyle top;
|
||||
BorderStyle bottom;
|
||||
BorderStyle diagonal;
|
||||
QColor leftColor;
|
||||
QColor rightColor;
|
||||
QColor topColor;
|
||||
QColor bottomColor;
|
||||
QColor diagonalColor;
|
||||
DiagonalBorderType diagonalType;
|
||||
|
||||
//helper member
|
||||
bool _dirty; //key re-generated is need.
|
||||
QByteArray _key;
|
||||
bool _redundant; //same border already used by some other Formats
|
||||
int _index; //index in the border list
|
||||
} m_border;
|
||||
|
||||
QByteArray borderKey() const;
|
||||
bool hasBorders() const {return !m_border._redundant;}
|
||||
void setBorderRedundant(bool redundant) {m_border._redundant = redundant;}
|
||||
int borderIndex() const {return m_border._index;}
|
||||
void setBorderIndex(int index) {m_border._index = index;}
|
||||
|
||||
struct FillData {
|
||||
FillPattern pattern;
|
||||
QColor bgColor;
|
||||
QColor fgColor;
|
||||
|
||||
//helper member
|
||||
bool _dirty; //key re-generated is need.
|
||||
QByteArray _key;
|
||||
bool _redundant; //same border already used by some other Formats
|
||||
int _index; //index in the border list
|
||||
} m_fill;
|
||||
|
||||
QByteArray fillKey() const;
|
||||
bool hasFill() const {return !m_fill._redundant;}
|
||||
void setFillRedundant(bool redundant) {m_fill._redundant = redundant;}
|
||||
int fillIndex() const {return m_fill._index;}
|
||||
void setFillIndex(int index) {m_fill._index = index;}
|
||||
|
||||
struct ProtectionData {
|
||||
bool locked;
|
||||
bool hidden;
|
||||
} m_protection;
|
||||
|
||||
bool m_dirty; //The key re-generation is need.
|
||||
QByteArray m_formatKey;
|
||||
QByteArray formatKey() const;
|
||||
|
||||
static QList<Format *> s_xfFormats;
|
||||
int m_xf_index;
|
||||
int xfIndex(bool generateIfNotValid=true); //Generate index when first called.
|
||||
void clearExtraInfos();
|
||||
|
||||
bool m_is_dxf_fomat;
|
||||
int m_dxf_index;
|
||||
static QList<Format *> s_dxfFormats;
|
||||
bool isDxfFormat() const;
|
||||
int xfIndex() const {return m_xf_index;}
|
||||
void setXfIndex(int index) {m_xf_index = index; m_font.index=index;}
|
||||
|
||||
//num
|
||||
int numFormatIndex() const {return m_num_format_index;}
|
||||
|
||||
int m_theme;
|
||||
int m_color_indexed;
|
||||
int theme() const {return m_theme;}
|
||||
int colorIndexed() const {return m_color_indexed;}
|
||||
|
||||
//fills
|
||||
bool hasFill() const {return m_has_fill;}
|
||||
int fillIndex() const {return m_fill_index;}
|
||||
|
||||
//borders
|
||||
bool hasBorders() const {return m_has_borders;}
|
||||
void setHasBorder(bool has) {m_has_borders=has;}
|
||||
int borderIndex() const {return m_border_index;}
|
||||
|
||||
bool m_is_dxf_fomat;
|
||||
|
||||
int m_xf_index;
|
||||
int m_dxf_index;
|
||||
|
||||
int m_num_format_index;
|
||||
|
||||
bool m_has_font;
|
||||
int m_font_index;
|
||||
int m_font_family;
|
||||
QString m_font_scheme;
|
||||
QColor m_bg_color;
|
||||
QColor m_fg_color;
|
||||
int m_theme;
|
||||
int m_color_indexed;
|
||||
|
||||
bool m_has_fill;
|
||||
int m_fill_index;
|
||||
|
||||
bool m_has_borders;
|
||||
int m_border_index;
|
||||
};
|
||||
|
||||
} // namespace QXlsx
|
||||
|
||||
@@ -89,6 +89,7 @@ bool Package::createPackage(const QString &packageName)
|
||||
{
|
||||
ZipWriter zipWriter(packageName);
|
||||
|
||||
m_workbook->styles()->clearExtraFormatInfo(); //These info will be generated when write the worksheet data.
|
||||
writeWorksheetFiles(zipWriter);
|
||||
// writeChartsheetFiles(zipWriter);
|
||||
writeWorkbookFile(zipWriter);
|
||||
@@ -100,6 +101,7 @@ bool Package::createPackage(const QString &packageName)
|
||||
writeSharedStringsFile(zipWriter);
|
||||
writeDocPropsFiles(zipWriter);
|
||||
writeContentTypesFiles(zipWriter);
|
||||
m_workbook->styles()->prepareStyles();
|
||||
writeStylesFiles(zipWriter);
|
||||
writeThemeFile(zipWriter);
|
||||
writeRootRelsFile(zipWriter);
|
||||
|
||||
+185
-18
@@ -26,6 +26,9 @@
|
||||
#include "xlsxformat.h"
|
||||
#include "xmlstreamwriter_p.h"
|
||||
#include <QFile>
|
||||
#include <QMap>
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
|
||||
namespace QXlsx {
|
||||
|
||||
@@ -34,29 +37,106 @@ Styles::Styles(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_fill_count = 2; //Starts from 2
|
||||
m_borders_count = 1;
|
||||
m_borders_count = 0;
|
||||
m_font_count = 0;
|
||||
}
|
||||
|
||||
//Add the default cell format
|
||||
Format *format = addFormat();
|
||||
format->setHasBorder(true);
|
||||
Styles::~Styles()
|
||||
{
|
||||
qDeleteAll(m_formats);
|
||||
}
|
||||
|
||||
Format *Styles::addFormat()
|
||||
{
|
||||
Format *format = new Format();
|
||||
format->setXfIndex(m_formats.size());
|
||||
m_font_count += 1;
|
||||
|
||||
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()
|
||||
{
|
||||
m_xf_formats = Format::s_xfFormats;
|
||||
m_dxf_formats = Format::s_dxfFormats;
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
{
|
||||
QByteArray key;
|
||||
QDataStream stream(&key, QIODevice::WriteOnly);
|
||||
stream<<QColor()<<QColor()<<Format::PatternGray125;
|
||||
fillsKeyCache[key] = 1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
m_fill_count = fillsKeyCache.size() + 2;
|
||||
}
|
||||
|
||||
void Styles::clearExtraFormatInfo()
|
||||
{
|
||||
foreach (Format *format, m_formats)
|
||||
format->clearExtraInfos();
|
||||
}
|
||||
|
||||
void Styles::saveToXmlFile(QIODevice *device)
|
||||
{
|
||||
//Todo
|
||||
m_xf_formats = m_formats;
|
||||
|
||||
XmlStreamWriter writer(device);
|
||||
|
||||
writer.writeStartDocument("1.0", true);
|
||||
@@ -180,6 +260,7 @@ void Styles::writeFills(XmlStreamWriter &writer)
|
||||
{
|
||||
writer.writeStartElement("fills");
|
||||
writer.writeAttribute("count", QString::number(m_fill_count));
|
||||
//wirte two default fill first
|
||||
writer.writeStartElement("fill");
|
||||
writer.writeEmptyElement("patternFill");
|
||||
writer.writeAttribute("patternType", "none");
|
||||
@@ -190,12 +271,52 @@ void Styles::writeFills(XmlStreamWriter &writer)
|
||||
writer.writeEndElement();//fill
|
||||
foreach (Format *format, m_xf_formats) {
|
||||
if (format->hasFill()) {
|
||||
//:TODO
|
||||
writeFill(writer, format);
|
||||
}
|
||||
}
|
||||
writer.writeEndElement(); //fills
|
||||
}
|
||||
|
||||
void Styles::writeFill(XmlStreamWriter &writer, Format *format)
|
||||
{
|
||||
static QMap<int, QString> patternStrings;
|
||||
if (patternStrings.isEmpty()) {
|
||||
patternStrings[Format::PatternNone] = "none";
|
||||
patternStrings[Format::PatternSolid] = "solid";
|
||||
patternStrings[Format::PatternMediumGray] = "mediumGray";
|
||||
patternStrings[Format::PatternDarkGray] = "darkGray";
|
||||
patternStrings[Format::PatternLightGray] = "lightGray";
|
||||
patternStrings[Format::PatternDarkHorizontal] = "darkHorizontal";
|
||||
patternStrings[Format::PatternDarkVertical] = "darkVertical";
|
||||
patternStrings[Format::PatternDarkDown] = "darkDown";
|
||||
patternStrings[Format::PatternDarkUp] = "darkUp";
|
||||
patternStrings[Format::PatternDarkGrid] = "darkGrid";
|
||||
patternStrings[Format::PatternDarkTrellis] = "darkTrellis";
|
||||
patternStrings[Format::PatternLightHorizontal] = "lightHorizontal";
|
||||
patternStrings[Format::PatternLightVertical] = "lightVertical";
|
||||
patternStrings[Format::PatternLightDown] = "lightDown";
|
||||
patternStrings[Format::PatternLightUp] = "lightUp";
|
||||
patternStrings[Format::PatternLightTrellis] = "lightTrellis";
|
||||
patternStrings[Format::PatternGray125] = "gray125";
|
||||
patternStrings[Format::PatternGray0625] = "gray0625";
|
||||
}
|
||||
|
||||
writer.writeStartElement("fill");
|
||||
writer.writeStartElement("patternFill");
|
||||
writer.writeAttribute("patternType", patternStrings[format->fillPattern()]);
|
||||
if (format->patternForegroundColor().isValid()) {
|
||||
writer.writeEmptyElement("fgColor");
|
||||
writer.writeAttribute("rgb", "FF"+format->patternForegroundColor().name().mid(1));
|
||||
}
|
||||
if (format->patternBackgroundColor().isValid()) {
|
||||
writer.writeEmptyElement("bgColor");
|
||||
writer.writeAttribute("rgb", "FF"+format->patternBackgroundColor().name().mid(1));
|
||||
}
|
||||
|
||||
writer.writeEndElement();//patternFill
|
||||
writer.writeEndElement();//fill
|
||||
}
|
||||
|
||||
void Styles::writeBorders(XmlStreamWriter &writer)
|
||||
{
|
||||
writer.writeStartElement("borders");
|
||||
@@ -203,12 +324,21 @@ void Styles::writeBorders(XmlStreamWriter &writer)
|
||||
foreach (Format *format, m_xf_formats) {
|
||||
if (format->hasBorders()) {
|
||||
writer.writeStartElement("border");
|
||||
writer.writeEmptyElement("left");
|
||||
writer.writeEmptyElement("right");
|
||||
writer.writeEmptyElement("top");
|
||||
writer.writeEmptyElement("bottom");
|
||||
if (format->diagonalBorderType() == Format::DiagonalBorderUp) {
|
||||
writer.writeAttribute("diagonalUp", "1");
|
||||
} else if (format->diagonalBorderType() == Format::DiagonalBorderDown) {
|
||||
writer.writeAttribute("diagonalDown", "1");
|
||||
} else if (format->DiagnoalBorderBoth) {
|
||||
writer.writeAttribute("diagonalUp", "1");
|
||||
writer.writeAttribute("diagonalDown", "1");
|
||||
}
|
||||
writeSubBorder(writer, "left", format->leftBorderStyle(), format->leftBorderColor());
|
||||
writeSubBorder(writer, "right", format->rightBorderStyle(), format->rightBorderColor());
|
||||
writeSubBorder(writer, "top", format->topBorderStyle(), format->topBorderColor());
|
||||
writeSubBorder(writer, "bottom", format->bottomBorderStyle(), format->bottomBorderColor());
|
||||
|
||||
if (!format->isDxfFormat()) {
|
||||
writer.writeEmptyElement("diagonal");
|
||||
writeSubBorder(writer, "diagonal", format->diagonalBorderStyle(), format->diagonalBorderColor());
|
||||
}
|
||||
writer.writeEndElement();//border
|
||||
}
|
||||
@@ -216,12 +346,47 @@ void Styles::writeBorders(XmlStreamWriter &writer)
|
||||
writer.writeEndElement();//borders
|
||||
}
|
||||
|
||||
void Styles::writeSubBorder(XmlStreamWriter &writer, const QString &type, int style, const QColor &color)
|
||||
{
|
||||
if (style == Format::BorderNone) {
|
||||
writer.writeEmptyElement(type);
|
||||
return;
|
||||
}
|
||||
|
||||
static QMap<int, QString> stylesString;
|
||||
if (stylesString.isEmpty()) {
|
||||
stylesString[Format::BorderNone] = "none";
|
||||
stylesString[Format::BorderThin] = "thin";
|
||||
stylesString[Format::BorderMedium] = "medium";
|
||||
stylesString[Format::BorderDashed] = "dashed";
|
||||
stylesString[Format::BorderDotted] = "dotted";
|
||||
stylesString[Format::BorderThick] = "thick";
|
||||
stylesString[Format::BorderDouble] = "double";
|
||||
stylesString[Format::BorderHair] = "hair";
|
||||
stylesString[Format::BorderMediumDashed] = "mediumDashed";
|
||||
stylesString[Format::BorderDashDot] = "dashDot";
|
||||
stylesString[Format::BorderMediumDashDot] = "mediumDashDot";
|
||||
stylesString[Format::BorderDashDotDot] = "dashDotDot";
|
||||
stylesString[Format::BorderMediumDashDotDot] = "mediumDashDotDot";
|
||||
stylesString[Format::BorderSlantDashDot] = "slantDashDot";
|
||||
}
|
||||
|
||||
writer.writeStartElement(type);
|
||||
writer.writeAttribute("style", stylesString[style]);
|
||||
writer.writeEmptyElement("color");
|
||||
if (color.isValid())
|
||||
writer.writeAttribute("rgb", "FF"+color.name().mid(1)); //remove #
|
||||
else
|
||||
writer.writeAttribute("auto", "1");
|
||||
writer.writeEndElement();//type
|
||||
}
|
||||
|
||||
void Styles::writeCellXfs(XmlStreamWriter &writer)
|
||||
{
|
||||
writer.writeStartElement("cellXfs");
|
||||
writer.writeAttribute("count", QString::number(m_xf_formats.size()));
|
||||
foreach (Format *format, m_xf_formats) {
|
||||
int num_fmt_id = format->numFormatIndex();
|
||||
int num_fmt_id = format->numberFormat();
|
||||
int font_id = format->fontIndex();
|
||||
int fill_id = format->fillIndex();
|
||||
int border_id = format->borderIndex();
|
||||
@@ -232,12 +397,14 @@ void Styles::writeCellXfs(XmlStreamWriter &writer)
|
||||
writer.writeAttribute("fillId", QString::number(fill_id));
|
||||
writer.writeAttribute("borderId", QString::number(border_id));
|
||||
writer.writeAttribute("xfId", QString::number(xf_id));
|
||||
if (format->numFormatIndex() > 0)
|
||||
if (format->numberFormat() > 0)
|
||||
writer.writeAttribute("applyNumberFormat", "1");
|
||||
if (format->fontIndex() > 0)
|
||||
writer.writeAttribute("applyFont", "1");
|
||||
if (format->fillIndex() > 0)
|
||||
if (format->borderIndex() > 0)
|
||||
writer.writeAttribute("applyBorder", "1");
|
||||
if (format->fillIndex() > 0)
|
||||
writer.writeAttribute("applyFill", "1");
|
||||
if (format->alignmentChanged())
|
||||
writer.writeAttribute("applyAlignment", "1");
|
||||
|
||||
|
||||
+5
-1
@@ -38,18 +38,22 @@ class Styles : public QObject
|
||||
{
|
||||
public:
|
||||
explicit Styles(QObject *parent=0);
|
||||
~Styles();
|
||||
Format *addFormat();
|
||||
|
||||
void prepareStyles();
|
||||
void clearExtraFormatInfo();
|
||||
void saveToXmlFile(QIODevice *device);
|
||||
|
||||
private:
|
||||
void writeFonts(XmlStreamWriter &writer);
|
||||
void writeFills(XmlStreamWriter &writer);
|
||||
void writeFill(XmlStreamWriter &writer, Format *format);
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user