diff src/xlsx/xlsxformat.cpp @ 1:93d3106bb9a4

Add qt xlsx library
author Andre Heinecke <andre.heinecke@intevation.de>
date Tue, 22 Mar 2016 10:38:08 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/xlsx/xlsxformat.cpp	Tue Mar 22 10:38:08 2016 +0100
@@ -0,0 +1,1432 @@
+/****************************************************************************
+** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
+** All right reserved.
+**
+** Permission is hereby granted, free of charge, to any person obtaining
+** a copy of this software and associated documentation files (the
+** "Software"), to deal in the Software without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Software, and to
+** permit persons to whom the Software is furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be
+** included in all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**
+****************************************************************************/
+#include "xlsxformat.h"
+#include "xlsxformat_p.h"
+#include "xlsxcolor_p.h"
+#include "xlsxnumformatparser_p.h"
+#include <QDataStream>
+#include <QDebug>
+
+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
+{
+    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<Format::FontScript>(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<Format::FontUnderline>(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 <fonts > 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; i<FormatPrivate::P_Font_ENDID; ++i) {
+            if (d->properties.contains(i))
+                stream << i << d->properties[i];
+        };
+
+        const_cast<Format*>(this)->d->font_key = key;
+        const_cast<Format*>(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<FormatPrivate::P_Font_ENDID; ++i) {
+        if (hasProperty(i))
+            return true;
+    }
+    return false;
+}
+
+/*!
+ * Return the horizontal alignment.
+ */
+Format::HorizontalAlignment Format::horizontalAlignment() const
+{
+    return static_cast<Format::HorizontalAlignment>(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<Format::VerticalAlignment>(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::setTextWarp(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<FormatPrivate::P_Alignment_ENDID; ++i) {
+        if (hasProperty(i))
+            return true;
+    }
+    return false;
+}
+
+/*!
+ * Set the border style with the given \a style.
+ */
+void Format::setBorderStyle(BorderStyle style)
+{
+    setLeftBorderStyle(style);
+    setRightBorderStyle(style);
+    setBottomBorderStyle(style);
+    setTopBorderStyle(style);
+}
+
+/*!
+ * Sets the border color with the given \a color.
+ */
+void Format::setBorderColor(const QColor &color)
+{
+    setLeftBorderColor(color);
+    setRightBorderColor(color);
+    setTopBorderColor(color);
+    setBottomBorderColor(color);
+}
+
+/*!
+ * Returns the left border style
+ */
+Format::BorderStyle Format::leftBorderStyle() const
+{
+    return static_cast<BorderStyle>(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<BorderStyle>(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<BorderStyle>(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<BorderStyle>(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<BorderStyle>(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<DiagonalBorderType>(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; i<FormatPrivate::P_Border_ENDID; ++i) {
+            if (d->properties.contains(i))
+                stream << i << d->properties[i];
+        };
+
+        const_cast<Format*>(this)->d->border_key = key;
+        const_cast<Format*>(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<FormatPrivate::P_Border_ENDID; ++i) {
+        if (hasProperty(i))
+            return true;
+    }
+    return false;
+}
+
+/*!
+    Return the fill pattern.
+*/
+Format::FillPattern Format::fillPattern() const
+{
+    return static_cast<FillPattern>(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; i<FormatPrivate::P_Fill_ENDID; ++i) {
+            if (d->properties.contains(i))
+                stream << i << d->properties[i];
+        };
+
+        const_cast<Format*>(this)->d->fill_key = key;
+        const_cast<Format*>(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<FormatPrivate::P_Fill_ENDID; ++i) {
+        if (hasProperty(i))
+            return true;
+    }
+    return false;
+}
+
+/*!
+    Returns whether the hidden protection property is set to true.
+*/
+bool Format::hidden() const
+{
+    return boolProperty(FormatPrivate::P_Protection_Hidden);
+}
+
+/*!
+    Sets the hidden protection property with the given \a hidden.
+*/
+void Format::setHidden(bool hidden)
+{
+    setProperty(FormatPrivate::P_Protection_Hidden, hidden);
+}
+
+/*!
+    Returns whether the locked protection property is set to true.
+*/
+bool Format::locked() const
+{
+    return boolProperty(FormatPrivate::P_Protection_Locked);
+}
+
+/*!
+    Sets the locked protection property with the given \a locked.
+*/
+void Format::setLocked(bool locked)
+{
+    setProperty(FormatPrivate::P_Protection_Locked, locked);
+}
+
+/*!
+    \internal
+    Return true if the format has protection data, otherwise return false.
+ */
+bool Format::hasProtectionData() const
+{
+    if (!d)
+        return false;
+
+    if (hasProperty(FormatPrivate::P_Protection_Hidden
+            || FormatPrivate::P_Protection_Locked)) {
+        return true;
+    }
+    return false;
+}
+
+/*!
+    Merges the current format with the properties described by format \a modifier.
+ */
+void Format::mergeFormat(const Format &modifier)
+{
+    if (!modifier.isValid())
+        return;
+
+    if (!isValid()) {
+        d = modifier.d;
+        return;
+    }
+
+    QMapIterator<int, QVariant> it(modifier.d->properties);
+    while(it.hasNext()) {
+        it.next();
+        setProperty(it.key(), it.value());
+    }
+}
+
+/*!
+    Returns true if the format is valid; otherwise returns false.
+ */
+bool Format::isValid() const
+{
+    if (d)
+        return true;
+    return false;
+}
+
+/*!
+    Returns true if the format is empty; otherwise returns false.
+ */
+bool Format::isEmpty() const
+{
+    if (!d)
+        return true;
+    return d->properties.isEmpty();
+}
+
+/*!
+ * \internal
+ */
+QByteArray Format::formatKey() const
+{
+    if (isEmpty())
+        return QByteArray();
+
+    if (d->dirty) {
+        QByteArray key;
+        QDataStream stream(&key, QIODevice::WriteOnly);
+
+        QMapIterator<int, QVariant> i(d->properties);
+        while (i.hasNext()) {
+            i.next();
+            stream<<i.key()<<i.value();
+        }
+
+        d->formatKey = key;
+        d->dirty = false;
+    }
+
+    return d->formatKey;
+}
+
+/*!
+ * \internal
+ *  Called by QXlsx::Styles or some unittests.
+ */
+void Format::setXfIndex(int index)
+{
+    if (!d)
+        d = new FormatPrivate;
+    d->xf_index = index;
+    d->xf_indexValid = true;
+}
+
+/*!
+ * \internal
+ */
+int Format::xfIndex() const
+{
+    if (!d)
+        return -1;
+    return d->xf_index;
+}
+
+/*!
+ * \internal
+ */
+bool Format::xfIndexValid() const
+{
+    if (!d)
+        return false;
+    return d->xf_indexValid;
+}
+
+/*!
+ * \internal
+ *  Called by QXlsx::Styles or some unittests.
+ */
+void Format::setDxfIndex(int index)
+{
+    if (!d)
+        d = new FormatPrivate;
+    d->dxf_index = index;
+    d->dxf_indexValid = true;
+}
+
+/*!
+ * \internal
+ * Returns the index in the styles dxfs.
+ */
+int Format::dxfIndex() const
+{
+    if (!d)
+        return -1;
+    return d->dxf_index;
+}
+
+/*!
+ * \internal
+ * Returns whether the dxf index is valid or not.
+ */
+bool Format::dxfIndexValid() const
+{
+    if (!d)
+        return false;
+    return d->dxf_indexValid;
+}
+
+/*!
+    Returns ture if the \a format is equal to this format.
+*/
+bool Format::operator ==(const Format &format) const
+{
+    return this->formatKey() == format.formatKey();
+}
+
+/*!
+    Returns ture if the \a format is not equal to this format.
+*/
+bool Format::operator !=(const Format &format) const
+{
+    return this->formatKey() != format.formatKey();
+}
+
+int Format::theme() const
+{
+    return d->theme;
+}
+
+/*!
+ * \internal
+ */
+QVariant Format::property(int propertyId, const QVariant &defaultValue) const
+{
+    if (d && d->properties.contains(propertyId))
+        return d->properties[propertyId];
+    return defaultValue;
+}
+
+/*!
+ * \internal
+ */
+void Format::setProperty(int propertyId, const QVariant &value, const QVariant &clearValue, bool detach)
+{
+    if (!d)
+        d = new FormatPrivate;
+
+    if (value != clearValue) {
+        if (d->properties.contains(propertyId) && d->properties[propertyId] == value)
+            return;
+        if (detach)
+            d.detach();
+        d->properties[propertyId] = value;
+    } else {
+        if (!d->properties.contains(propertyId))
+            return;
+        if (detach)
+            d.detach();
+        d->properties.remove(propertyId);
+    }
+
+    d->dirty = true;
+    d->xf_indexValid = false;
+    d->dxf_indexValid = false;
+
+    if (propertyId >= FormatPrivate::P_Font_STARTID && propertyId < FormatPrivate::P_Font_ENDID) {
+        d->font_dirty = true;
+        d->font_index_valid = false;
+    } 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;
+    }
+}
+
+/*!
+ * \internal
+ */
+void Format::clearProperty(int propertyId)
+{
+    setProperty(propertyId, QVariant());
+}
+
+/*!
+ * \internal
+ */
+bool Format::hasProperty(int propertyId) const
+{
+    if (!d)
+        return false;
+    return d->properties.contains(propertyId);
+}
+
+/*!
+ * \internal
+ */
+bool Format::boolProperty(int propertyId, bool defaultValue) const
+{
+    if (!hasProperty(propertyId))
+        return defaultValue;
+
+    const QVariant prop = d->properties[propertyId];
+    if (prop.userType() != QMetaType::Bool)
+        return defaultValue;
+    return prop.toBool();
+}
+
+/*!
+ * \internal
+ */
+int Format::intProperty(int propertyId, int defaultValue) const
+{
+    if (!hasProperty(propertyId))
+        return defaultValue;
+
+    const QVariant prop = d->properties[propertyId];
+    if (prop.userType() != QMetaType::Int)
+        return defaultValue;
+    return prop.toInt();
+}
+
+/*!
+ * \internal
+ */
+double Format::doubleProperty(int propertyId, double defaultValue) const
+{
+    if (!hasProperty(propertyId))
+        return defaultValue;
+
+    const QVariant prop = d->properties[propertyId];
+    if (prop.userType() != QMetaType::Double && prop.userType() != QMetaType::Float)
+        return defaultValue;
+    return prop.toDouble();
+}
+
+/*!
+ * \internal
+ */
+QString Format::stringProperty(int propertyId, const QString &defaultValue) const
+{
+    if (!hasProperty(propertyId))
+        return defaultValue;
+
+    const QVariant prop = d->properties[propertyId];
+    if (prop.userType() != QMetaType::QString)
+        return defaultValue;
+    return prop.toString();
+}
+
+/*!
+ * \internal
+ */
+QColor Format::colorProperty(int propertyId, const QColor &defaultValue) const
+{
+    if (!hasProperty(propertyId))
+        return defaultValue;
+
+    const QVariant prop = d->properties[propertyId];
+    if (prop.userType() != qMetaTypeId<XlsxColor>())
+        return defaultValue;
+    return qvariant_cast<XlsxColor>(prop).rgbColor();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const Format &f)
+{
+    dbg.nospace() << "QXlsx::Format(" << f.d->properties << ")";
+    return dbg.space();
+}
+#endif
+
+QT_END_NAMESPACE_XLSX
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)