File indexing completed on 2025-03-23 03:32:49

0001 // xlsxformat.cpp
0002 
0003 #include <QtGlobal>
0004 #include <QDataStream>
0005 #include <QDebug>
0006 
0007 #include "xlsxformat.h"
0008 #include "xlsxformat_p.h"
0009 #include "xlsxcolor_p.h"
0010 #include "xlsxnumformatparser_p.h"
0011 
0012 QT_BEGIN_NAMESPACE_XLSX
0013 
0014 FormatPrivate::FormatPrivate()
0015     : dirty(true)
0016     , font_dirty(true), font_index_valid(false), font_index(0)
0017     , fill_dirty(true), fill_index_valid(false), fill_index(0)
0018     , border_dirty(true), border_index_valid(false), border_index(0)
0019     , xf_index(-1), xf_indexValid(false)
0020     , is_dxf_fomat(false), dxf_index(-1), dxf_indexValid(false)
0021     , theme(0)
0022 {
0023 }
0024 
0025 FormatPrivate::FormatPrivate(const FormatPrivate &other)
0026     : QSharedData(other)
0027     , dirty(other.dirty), formatKey(other.formatKey)
0028     , font_dirty(other.font_dirty), font_index_valid(other.font_index_valid), font_key(other.font_key), font_index(other.font_index)
0029     , fill_dirty(other.fill_dirty), fill_index_valid(other.fill_index_valid), fill_key(other.fill_key), fill_index(other.fill_index)
0030     , border_dirty(other.border_dirty), border_index_valid(other.border_index_valid), border_key(other.border_key), border_index(other.border_index)
0031     , xf_index(other.xf_index), xf_indexValid(other.xf_indexValid)
0032     , is_dxf_fomat(other.is_dxf_fomat), dxf_index(other.dxf_index), dxf_indexValid(other.dxf_indexValid)
0033     , theme(other.theme)
0034     , properties(other.properties)
0035 {
0036 
0037 }
0038 
0039 FormatPrivate::~FormatPrivate()
0040 {
0041 
0042 }
0043 
0044 /*!
0045  * \class Format
0046  * \inmodule QtXlsx
0047  * \brief Providing the methods and properties that are available for formatting cells in Excel.
0048  */
0049 
0050 /*!
0051  * \enum Format::FontScript
0052  *
0053  * The enum type defines the type of font script.
0054  *
0055  * \value FontScriptNormal normal
0056  * \value FontScriptSuper super script
0057  * \value FontScriptSub sub script
0058  */
0059 
0060 
0061 /*!
0062  * \enum Format::FontUnderline
0063  *
0064  * The enum type defines the type of font underline.
0065  *
0066  * \value FontUnderlineNone
0067  * \value FontUnderlineSingle
0068  * \value FontUnderlineDouble
0069  * \value FontUnderlineSingleAccounting
0070  * \value FontUnderlineDoubleAccounting
0071  */
0072 
0073 /*!
0074  * \enum Format::HorizontalAlignment
0075  *
0076  * The enum type defines the type of horizontal alignment.
0077  *
0078  * \value AlignHGeneral
0079  * \value AlignLeft
0080  * \value AlignHCenter
0081  * \value AlignRight
0082  * \value AlignHFill
0083  * \value AlignHJustify
0084  * \value AlignHMerge
0085  * \value AlignHDistributed
0086  */
0087 
0088 /*!
0089  * \enum Format::VerticalAlignment
0090  *
0091  * The enum type defines the type of vertical alignment.
0092  *
0093  * \value AlignTop,
0094  * \value AlignVCenter,
0095  * \value AlignBottom,
0096  * \value AlignVJustify,
0097  * \value AlignVDistributed
0098  */
0099 
0100 /*!
0101  * \enum Format::BorderStyle
0102  *
0103  * The enum type defines the type of font underline.
0104  *
0105  * \value BorderNone
0106  * \value BorderThin
0107  * \value BorderMedium
0108  * \value BorderDashed
0109  * \value BorderDotted
0110  * \value BorderThick
0111  * \value BorderDouble
0112  * \value BorderHair
0113  * \value BorderMediumDashed
0114  * \value BorderDashDot
0115  * \value BorderMediumDashDot
0116  * \value BorderDashDotDot
0117  * \value BorderMediumDashDotDot
0118  * \value BorderSlantDashDot
0119 */
0120 
0121 /*!
0122  * \enum Format::DiagonalBorderType
0123  *
0124  * The enum type defines the type of diagonal border.
0125  *
0126  * \value DiagonalBorderNone
0127  * \value DiagonalBorderDown
0128  * \value DiagonalBorderUp
0129  * \value DiagnoalBorderBoth
0130  */
0131 
0132 /*!
0133  * \enum Format::FillPattern
0134  *
0135  * The enum type defines the type of fill.
0136  *
0137  * \value PatternNone
0138  * \value PatternSolid
0139  * \value PatternMediumGray
0140  * \value PatternDarkGray
0141  * \value PatternLightGray
0142  * \value PatternDarkHorizontal
0143  * \value PatternDarkVertical
0144  * \value PatternDarkDown
0145  * \value PatternDarkUp
0146  * \value PatternDarkGrid
0147  * \value PatternDarkTrellis
0148  * \value PatternLightHorizontal
0149  * \value PatternLightVertical
0150  * \value PatternLightDown
0151  * \value PatternLightUp
0152  * \value PatternLightTrellis
0153  * \value PatternGray125
0154  * \value PatternGray0625
0155  * \value PatternLightGrid
0156  */
0157 
0158 /*!
0159  *  Creates a new invalid format.
0160  */
0161 Format::Format()
0162 {
0163     //The d pointer is initialized with a null pointer
0164 }
0165 
0166 /*!
0167    Creates a new format with the same attributes as the \a other format.
0168  */
0169 Format::Format(const Format &other)
0170     :d(other.d)
0171 {
0172 
0173 }
0174 
0175 /*!
0176    Assigns the \a other format to this format, and returns a
0177    reference to this format.
0178  */
0179 Format &Format::operator =(const Format &other)
0180 {
0181     d = other.d;
0182     return *this;
0183 }
0184 
0185 /*!
0186  * Destroys this format.
0187  */
0188 Format::~Format()
0189 {
0190 }
0191 
0192 /*!
0193  * Returns the number format identifier.
0194  */
0195 int Format::numberFormatIndex() const
0196 {
0197     return intProperty(FormatPrivate::P_NumFmt_Id, 0);
0198 }
0199 
0200 /*!
0201  * Set the number format identifier. The \a format
0202  * must be a valid built-in number format identifier
0203  * or the identifier of a custom number format.
0204  */
0205 void Format::setNumberFormatIndex(int format)
0206 {
0207     setProperty(FormatPrivate::P_NumFmt_Id, format);
0208     clearProperty(FormatPrivate::P_NumFmt_FormatCode);
0209 }
0210 
0211 /*!
0212  * Returns the number format string.
0213  * \note for built-in number formats, this may
0214  * return an empty string.
0215  */
0216 QString Format::numberFormat() const
0217 {
0218     return stringProperty(FormatPrivate::P_NumFmt_FormatCode);
0219 }
0220 
0221 /*!
0222  * Set number \a format.
0223  * http://office.microsoft.com/en-001/excel-help/create-a-custom-number-format-HP010342372.aspx
0224  */
0225 void Format::setNumberFormat(const QString &format)
0226 {
0227     if (format.isEmpty())
0228         return;
0229     setProperty(FormatPrivate::P_NumFmt_FormatCode, format);
0230     clearProperty(FormatPrivate::P_NumFmt_Id); //numFmt id must be re-generated.
0231 }
0232 
0233 /*!
0234  * Returns whether the number format is probably a dateTime or not
0235  */
0236 bool Format::isDateTimeFormat() const
0237 {
0238     //NOTICE:
0239 
0240     if (hasProperty(FormatPrivate::P_NumFmt_FormatCode)) 
0241     {
0242         //Custom numFmt, so
0243         //Gauss from the number string
0244         return NumFormatParser::isDateTime(numberFormat());
0245     } 
0246     else if (hasProperty(FormatPrivate::P_NumFmt_Id))
0247     {
0248         //Non-custom numFmt
0249         int idx = numberFormatIndex();
0250 
0251         //Is built-in date time number id?
0252         if ((idx >= 14 && idx <= 22) || (idx >= 45 && idx <= 47))
0253             return true;
0254 
0255         if ((idx >= 27 && idx <= 36) || (idx >= 50 && idx <= 58)) //Used in CHS\CHT\JPN\KOR
0256             return true;
0257     }
0258 
0259     return false;
0260 }
0261 
0262 /*!
0263     \internal
0264     Set a custom num \a format with the given \a id.
0265  */
0266 void Format::setNumberFormat(int id, const QString &format)
0267 {
0268     setProperty(FormatPrivate::P_NumFmt_Id, id);
0269     setProperty(FormatPrivate::P_NumFmt_FormatCode, format);
0270 }
0271 
0272 /*!
0273     \internal
0274     Called by styles to fix the numFmt
0275  */
0276 void Format::fixNumberFormat(int id, const QString &format)
0277 {
0278     setProperty(FormatPrivate::P_NumFmt_Id, id, 0, false);
0279     setProperty(FormatPrivate::P_NumFmt_FormatCode, format, QString(), false);
0280 }
0281 
0282 /*!
0283     \internal
0284     Return true if the format has number format.
0285  */
0286 bool Format::hasNumFmtData() const
0287 {
0288     if (!d)
0289         return false;
0290 
0291     if ( hasProperty(FormatPrivate::P_NumFmt_Id) ||
0292          hasProperty(FormatPrivate::P_NumFmt_FormatCode) )
0293     {
0294         return true;
0295     }
0296     return false;
0297 }
0298 
0299 /*!
0300  * Return the size of the font in points.
0301  */
0302 int Format::fontSize() const
0303 {
0304     return intProperty(FormatPrivate::P_Font_Size);
0305 }
0306 
0307 /*!
0308  * Set the \a size of the font in points.
0309  */
0310 void Format::setFontSize(int size)
0311 {
0312     setProperty(FormatPrivate::P_Font_Size, size, 0);
0313 }
0314 
0315 /*!
0316  * Return whether the font is italic.
0317  */
0318 bool Format::fontItalic() const
0319 {
0320     return boolProperty(FormatPrivate::P_Font_Italic);
0321 }
0322 
0323 /*!
0324  * Turn on/off the italic font based on \a italic.
0325  */
0326 void Format::setFontItalic(bool italic)
0327 {
0328     setProperty(FormatPrivate::P_Font_Italic, italic, false);
0329 }
0330 
0331 /*!
0332  * Return whether the font is strikeout.
0333  */
0334 bool Format::fontStrikeOut() const
0335 {
0336     return boolProperty(FormatPrivate::P_Font_StrikeOut);
0337 }
0338 
0339 /*!
0340  * Turn on/off the strikeOut font based on \a strikeOut.
0341  */
0342 void Format::setFontStrikeOut(bool strikeOut)
0343 {
0344     setProperty(FormatPrivate::P_Font_StrikeOut, strikeOut, false);
0345 }
0346 
0347 /*!
0348  * Return the color of the font.
0349  */
0350 QColor Format::fontColor() const
0351 {
0352     if (hasProperty(FormatPrivate::P_Font_Color))
0353         return colorProperty(FormatPrivate::P_Font_Color);
0354     return QColor();
0355 }
0356 
0357 /*!
0358  * Set the \a color of the font.
0359  */
0360 void Format::setFontColor(const QColor &color)
0361 {
0362     setProperty(FormatPrivate::P_Font_Color, XlsxColor(color), XlsxColor());
0363 }
0364 
0365 /*!
0366  * Return whether the font is bold.
0367  */
0368 bool Format::fontBold() const
0369 {
0370     return boolProperty(FormatPrivate::P_Font_Bold);
0371 }
0372 
0373 /*!
0374  * Turn on/off the bold font based on the given \a bold.
0375  */
0376 void Format::setFontBold(bool bold)
0377 {
0378     setProperty(FormatPrivate::P_Font_Bold, bold, false);
0379 }
0380 
0381 /*!
0382  * Return the script style of the font.
0383  */
0384 Format::FontScript Format::fontScript() const
0385 {
0386     return static_cast<Format::FontScript>(intProperty(FormatPrivate::P_Font_Script));
0387 }
0388 
0389 /*!
0390  * Set the script style of the font to \a script.
0391  */
0392 void Format::setFontScript(FontScript script)
0393 {
0394     setProperty(FormatPrivate::P_Font_Script, script, FontScriptNormal);
0395 }
0396 
0397 /*!
0398  * Return the underline style of the font.
0399  */
0400 Format::FontUnderline Format::fontUnderline() const
0401 {
0402     return static_cast<Format::FontUnderline>(intProperty(FormatPrivate::P_Font_Underline));
0403 }
0404 
0405 /*!
0406  * Set the underline style of the font to \a underline.
0407  */
0408 void Format::setFontUnderline(FontUnderline underline)
0409 {
0410     setProperty(FormatPrivate::P_Font_Underline, underline, FontUnderlineNone);
0411 }
0412 
0413 /*!
0414  * Return whether the font is outline.
0415  */
0416 bool Format::fontOutline() const
0417 {
0418     return boolProperty(FormatPrivate::P_Font_Outline);
0419 }
0420 
0421 /*!
0422  * Turn on/off the outline font based on \a outline.
0423  */
0424 void Format::setFontOutline(bool outline)
0425 {
0426     setProperty(FormatPrivate::P_Font_Outline, outline, false);
0427 }
0428 
0429 /*!
0430  * Return the name of the font.
0431  */
0432 QString Format::fontName() const
0433 {
0434     return stringProperty(FormatPrivate::P_Font_Name, QStringLiteral("Calibri"));
0435 }
0436 
0437 /*!
0438  * Set the name of the font to \a name.
0439  */
0440 void Format::setFontName(const QString &name)
0441 {
0442     setProperty(FormatPrivate::P_Font_Name, name, QStringLiteral("Calibri"));
0443 }
0444 
0445 /*!
0446  * Returns a QFont object based on font data contained in the format.
0447  */
0448 QFont Format::font() const
0449 {
0450    QFont font;
0451    font.setFamily(fontName());
0452    if (fontSize() > 0)
0453        font.setPointSize(fontSize());
0454    font.setBold(fontBold());
0455    font.setItalic(fontItalic());
0456    font.setUnderline(fontUnderline()!=FontUnderlineNone);
0457    font.setStrikeOut(fontStrikeOut());
0458    return font;
0459 }
0460 
0461 /*!
0462  * Set the format properties from the given \a font.
0463  */
0464 void Format::setFont(const QFont &font)
0465 {
0466     setFontName(font.family());
0467     if (font.pointSize() > 0)
0468         setFontSize(font.pointSize());
0469     setFontBold(font.bold());
0470     setFontItalic(font.italic());
0471     setFontUnderline(font.underline() ? FontUnderlineSingle : FontUnderlineNone);
0472     setFontStrikeOut(font.strikeOut());
0473 }
0474 
0475 /*!
0476  * \internal
0477  * When the format has font data, when need to assign a valid index for it.
0478  * The index value is depend on the order <fonts > in styles.xml
0479  */
0480 bool Format::fontIndexValid() const
0481 {
0482     if (!hasFontData())
0483         return false;
0484     return d->font_index_valid;
0485 }
0486 
0487 /*!
0488  * \internal
0489  */
0490 int Format::fontIndex() const
0491 {
0492     if (fontIndexValid())
0493         return d->font_index;
0494 
0495     return 0;
0496 }
0497 
0498 /*!
0499  * \internal
0500  */
0501 void Format::setFontIndex(int index)
0502 {
0503     d->font_index = index;
0504     d->font_index_valid = true;
0505 }
0506 
0507 /*!
0508  * \internal
0509  */
0510 QByteArray Format::fontKey() const
0511 {
0512     if (isEmpty())
0513         return QByteArray();
0514 
0515     if (d->font_dirty) {
0516         QByteArray key;
0517         QDataStream stream(&key, QIODevice::WriteOnly);
0518         for (int i=FormatPrivate::P_Font_STARTID; i<FormatPrivate::P_Font_ENDID; ++i) {
0519             auto it = d->properties.constFind(i);
0520             if (it != d->properties.constEnd())
0521                 stream << i << it.value();
0522         };
0523 
0524         const_cast<Format*>(this)->d->font_key = key;
0525         const_cast<Format*>(this)->d->font_dirty = false;
0526     }
0527 
0528     return d->font_key;
0529 }
0530 
0531 /*!
0532     \internal
0533     Return true if the format has font format, otherwise return false.
0534  */
0535 bool Format::hasFontData() const
0536 {
0537     if (!d)
0538         return false;
0539 
0540     for (int i=FormatPrivate::P_Font_STARTID; i<FormatPrivate::P_Font_ENDID; ++i) {
0541         if (hasProperty(i))
0542             return true;
0543     }
0544     return false;
0545 }
0546 
0547 /*!
0548  * Return the horizontal alignment.
0549  */
0550 Format::HorizontalAlignment Format::horizontalAlignment() const
0551 {
0552     return static_cast<Format::HorizontalAlignment>(intProperty(FormatPrivate::P_Alignment_AlignH, AlignHGeneral));
0553 }
0554 
0555 /*!
0556  * Set the horizontal alignment with the given \a align.
0557  */
0558 void Format::setHorizontalAlignment(HorizontalAlignment align)
0559 {
0560     if (hasProperty(FormatPrivate::P_Alignment_Indent)
0561             &&(align != AlignHGeneral && align != AlignLeft && align != AlignRight && align != AlignHDistributed)) {
0562         clearProperty(FormatPrivate::P_Alignment_Indent);
0563     }
0564 
0565     if (hasProperty(FormatPrivate::P_Alignment_ShinkToFit)
0566             && (align == AlignHFill || align == AlignHJustify || align == AlignHDistributed)) {
0567         clearProperty(FormatPrivate::P_Alignment_ShinkToFit);
0568     }
0569 
0570     setProperty(FormatPrivate::P_Alignment_AlignH, align, AlignHGeneral);
0571 }
0572 
0573 /*!
0574  * Return the vertical alignment.
0575  */
0576 Format::VerticalAlignment Format::verticalAlignment() const
0577 {
0578     return static_cast<Format::VerticalAlignment>(intProperty(FormatPrivate::P_Alignment_AlignV, AlignBottom));
0579 }
0580 
0581 /*!
0582  * Set the vertical alignment with the given \a align.
0583  */
0584 void Format::setVerticalAlignment(VerticalAlignment align)
0585 {
0586     setProperty(FormatPrivate::P_Alignment_AlignV, align, AlignBottom);
0587 }
0588 
0589 /*!
0590  * Return whether the cell text is wrapped.
0591  */
0592 bool Format::textWrap() const
0593 {
0594     return boolProperty(FormatPrivate::P_Alignment_Wrap);
0595 }
0596 
0597 /*!
0598  * Enable the text wrap if \a wrap is true.
0599  */
0600 void Format::setTextWrap(bool wrap)
0601 {
0602     if (wrap && hasProperty(FormatPrivate::P_Alignment_ShinkToFit))
0603         clearProperty(FormatPrivate::P_Alignment_ShinkToFit);
0604 
0605     setProperty(FormatPrivate::P_Alignment_Wrap, wrap, false);
0606 }
0607 
0608 /*!
0609  * Return the text rotation.
0610  */
0611 int Format::rotation() const
0612 {
0613     return intProperty(FormatPrivate::P_Alignment_Rotation);
0614 }
0615 
0616 /*!
0617  * Set the text roation with the given \a rotation. Must be in the range [0, 180] or 255.
0618  */
0619 void Format::setRotation(int rotation)
0620 {
0621     setProperty(FormatPrivate::P_Alignment_Rotation, rotation, 0);
0622 }
0623 
0624 /*!
0625  * Return the text indentation level.
0626  */
0627 int Format::indent() const
0628 {
0629     return intProperty(FormatPrivate::P_Alignment_Indent);
0630 }
0631 
0632 /*!
0633  * Set the text indentation level with the given \a indent. Must be less than or equal to 15.
0634  */
0635 void Format::setIndent(int indent)
0636 {
0637     if (indent && hasProperty(FormatPrivate::P_Alignment_AlignH)) {
0638         HorizontalAlignment hl = horizontalAlignment();
0639 
0640         if (hl != AlignHGeneral && hl != AlignLeft && hl!= AlignRight && hl!= AlignHJustify) {
0641             setHorizontalAlignment(AlignLeft);
0642         }
0643     }
0644 
0645     setProperty(FormatPrivate::P_Alignment_Indent, indent, 0);
0646 }
0647 
0648 /*!
0649  * Return whether the cell is shrink to fit.
0650  */
0651 bool Format::shrinkToFit() const
0652 {
0653     return boolProperty(FormatPrivate::P_Alignment_ShinkToFit);
0654 }
0655 
0656 /*!
0657  * Turn on/off shrink to fit base on \a shink.
0658  */
0659 void Format::setShrinkToFit(bool shink)
0660 {
0661     if (shink && hasProperty(FormatPrivate::P_Alignment_Wrap))
0662         clearProperty(FormatPrivate::P_Alignment_Wrap);
0663 
0664     if (shink && hasProperty(FormatPrivate::P_Alignment_AlignH)) {
0665         HorizontalAlignment hl = horizontalAlignment();
0666         if (hl == AlignHFill || hl == AlignHJustify || hl == AlignHDistributed)
0667             setHorizontalAlignment(AlignLeft);
0668     }
0669 
0670     setProperty(FormatPrivate::P_Alignment_ShinkToFit, shink, false);
0671 }
0672 
0673 /*!
0674  * \internal
0675  */
0676 bool Format::hasAlignmentData() const
0677 {
0678     if (!d)
0679         return false;
0680 
0681     for (int i=FormatPrivate::P_Alignment_STARTID; i<FormatPrivate::P_Alignment_ENDID; ++i) {
0682         if (hasProperty(i))
0683             return true;
0684     }
0685     return false;
0686 }
0687 
0688 /*!
0689  * Set the border style with the given \a style.
0690  */
0691 void Format::setBorderStyle(BorderStyle style)
0692 {
0693     setLeftBorderStyle(style);
0694     setRightBorderStyle(style);
0695     setBottomBorderStyle(style);
0696     setTopBorderStyle(style);
0697 }
0698 
0699 /*!
0700  * Sets the border color with the given \a color.
0701  */
0702 void Format::setBorderColor(const QColor &color)
0703 {
0704     setLeftBorderColor(color);
0705     setRightBorderColor(color);
0706     setTopBorderColor(color);
0707     setBottomBorderColor(color);
0708 }
0709 
0710 /*!
0711  * Returns the left border style
0712  */
0713 Format::BorderStyle Format::leftBorderStyle() const
0714 {
0715     return static_cast<BorderStyle>(intProperty(FormatPrivate::P_Border_LeftStyle));
0716 }
0717 
0718 /*!
0719  * Sets the left border style to \a style
0720  */
0721 void Format::setLeftBorderStyle(BorderStyle style)
0722 {
0723     setProperty(FormatPrivate::P_Border_LeftStyle, style, BorderNone);
0724 }
0725 
0726 /*!
0727  * Returns the left border color
0728  */
0729 QColor Format::leftBorderColor() const
0730 {
0731     return colorProperty(FormatPrivate::P_Border_LeftColor);
0732 }
0733 
0734 /*!
0735     Sets the left border color to the given \a color
0736 */
0737 void Format::setLeftBorderColor(const QColor &color)
0738 {
0739     setProperty(FormatPrivate::P_Border_LeftColor, XlsxColor(color), XlsxColor());
0740 }
0741 
0742 /*!
0743     Returns the right border style.
0744 */
0745 Format::BorderStyle Format::rightBorderStyle() const
0746 {
0747     return static_cast<BorderStyle>(intProperty(FormatPrivate::P_Border_RightStyle));
0748 }
0749 
0750 /*!
0751     Sets the right border style to the given \a style.
0752 */
0753 void Format::setRightBorderStyle(BorderStyle style)
0754 {
0755     setProperty(FormatPrivate::P_Border_RightStyle, style, BorderNone);
0756 }
0757 
0758 /*!
0759     Returns the right border color.
0760 */
0761 QColor Format::rightBorderColor() const
0762 {
0763     return colorProperty(FormatPrivate::P_Border_RightColor);
0764 }
0765 
0766 /*!
0767     Sets the right border color to the given \a color
0768 */
0769 void Format::setRightBorderColor(const QColor &color)
0770 {
0771     setProperty(FormatPrivate::P_Border_RightColor, XlsxColor(color), XlsxColor());
0772 }
0773 
0774 /*!
0775     Returns the top border style.
0776 */
0777 Format::BorderStyle Format::topBorderStyle() const
0778 {
0779     return static_cast<BorderStyle>(intProperty(FormatPrivate::P_Border_TopStyle));
0780 }
0781 
0782 /*!
0783     Sets the top border style to the given \a style.
0784 */
0785 void Format::setTopBorderStyle(BorderStyle style)
0786 {
0787     setProperty(FormatPrivate::P_Border_TopStyle, style, BorderNone);
0788 }
0789 
0790 /*!
0791     Returns the top border color.
0792 */
0793 QColor Format::topBorderColor() const
0794 {
0795     return colorProperty(FormatPrivate::P_Border_TopColor);
0796 }
0797 
0798 /*!
0799     Sets the top border color to the given \a color.
0800 */
0801 void Format::setTopBorderColor(const QColor &color)
0802 {
0803     setProperty(FormatPrivate::P_Border_TopColor, XlsxColor(color), XlsxColor());
0804 }
0805 
0806 /*!
0807     Returns the bottom border style.
0808 */
0809 Format::BorderStyle Format::bottomBorderStyle() const
0810 {
0811     return static_cast<BorderStyle>(intProperty(FormatPrivate::P_Border_BottomStyle));
0812 }
0813 
0814 /*!
0815     Sets the bottom border style to the given \a style.
0816 */
0817 void Format::setBottomBorderStyle(BorderStyle style)
0818 {
0819     setProperty(FormatPrivate::P_Border_BottomStyle, style, BorderNone);
0820 }
0821 
0822 /*!
0823     Returns the bottom border color.
0824 */
0825 QColor Format::bottomBorderColor() const
0826 {
0827     return colorProperty(FormatPrivate::P_Border_BottomColor);
0828 }
0829 
0830 /*!
0831     Sets the bottom border color to the given \a color.
0832 */
0833 void Format::setBottomBorderColor(const QColor &color)
0834 {
0835     setProperty(FormatPrivate::P_Border_BottomColor, XlsxColor(color), XlsxColor());
0836 }
0837 
0838 /*!
0839     Return the diagonla border style.
0840 */
0841 Format::BorderStyle Format::diagonalBorderStyle() const
0842 {
0843     return static_cast<BorderStyle>(intProperty(FormatPrivate::P_Border_DiagonalStyle));
0844 }
0845 
0846 /*!
0847     Sets the diagonal border style to the given \a style.
0848 */
0849 void Format::setDiagonalBorderStyle(BorderStyle style)
0850 {
0851     setProperty(FormatPrivate::P_Border_DiagonalStyle, style, BorderNone);
0852 }
0853 
0854 /*!
0855     Returns the diagonal border type.
0856 */
0857 Format::DiagonalBorderType Format::diagonalBorderType() const
0858 {
0859     return static_cast<DiagonalBorderType>(intProperty(FormatPrivate::P_Border_DiagonalType));
0860 }
0861 
0862 /*!
0863     Sets the diagonal border type to the given \a style
0864 */
0865 void Format::setDiagonalBorderType(DiagonalBorderType style)
0866 {
0867     setProperty(FormatPrivate::P_Border_DiagonalType, style, DiagonalBorderNone);
0868 }
0869 
0870 /*!
0871     Returns the diagonal border color.
0872 */
0873 QColor Format::diagonalBorderColor() const
0874 {
0875     return colorProperty(FormatPrivate::P_Border_DiagonalColor);
0876 }
0877 
0878 /*!
0879     Sets the diagonal border color to the given \a color
0880 */
0881 void Format::setDiagonalBorderColor(const QColor &color)
0882 {
0883     setProperty(FormatPrivate::P_Border_DiagonalColor, XlsxColor(color), XlsxColor());
0884 }
0885 
0886 /*!
0887     \internal
0888     Returns whether this format has been set valid border index.
0889 */
0890 bool Format::borderIndexValid() const
0891 {
0892     if (!hasBorderData())
0893         return false;
0894     return d->border_index_valid;
0895 }
0896 
0897 /*!
0898     \internal
0899     Returns the border index.
0900 */
0901 int Format::borderIndex() const
0902 {
0903     if (borderIndexValid())
0904         return d->border_index;
0905     return 0;
0906 }
0907 
0908 /*!
0909  * \internal
0910  */
0911 void Format::setBorderIndex(int index)
0912 {
0913     d->border_index = index;
0914     d->border_index_valid = true;
0915 }
0916 
0917 /*! \internal
0918  */
0919 QByteArray Format::borderKey() const
0920 {
0921     if (isEmpty())
0922         return QByteArray();
0923 
0924     if (d->border_dirty) {
0925         QByteArray key;
0926         QDataStream stream(&key, QIODevice::WriteOnly);
0927         for (int i=FormatPrivate::P_Border_STARTID; i<FormatPrivate::P_Border_ENDID; ++i) {
0928             auto it = d->properties.constFind(i);
0929             if (it != d->properties.constEnd())
0930                 stream << i << it.value();
0931         };
0932 
0933         const_cast<Format*>(this)->d->border_key = key;
0934         const_cast<Format*>(this)->d->border_dirty = false;
0935     }
0936 
0937     return d->border_key;
0938 }
0939 
0940 /*!
0941     \internal
0942     Return true if the format has border format, otherwise return false.
0943  */
0944 bool Format::hasBorderData() const
0945 {
0946     if (!d)
0947         return false;
0948 
0949     for (int i=FormatPrivate::P_Border_STARTID; i<FormatPrivate::P_Border_ENDID; ++i) {
0950         if (hasProperty(i))
0951             return true;
0952     }
0953     return false;
0954 }
0955 
0956 /*!
0957     Return the fill pattern.
0958 */
0959 Format::FillPattern Format::fillPattern() const
0960 {
0961     return static_cast<FillPattern>(intProperty(FormatPrivate::P_Fill_Pattern, PatternNone));
0962 }
0963 
0964 /*!
0965     Sets the fill pattern to the given \a pattern.
0966 */
0967 void Format::setFillPattern(FillPattern pattern)
0968 {
0969     setProperty(FormatPrivate::P_Fill_Pattern, pattern, PatternNone);
0970 }
0971 
0972 /*!
0973     Returns the foreground color of the pattern.
0974 */
0975 QColor Format::patternForegroundColor() const
0976 {
0977     return colorProperty(FormatPrivate::P_Fill_FgColor);
0978 }
0979 
0980 /*!
0981     Sets the foreground color of the pattern with the given \a color.
0982 */
0983 void Format::setPatternForegroundColor(const QColor &color)
0984 {
0985     if (color.isValid() && !hasProperty(FormatPrivate::P_Fill_Pattern))
0986         setFillPattern(PatternSolid);
0987     setProperty(FormatPrivate::P_Fill_FgColor, XlsxColor(color), XlsxColor());
0988 }
0989 
0990 /*!
0991     Returns the background color of the pattern.
0992 */
0993 QColor Format::patternBackgroundColor() const
0994 {
0995     return colorProperty(FormatPrivate::P_Fill_BgColor);
0996 }
0997 
0998 /*!
0999     Sets the background color of the pattern with the given \a color.
1000 */
1001 void Format::setPatternBackgroundColor(const QColor &color)
1002 {
1003     if (color.isValid() && !hasProperty(FormatPrivate::P_Fill_Pattern))
1004         setFillPattern(PatternSolid);
1005     setProperty(FormatPrivate::P_Fill_BgColor, XlsxColor(color), XlsxColor());
1006 }
1007 
1008 /*!
1009  * \internal
1010  */
1011 bool Format::fillIndexValid() const
1012 {
1013     if (!hasFillData())
1014         return false;
1015     return d->fill_index_valid;
1016 }
1017 
1018 /*!
1019  * \internal
1020  */
1021 int Format::fillIndex() const
1022 {
1023     if (fillIndexValid())
1024         return d->fill_index;
1025     return 0;
1026 }
1027 
1028 /*!
1029  * \internal
1030  */
1031 void Format::setFillIndex(int index)
1032 {
1033     d->fill_index = index;
1034     d->fill_index_valid = true;
1035 }
1036 
1037 /*!
1038  * \internal
1039  */
1040 QByteArray Format::fillKey() const
1041 {
1042     if (isEmpty())
1043         return QByteArray();
1044 
1045     if (d->fill_dirty) {
1046         QByteArray key;
1047         QDataStream stream(&key, QIODevice::WriteOnly);
1048         for (int i=FormatPrivate::P_Fill_STARTID; i<FormatPrivate::P_Fill_ENDID; ++i) {
1049             auto it = d->properties.constFind(i);
1050             if (it != d->properties.constEnd())
1051                 stream << i << it.value();
1052         };
1053 
1054         const_cast<Format*>(this)->d->fill_key = key;
1055         const_cast<Format*>(this)->d->fill_dirty = false;
1056     }
1057 
1058     return d->fill_key;
1059 }
1060 
1061 /*!
1062     \internal
1063     Return true if the format has fill format, otherwise return false.
1064  */
1065 bool Format::hasFillData() const
1066 {
1067     if (!d)
1068         return false;
1069 
1070     for (int i=FormatPrivate::P_Fill_STARTID; i<FormatPrivate::P_Fill_ENDID; ++i) {
1071         if (hasProperty(i))
1072             return true;
1073     }
1074     return false;
1075 }
1076 
1077 /*!
1078     Returns whether the hidden protection property is set to true.
1079 */
1080 bool Format::hidden() const
1081 {
1082     return boolProperty(FormatPrivate::P_Protection_Hidden);
1083 }
1084 
1085 /*!
1086     Sets the hidden protection property with the given \a hidden.
1087 */
1088 void Format::setHidden(bool hidden)
1089 {
1090     setProperty(FormatPrivate::P_Protection_Hidden, hidden);
1091 }
1092 
1093 /*!
1094     Returns whether the locked protection property is set to true.
1095 */
1096 bool Format::locked() const
1097 {
1098     return boolProperty(FormatPrivate::P_Protection_Locked);
1099 }
1100 
1101 /*!
1102     Sets the locked protection property with the given \a locked.
1103 */
1104 void Format::setLocked(bool locked)
1105 {
1106     setProperty(FormatPrivate::P_Protection_Locked, locked);
1107 }
1108 
1109 /*!
1110     \internal
1111     Return true if the format has protection data, otherwise return false.
1112  */
1113 bool Format::hasProtectionData() const
1114 {
1115     if (!d)
1116         return false;
1117 
1118     if (hasProperty(FormatPrivate::P_Protection_Hidden)
1119             || hasProperty(FormatPrivate::P_Protection_Locked)) {
1120         return true;
1121     }
1122     return false;
1123 }
1124 
1125 /*!
1126     Merges the current format with the properties described by format \a modifier.
1127  */
1128 void Format::mergeFormat(const Format &modifier)
1129 {
1130     if (!modifier.isValid())
1131         return;
1132 
1133     if (!isValid()) {
1134         d = modifier.d;
1135         return;
1136     }
1137 
1138     QMapIterator<int, QVariant> it(modifier.d->properties);
1139     while(it.hasNext()) {
1140         it.next();
1141         setProperty(it.key(), it.value());
1142     }
1143 }
1144 
1145 /*!
1146     Returns true if the format is valid; otherwise returns false.
1147  */
1148 bool Format::isValid() const
1149 {
1150     if (d)
1151         return true;
1152     return false;
1153 }
1154 
1155 /*!
1156     Returns true if the format is empty; otherwise returns false.
1157  */
1158 bool Format::isEmpty() const
1159 {
1160     if (!d)
1161         return true;
1162     return d->properties.isEmpty();
1163 }
1164 
1165 /*!
1166  * \internal
1167  */
1168 QByteArray Format::formatKey() const
1169 {
1170     if (isEmpty())
1171         return QByteArray();
1172 
1173     if (d->dirty) {
1174         QByteArray key;
1175         QDataStream stream(&key, QIODevice::WriteOnly);
1176 
1177         QMapIterator<int, QVariant> i(d->properties);
1178         while (i.hasNext()) {
1179             i.next();
1180             stream<<i.key()<<i.value();
1181         }
1182 
1183         d->formatKey = key;
1184         d->dirty = false;
1185     }
1186 
1187     return d->formatKey;
1188 }
1189 
1190 /*!
1191  * \internal
1192  *  Called by QXlsx::Styles or some unittests.
1193  */
1194 void Format::setXfIndex(int index)
1195 {
1196     if (!d)
1197         d = new FormatPrivate;
1198     d->xf_index = index;
1199     d->xf_indexValid = true;
1200 }
1201 
1202 /*!
1203  * \internal
1204  */
1205 int Format::xfIndex() const
1206 {
1207     if (!d)
1208         return -1;
1209     return d->xf_index;
1210 }
1211 
1212 /*!
1213  * \internal
1214  */
1215 bool Format::xfIndexValid() const
1216 {
1217     if (!d)
1218         return false;
1219     return d->xf_indexValid;
1220 }
1221 
1222 /*!
1223  * \internal
1224  *  Called by QXlsx::Styles or some unittests.
1225  */
1226 void Format::setDxfIndex(int index)
1227 {
1228     if (!d)
1229         d = new FormatPrivate;
1230     d->dxf_index = index;
1231     d->dxf_indexValid = true;
1232 }
1233 
1234 /*!
1235  * \internal
1236  * Returns the index in the styles dxfs.
1237  */
1238 int Format::dxfIndex() const
1239 {
1240     if (!d)
1241         return -1;
1242     return d->dxf_index;
1243 }
1244 
1245 /*!
1246  * \internal
1247  * Returns whether the dxf index is valid or not.
1248  */
1249 bool Format::dxfIndexValid() const
1250 {
1251     if (!d)
1252         return false;
1253     return d->dxf_indexValid;
1254 }
1255 
1256 /*!
1257     Returns ture if the \a format is equal to this format.
1258 */
1259 bool Format::operator ==(const Format &format) const
1260 {
1261     return this->formatKey() == format.formatKey();
1262 }
1263 
1264 /*!
1265     Returns ture if the \a format is not equal to this format.
1266 */
1267 bool Format::operator !=(const Format &format) const
1268 {
1269     return this->formatKey() != format.formatKey();
1270 }
1271 
1272 int Format::theme() const
1273 {
1274     return d->theme;
1275 }
1276 
1277 /*!
1278  * \internal
1279  */
1280 QVariant Format::property(int propertyId, const QVariant &defaultValue) const
1281 {
1282     if (d) {
1283         auto it = d->properties.constFind(propertyId);
1284         if (it != d->properties.constEnd())
1285             return it.value();
1286     }
1287     return defaultValue;
1288 }
1289 
1290 /*!
1291  * \internal
1292  */
1293 void Format::setProperty(int propertyId, const QVariant &value, const QVariant &clearValue, bool detach)
1294 {
1295     if (!d)
1296         d = new FormatPrivate;
1297 
1298     if (value != clearValue)
1299     {
1300         auto it = d->properties.constFind(propertyId);
1301         if (it != d->properties.constEnd() && it.value() == value)
1302             return;
1303 
1304         if (detach)
1305             d.detach();
1306 
1307         d->properties[propertyId] = value;
1308     }
1309     else
1310     {
1311         if (!d->properties.contains(propertyId))
1312             return;
1313 
1314         if (detach)
1315             d.detach();
1316 
1317         d->properties.remove(propertyId);
1318     }
1319 
1320     d->dirty = true;
1321     d->xf_indexValid = false;
1322     d->dxf_indexValid = false;
1323 
1324     if (propertyId >= FormatPrivate::P_Font_STARTID && propertyId < FormatPrivate::P_Font_ENDID)
1325     {
1326         d->font_dirty = true;
1327         d->font_index_valid = false;
1328     }
1329     else if (propertyId >= FormatPrivate::P_Border_STARTID && propertyId < FormatPrivate::P_Border_ENDID)
1330     {
1331         d->border_dirty = true;
1332         d->border_index_valid = false;
1333     }
1334     else if (propertyId >= FormatPrivate::P_Fill_STARTID && propertyId < FormatPrivate::P_Fill_ENDID)
1335     {
1336         d->fill_dirty = true;
1337         d->fill_index_valid = false;
1338     }
1339 }
1340 
1341 /*!
1342  * \internal
1343  */
1344 void Format::clearProperty(int propertyId)
1345 {
1346     setProperty(propertyId, QVariant());
1347 }
1348 
1349 /*!
1350  * \internal
1351  */
1352 bool Format::hasProperty(int propertyId) const
1353 {
1354     if (!d)
1355         return false;
1356     return d->properties.contains(propertyId);
1357 }
1358 
1359 /*!
1360  * \internal
1361  */
1362 bool Format::boolProperty(int propertyId, bool defaultValue) const
1363 {
1364     if (!hasProperty(propertyId))
1365         return defaultValue;
1366 
1367     const QVariant prop = d->properties[propertyId];
1368     if (prop.userType() != QMetaType::Bool)
1369         return defaultValue;
1370     return prop.toBool();
1371 }
1372 
1373 /*!
1374  * \internal
1375  */
1376 int Format::intProperty(int propertyId, int defaultValue) const
1377 {
1378     if (!hasProperty(propertyId))
1379         return defaultValue;
1380 
1381     const QVariant prop = d->properties[propertyId];
1382     if (prop.userType() != QMetaType::Int)
1383         return defaultValue;
1384     return prop.toInt();
1385 }
1386 
1387 /*!
1388  * \internal
1389  */
1390 double Format::doubleProperty(int propertyId, double defaultValue) const
1391 {
1392     if (!hasProperty(propertyId))
1393         return defaultValue;
1394 
1395     const QVariant prop = d->properties[propertyId];
1396     if (prop.userType() != QMetaType::Double && prop.userType() != QMetaType::Float)
1397         return defaultValue;
1398     return prop.toDouble();
1399 }
1400 
1401 /*!
1402  * \internal
1403  */
1404 QString Format::stringProperty(int propertyId, const QString &defaultValue) const
1405 {
1406     if (!hasProperty(propertyId))
1407         return defaultValue;
1408 
1409     const QVariant prop = d->properties[propertyId];
1410     if (prop.userType() != QMetaType::QString)
1411         return defaultValue;
1412     return prop.toString();
1413 }
1414 
1415 /*!
1416  * \internal
1417  */
1418 QColor Format::colorProperty(int propertyId, const QColor &defaultValue) const
1419 {
1420     if (!hasProperty(propertyId))
1421         return defaultValue;
1422 
1423     const QVariant prop = d->properties[propertyId];
1424     if (prop.userType() != qMetaTypeId<XlsxColor>())
1425         return defaultValue;
1426     return qvariant_cast<XlsxColor>(prop).rgbColor();
1427 }
1428 
1429 #ifndef QT_NO_DEBUG_STREAM
1430 QDebug operator<<(QDebug dbg, const Format &f)
1431 {
1432     dbg.nospace() << "QXlsx::Format(" << f.d->properties << ")";
1433     return dbg.space();
1434 }
1435 #endif
1436 
1437 QT_END_NAMESPACE_XLSX