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