// xlsxformat.cpp #include #include #include #include "xlsxformat.h" #include "xlsxformat_p.h" #include "xlsxcolor_p.h" #include "xlsxnumformatparser_p.h" QT_BEGIN_NAMESPACE_XLSX FormatPrivate::FormatPrivate() : dirty(true) , font_dirty(true), font_index_valid(false), font_index(0) , fill_dirty(true), fill_index_valid(false), fill_index(0) , border_dirty(true), border_index_valid(false), border_index(0) , xf_index(-1), xf_indexValid(false) , is_dxf_fomat(false), dxf_index(-1), dxf_indexValid(false) , theme(0) { } FormatPrivate::FormatPrivate(const FormatPrivate &other) : QSharedData(other) , 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) , theme(other.theme) , properties(other.properties) { } FormatPrivate::~FormatPrivate() { } /*! * \class Format * \inmodule QtXlsx * \brief Providing the methods and properties that are available for formatting cells in Excel. */ /*! * \enum Format::FontScript * * The enum type defines the type of font script. * * \value FontScriptNormal normal * \value FontScriptSuper super script * \value FontScriptSub sub script */ /*! * \enum Format::FontUnderline * * The enum type defines the type of font underline. * * \value FontUnderlineNone * \value FontUnderlineSingle * \value FontUnderlineDouble * \value FontUnderlineSingleAccounting * \value FontUnderlineDoubleAccounting */ /*! * \enum Format::HorizontalAlignment * * The enum type defines the type of horizontal alignment. * * \value AlignHGeneral * \value AlignLeft * \value AlignHCenter * \value AlignRight * \value AlignHFill * \value AlignHJustify * \value AlignHMerge * \value AlignHDistributed */ /*! * \enum Format::VerticalAlignment * * The enum type defines the type of vertical alignment. * * \value AlignTop, * \value AlignVCenter, * \value AlignBottom, * \value AlignVJustify, * \value AlignVDistributed */ /*! * \enum Format::BorderStyle * * The enum type defines the type of font underline. * * \value BorderNone * \value BorderThin * \value BorderMedium * \value BorderDashed * \value BorderDotted * \value BorderThick * \value BorderDouble * \value BorderHair * \value BorderMediumDashed * \value BorderDashDot * \value BorderMediumDashDot * \value BorderDashDotDot * \value BorderMediumDashDotDot * \value BorderSlantDashDot */ /*! * \enum Format::DiagonalBorderType * * The enum type defines the type of diagonal border. * * \value DiagonalBorderNone * \value DiagonalBorderDown * \value DiagonalBorderUp * \value DiagnoalBorderBoth */ /*! * \enum Format::FillPattern * * The enum type defines the type of fill. * * \value PatternNone * \value PatternSolid * \value PatternMediumGray * \value PatternDarkGray * \value PatternLightGray * \value PatternDarkHorizontal * \value PatternDarkVertical * \value PatternDarkDown * \value PatternDarkUp * \value PatternDarkGrid * \value PatternDarkTrellis * \value PatternLightHorizontal * \value PatternLightVertical * \value PatternLightDown * \value PatternLightUp * \value PatternLightTrellis * \value PatternGray125 * \value PatternGray0625 * \value PatternLightGrid */ /*! * Creates a new invalid format. */ Format::Format() { //The d pointer is initialized with a null pointer } /*! Creates a new format with the same attributes as the \a other format. */ Format::Format(const Format &other) :d(other.d) { } /*! Assigns the \a other format to this format, and returns a reference to this format. */ Format &Format::operator =(const Format &other) { d = other.d; return *this; } /*! * Destroys this format. */ Format::~Format() { } /*! * Returns the number format identifier. */ int Format::numberFormatIndex() const { return intProperty(FormatPrivate::P_NumFmt_Id, 0); } /*! * Set the number format identifier. The \a format * must be a valid built-in number format identifier * or the identifier of a custom number format. */ void Format::setNumberFormatIndex(int format) { setProperty(FormatPrivate::P_NumFmt_Id, format); clearProperty(FormatPrivate::P_NumFmt_FormatCode); } /*! * Returns the number format string. * \note for built-in number formats, this may * return an empty string. */ QString Format::numberFormat() const { return stringProperty(FormatPrivate::P_NumFmt_FormatCode); } /*! * Set number \a format. * http://office.microsoft.com/en-001/excel-help/create-a-custom-number-format-HP010342372.aspx */ void Format::setNumberFormat(const QString &format) { if (format.isEmpty()) return; setProperty(FormatPrivate::P_NumFmt_FormatCode, format); clearProperty(FormatPrivate::P_NumFmt_Id); //numFmt id must be re-generated. } /*! * Returns whether the number format is probably a dateTime or not */ bool Format::isDateTimeFormat() const { //NOTICE: if (hasProperty(FormatPrivate::P_NumFmt_FormatCode)) { //Custom numFmt, so //Gauss from the number string return NumFormatParser::isDateTime(numberFormat()); } else if (hasProperty(FormatPrivate::P_NumFmt_Id)) { //Non-custom numFmt int idx = numberFormatIndex(); //Is built-in date time number id? if ((idx >= 14 && idx <= 22) || (idx >= 45 && idx <= 47)) return true; if ((idx >= 27 && idx <= 36) || (idx >= 50 && idx <= 58)) //Used in CHS\CHT\JPN\KOR return true; } return false; } /*! \internal Set a custom num \a format with the given \a id. */ void Format::setNumberFormat(int id, const QString &format) { setProperty(FormatPrivate::P_NumFmt_Id, id); setProperty(FormatPrivate::P_NumFmt_FormatCode, format); } /*! \internal Called by styles to fix the numFmt */ void Format::fixNumberFormat(int id, const QString &format) { setProperty(FormatPrivate::P_NumFmt_Id, id, 0, false); setProperty(FormatPrivate::P_NumFmt_FormatCode, format, QString(), false); } /*! \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. */ int Format::fontSize() const { return intProperty(FormatPrivate::P_Font_Size); } /*! * Set the \a size of the font in points. */ void Format::setFontSize(int size) { setProperty(FormatPrivate::P_Font_Size, size, 0); } /*! * Return whether the font is italic. */ bool Format::fontItalic() const { return boolProperty(FormatPrivate::P_Font_Italic); } /*! * Turn on/off the italic font based on \a italic. */ void Format::setFontItalic(bool italic) { setProperty(FormatPrivate::P_Font_Italic, italic, false); } /*! * Return whether the font is strikeout. */ bool Format::fontStrikeOut() const { return boolProperty(FormatPrivate::P_Font_StrikeOut); } /*! * Turn on/off the strikeOut font based on \a strikeOut. */ void Format::setFontStrikeOut(bool strikeOut) { setProperty(FormatPrivate::P_Font_StrikeOut, strikeOut, false); } /*! * Return the color of the font. */ QColor Format::fontColor() const { if (hasProperty(FormatPrivate::P_Font_Color)) return colorProperty(FormatPrivate::P_Font_Color); return QColor(); } /*! * Set the \a color of the font. */ void Format::setFontColor(const QColor &color) { setProperty(FormatPrivate::P_Font_Color, XlsxColor(color), XlsxColor()); } /*! * Return whether the font is bold. */ bool Format::fontBold() const { return boolProperty(FormatPrivate::P_Font_Bold); } /*! * Turn on/off the bold font based on the given \a bold. */ void Format::setFontBold(bool bold) { setProperty(FormatPrivate::P_Font_Bold, bold, false); } /*! * Return the script style of the font. */ Format::FontScript Format::fontScript() const { return static_cast(intProperty(FormatPrivate::P_Font_Script)); } /*! * Set the script style of the font to \a script. */ void Format::setFontScript(FontScript script) { setProperty(FormatPrivate::P_Font_Script, script, FontScriptNormal); } /*! * Return the underline style of the font. */ Format::FontUnderline Format::fontUnderline() const { return static_cast(intProperty(FormatPrivate::P_Font_Underline)); } /*! * Set the underline style of the font to \a underline. */ void Format::setFontUnderline(FontUnderline underline) { setProperty(FormatPrivate::P_Font_Underline, underline, FontUnderlineNone); } /*! * Return whether the font is outline. */ bool Format::fontOutline() const { return boolProperty(FormatPrivate::P_Font_Outline); } /*! * Turn on/off the outline font based on \a outline. */ void Format::setFontOutline(bool outline) { setProperty(FormatPrivate::P_Font_Outline, outline, false); } /*! * Return the name of the font. */ QString Format::fontName() const { return stringProperty(FormatPrivate::P_Font_Name, QStringLiteral("Calibri")); } /*! * Set the name of the font to \a name. */ void Format::setFontName(const QString &name) { setProperty(FormatPrivate::P_Font_Name, name, QStringLiteral("Calibri")); } /*! * Returns a QFont object based on font data contained in the format. */ QFont Format::font() const { QFont font; font.setFamily(fontName()); if (fontSize() > 0) font.setPointSize(fontSize()); font.setBold(fontBold()); font.setItalic(fontItalic()); font.setUnderline(fontUnderline()!=FontUnderlineNone); font.setStrikeOut(fontStrikeOut()); return font; } /*! * Set the format properties from the given \a font. */ void Format::setFont(const QFont &font) { setFontName(font.family()); if (font.pointSize() > 0) setFontSize(font.pointSize()); setFontBold(font.bold()); setFontItalic(font.italic()); setFontUnderline(font.underline() ? FontUnderlineSingle : FontUnderlineNone); setFontStrikeOut(font.strikeOut()); } /*! * \internal * When the format has font data, when need to assign a valid index for it. * The index value is depend on the order in styles.xml */ bool Format::fontIndexValid() const { if (!hasFontData()) return false; return d->font_index_valid; } /*! * \internal */ int Format::fontIndex() const { if (fontIndexValid()) return d->font_index; return 0; } /*! * \internal */ void Format::setFontIndex(int index) { d->font_index = index; d->font_index_valid = true; } /*! * \internal */ QByteArray Format::fontKey() const { if (isEmpty()) return QByteArray(); if (d->font_dirty) { QByteArray key; QDataStream stream(&key, QIODevice::WriteOnly); for (int i=FormatPrivate::P_Font_STARTID; iproperties.constFind(i); if (it != d->properties.constEnd()) stream << i << it.value(); }; const_cast(this)->d->font_key = key; const_cast(this)->d->font_dirty = false; } 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(intProperty(FormatPrivate::P_Alignment_AlignH, AlignHGeneral)); } /*! * Set the horizontal alignment with the given \a align. */ void Format::setHorizontalAlignment(HorizontalAlignment align) { if (hasProperty(FormatPrivate::P_Alignment_Indent) &&(align != AlignHGeneral && align != AlignLeft && align != AlignRight && align != AlignHDistributed)) { clearProperty(FormatPrivate::P_Alignment_Indent); } if (hasProperty(FormatPrivate::P_Alignment_ShinkToFit) && (align == AlignHFill || align == AlignHJustify || align == AlignHDistributed)) { clearProperty(FormatPrivate::P_Alignment_ShinkToFit); } setProperty(FormatPrivate::P_Alignment_AlignH, align, AlignHGeneral); } /*! * Return the vertical alignment. */ Format::VerticalAlignment Format::verticalAlignment() const { return static_cast(intProperty(FormatPrivate::P_Alignment_AlignV, AlignBottom)); } /*! * Set the vertical alignment with the given \a align. */ void Format::setVerticalAlignment(VerticalAlignment align) { setProperty(FormatPrivate::P_Alignment_AlignV, align, AlignBottom); } /*! * Return whether the cell text is wrapped. */ bool Format::textWrap() const { return boolProperty(FormatPrivate::P_Alignment_Wrap); } /*! * Enable the text wrap if \a wrap is true. */ void Format::setTextWrap(bool wrap) { if (wrap && hasProperty(FormatPrivate::P_Alignment_ShinkToFit)) clearProperty(FormatPrivate::P_Alignment_ShinkToFit); setProperty(FormatPrivate::P_Alignment_Wrap, wrap, false); } /*! * Return the text rotation. */ int Format::rotation() const { return intProperty(FormatPrivate::P_Alignment_Rotation); } /*! * Set the text roation with the given \a rotation. Must be in the range [0, 180] or 255. */ void Format::setRotation(int rotation) { setProperty(FormatPrivate::P_Alignment_Rotation, rotation, 0); } /*! * Return the text indentation level. */ int Format::indent() const { return intProperty(FormatPrivate::P_Alignment_Indent); } /*! * Set the text indentation level with the given \a indent. Must be less than or equal to 15. */ void Format::setIndent(int indent) { if (indent && hasProperty(FormatPrivate::P_Alignment_AlignH)) { HorizontalAlignment hl = horizontalAlignment(); if (hl != AlignHGeneral && hl != AlignLeft && hl!= AlignRight && hl!= AlignHJustify) { setHorizontalAlignment(AlignLeft); } } setProperty(FormatPrivate::P_Alignment_Indent, indent, 0); } /*! * Return whether the cell is shrink to fit. */ bool Format::shrinkToFit() const { return boolProperty(FormatPrivate::P_Alignment_ShinkToFit); } /*! * Turn on/off shrink to fit base on \a shink. */ void Format::setShrinkToFit(bool shink) { if (shink && hasProperty(FormatPrivate::P_Alignment_Wrap)) clearProperty(FormatPrivate::P_Alignment_Wrap); if (shink && hasProperty(FormatPrivate::P_Alignment_AlignH)) { HorizontalAlignment hl = horizontalAlignment(); if (hl == AlignHFill || hl == AlignHJustify || hl == AlignHDistributed) setHorizontalAlignment(AlignLeft); } setProperty(FormatPrivate::P_Alignment_ShinkToFit, shink, false); } /*! * \internal */ bool Format::hasAlignmentData() const { if (!d) return false; for (int i=FormatPrivate::P_Alignment_STARTID; i(intProperty(FormatPrivate::P_Border_LeftStyle)); } /*! * Sets the left border style to \a style */ void Format::setLeftBorderStyle(BorderStyle style) { setProperty(FormatPrivate::P_Border_LeftStyle, style, BorderNone); } /*! * Returns the left border color */ QColor Format::leftBorderColor() const { return colorProperty(FormatPrivate::P_Border_LeftColor); } /*! Sets the left border color to the given \a color */ void Format::setLeftBorderColor(const QColor &color) { setProperty(FormatPrivate::P_Border_LeftColor, XlsxColor(color), XlsxColor()); } /*! Returns the right border style. */ Format::BorderStyle Format::rightBorderStyle() const { return static_cast(intProperty(FormatPrivate::P_Border_RightStyle)); } /*! Sets the right border style to the given \a style. */ void Format::setRightBorderStyle(BorderStyle style) { setProperty(FormatPrivate::P_Border_RightStyle, style, BorderNone); } /*! Returns the right border color. */ QColor Format::rightBorderColor() const { return colorProperty(FormatPrivate::P_Border_RightColor); } /*! Sets the right border color to the given \a color */ void Format::setRightBorderColor(const QColor &color) { setProperty(FormatPrivate::P_Border_RightColor, XlsxColor(color), XlsxColor()); } /*! Returns the top border style. */ Format::BorderStyle Format::topBorderStyle() const { return static_cast(intProperty(FormatPrivate::P_Border_TopStyle)); } /*! Sets the top border style to the given \a style. */ void Format::setTopBorderStyle(BorderStyle style) { setProperty(FormatPrivate::P_Border_TopStyle, style, BorderNone); } /*! Returns the top border color. */ QColor Format::topBorderColor() const { return colorProperty(FormatPrivate::P_Border_TopColor); } /*! Sets the top border color to the given \a color. */ void Format::setTopBorderColor(const QColor &color) { setProperty(FormatPrivate::P_Border_TopColor, XlsxColor(color), XlsxColor()); } /*! Returns the bottom border style. */ Format::BorderStyle Format::bottomBorderStyle() const { return static_cast(intProperty(FormatPrivate::P_Border_BottomStyle)); } /*! Sets the bottom border style to the given \a style. */ void Format::setBottomBorderStyle(BorderStyle style) { setProperty(FormatPrivate::P_Border_BottomStyle, style, BorderNone); } /*! Returns the bottom border color. */ QColor Format::bottomBorderColor() const { return colorProperty(FormatPrivate::P_Border_BottomColor); } /*! Sets the bottom border color to the given \a color. */ void Format::setBottomBorderColor(const QColor &color) { setProperty(FormatPrivate::P_Border_BottomColor, XlsxColor(color), XlsxColor()); } /*! Return the diagonla border style. */ Format::BorderStyle Format::diagonalBorderStyle() const { return static_cast(intProperty(FormatPrivate::P_Border_DiagonalStyle)); } /*! Sets the diagonal border style to the given \a style. */ void Format::setDiagonalBorderStyle(BorderStyle style) { setProperty(FormatPrivate::P_Border_DiagonalStyle, style, BorderNone); } /*! Returns the diagonal border type. */ Format::DiagonalBorderType Format::diagonalBorderType() const { return static_cast(intProperty(FormatPrivate::P_Border_DiagonalType)); } /*! Sets the diagonal border type to the given \a style */ void Format::setDiagonalBorderType(DiagonalBorderType style) { setProperty(FormatPrivate::P_Border_DiagonalType, style, DiagonalBorderNone); } /*! Returns the diagonal border color. */ QColor Format::diagonalBorderColor() const { return colorProperty(FormatPrivate::P_Border_DiagonalColor); } /*! Sets the diagonal border color to the given \a color */ void Format::setDiagonalBorderColor(const QColor &color) { setProperty(FormatPrivate::P_Border_DiagonalColor, XlsxColor(color), XlsxColor()); } /*! \internal Returns whether this format has been set valid border index. */ bool Format::borderIndexValid() const { if (!hasBorderData()) return false; return d->border_index_valid; } /*! \internal Returns the border index. */ int Format::borderIndex() const { if (borderIndexValid()) return d->border_index; return 0; } /*! * \internal */ void Format::setBorderIndex(int index) { d->border_index = index; d->border_index_valid = true; } /*! \internal */ QByteArray Format::borderKey() const { if (isEmpty()) return QByteArray(); if (d->border_dirty) { QByteArray key; QDataStream stream(&key, QIODevice::WriteOnly); for (int i=FormatPrivate::P_Border_STARTID; iproperties.constFind(i); if (it != d->properties.constEnd()) stream << i << it.value(); }; const_cast(this)->d->border_key = key; const_cast(this)->d->border_dirty = false; } 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(intProperty(FormatPrivate::P_Fill_Pattern, PatternNone)); } /*! Sets the fill pattern to the given \a pattern. */ void Format::setFillPattern(FillPattern pattern) { setProperty(FormatPrivate::P_Fill_Pattern, pattern, PatternNone); } /*! Returns the foreground color of the pattern. */ QColor Format::patternForegroundColor() const { return colorProperty(FormatPrivate::P_Fill_FgColor); } /*! Sets the foreground color of the pattern with the given \a color. */ void Format::setPatternForegroundColor(const QColor &color) { if (color.isValid() && !hasProperty(FormatPrivate::P_Fill_Pattern)) setFillPattern(PatternSolid); setProperty(FormatPrivate::P_Fill_FgColor, XlsxColor(color), XlsxColor()); } /*! Returns the background color of the pattern. */ QColor Format::patternBackgroundColor() const { return colorProperty(FormatPrivate::P_Fill_BgColor); } /*! Sets the background color of the pattern with the given \a color. */ void Format::setPatternBackgroundColor(const QColor &color) { if (color.isValid() && !hasProperty(FormatPrivate::P_Fill_Pattern)) setFillPattern(PatternSolid); setProperty(FormatPrivate::P_Fill_BgColor, XlsxColor(color), XlsxColor()); } /*! * \internal */ bool Format::fillIndexValid() const { if (!hasFillData()) return false; return d->fill_index_valid; } /*! * \internal */ int Format::fillIndex() const { if (fillIndexValid()) return d->fill_index; return 0; } /*! * \internal */ void Format::setFillIndex(int index) { d->fill_index = index; d->fill_index_valid = true; } /*! * \internal */ QByteArray Format::fillKey() const { if (isEmpty()) return QByteArray(); if (d->fill_dirty) { QByteArray key; QDataStream stream(&key, QIODevice::WriteOnly); for (int i=FormatPrivate::P_Fill_STARTID; iproperties.constFind(i); if (it != d->properties.constEnd()) stream << i << it.value(); }; const_cast(this)->d->fill_key = key; const_cast(this)->d->fill_dirty = false; } 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