File indexing completed on 2024-04-28 16:21:32

0001 /* This file is part of the KDE project
0002    Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org>
0003    Copyright 2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
0004    Copyright 2003 Norbert Andres <nandres@web.de>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This library is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this library; see the file COPYING.LIB.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019    Boston, MA 02110-1301, USA.
0020 */
0021 
0022 // Local
0023 #include "Style.h"
0024 
0025 #include <QBrush>
0026 #include <QHash>
0027 #include <QPen>
0028 #include <QFontDatabase>
0029 
0030 #include <KoGlobal.h>
0031 
0032 #include "SheetsDebug.h"
0033 #include "Currency.h"
0034 #include "Global.h"
0035 #include "StyleManager.h"
0036 #include "Util.h"
0037 
0038 using namespace Calligra::Sheets;
0039 
0040 /////////////////////////////////////////////////////////////////////////////
0041 //
0042 // SubStyles
0043 //
0044 /////////////////////////////////////////////////////////////////////////////
0045 
0046 namespace Calligra
0047 {
0048 namespace Sheets
0049 {
0050 
0051 static uint calculateValue(QPen const & pen)
0052 {
0053     uint n = pen.color().red() + pen.color().green() + pen.color().blue();
0054     n += 1000 * pen.width();
0055     n += 10000 * (uint) pen.style();
0056     return n;
0057 }
0058 
0059 // specialized debug method
0060 template<>
0061 QString SubStyleOne<Style::CurrencyFormat, Currency>::debugData(bool withName) const
0062 {
0063     QString out; if (withName) out = name(Style::CurrencyFormat) + ' '; QDebug qdbg(&out); qdbg << value1.symbol(); return out;
0064 }
0065 
0066 template<Style::Key key>
0067 class PenStyle : public SubStyleOne<key, QPen>
0068 {
0069 public:
0070     PenStyle(const QPen& p = Qt::NoPen) : SubStyleOne<key, QPen>(p) {}
0071 };
0072 
0073 template<Style::Key key>
0074 class BorderPenStyle : public PenStyle<key>
0075 {
0076 public:
0077     BorderPenStyle(const QPen& p = Qt::NoPen) : PenStyle<key>(p), value(calculateValue(p)) {}
0078     int value;
0079 };
0080 
0081 QString SubStyle::name(Style::Key key)
0082 {
0083     QString name;
0084     switch (key) {
0085     case Style::DefaultStyleKey:        name = "Default style"; break;
0086     case Style::NamedStyleKey:          name = "Named style"; break;
0087     case Style::LeftPen:                name = "Left pen"; break;
0088     case Style::RightPen:               name = "Right pen"; break;
0089     case Style::TopPen:                 name = "Top pen"; break;
0090     case Style::BottomPen:              name = "Bottom pen"; break;
0091     case Style::FallDiagonalPen:        name = "Fall diagonal pen"; break;
0092     case Style::GoUpDiagonalPen:        name = "Go up diagonal pen"; break;
0093     case Style::HorizontalAlignment:    name = "Horz. alignment"; break;
0094     case Style::VerticalAlignment:      name = "Vert. alignment"; break;
0095     case Style::MultiRow:               name = "Wrap text"; break;
0096     case Style::VerticalText:           name = "Vertical text"; break;
0097     case Style::Angle:                  name = "Angle"; break;
0098     case Style::Indentation:            name = "Indentation"; break;
0099     case Style::ShrinkToFit:            name = "Shrink to Fit"; break;
0100     case Style::Prefix:                 name = "Prefix"; break;
0101     case Style::Postfix:                name = "Postfix"; break;
0102     case Style::Precision:              name = "Precision"; break;
0103     case Style::ThousandsSep:           name = "Thousands separator"; break;
0104     case Style::FormatTypeKey:          name = "Format type"; break;
0105     case Style::FloatFormatKey:         name = "Float format"; break;
0106     case Style::FloatColorKey:          name = "Float color"; break;
0107     case Style::CurrencyFormat:         name = "Currency"; break;
0108     case Style::CustomFormat:           name = "Custom format"; break;
0109     case Style::BackgroundBrush:        name = "Background brush"; break;
0110     case Style::BackgroundColor:        name = "Background color"; break;
0111     case Style::FontColor:              name = "Font color"; break;
0112     case Style::FontFamily:             name = "Font family"; break;
0113     case Style::FontSize:               name = "Font size"; break;
0114     case Style::FontBold:               name = "Font bold"; break;
0115     case Style::FontItalic:             name = "Font italic"; break;
0116     case Style::FontStrike:             name = "Font strikeout"; break;
0117     case Style::FontUnderline:          name = "Font underline"; break;
0118     case Style::DontPrintText:          name = "Do not print text"; break;
0119     case Style::NotProtected:           name = "Not protected"; break;
0120     case Style::HideAll:                name = "Hide all"; break;
0121     case Style::HideFormula:            name = "Hide formula"; break;
0122     }
0123     return name;
0124 }
0125 
0126 SharedSubStyle SharedSubStyle::s_defaultStyle(new SubStyle());
0127 
0128 } // namespace Sheets
0129 } // namespace Calligra
0130 
0131 /////////////////////////////////////////////////////////////////////////////
0132 //
0133 // Style::Private
0134 //
0135 /////////////////////////////////////////////////////////////////////////////
0136 
0137 class Q_DECL_HIDDEN Style::Private : public QSharedData
0138 {
0139 public:
0140     QHash<Key, SharedSubStyle> subStyles;
0141 };
0142 
0143 
0144 /////////////////////////////////////////////////////////////////////////////
0145 //
0146 // Style
0147 //
0148 /////////////////////////////////////////////////////////////////////////////
0149 
0150 Style::Style()
0151         : d(new Private)
0152 {
0153 }
0154 
0155 Style::Style(const Style& style)
0156         : d(style.d)
0157 {
0158 }
0159 
0160 Style::~Style()
0161 {
0162 }
0163 
0164 Style::StyleType Style::type() const
0165 {
0166     return AUTO;
0167 }
0168 
0169 QString Style::parentName() const
0170 {
0171     if (!d->subStyles.contains(NamedStyleKey))
0172         return QString();
0173     return static_cast<const NamedStyle*>(d->subStyles[NamedStyleKey].data())->name;
0174 }
0175 
0176 void Style::setParentName(const QString& name)
0177 {
0178     d->subStyles.insert(NamedStyleKey, SharedSubStyle(new NamedStyle(name)));
0179 }
0180 
0181 void Style::clearAttribute(Key key)
0182 {
0183     d->subStyles.remove(key);
0184 }
0185 
0186 bool Style::hasAttribute(Key key) const
0187 {
0188     return d->subStyles.contains(key);
0189 }
0190 
0191 
0192 void Style::saveXML(QDomDocument& doc, QDomElement& format, const StyleManager* styleManager) const
0193 {
0194     // list of substyles to store
0195     QSet<Key> keysToStore;
0196 
0197     if (d->subStyles.contains(NamedStyleKey)) {
0198         const CustomStyle* namedStyle = styleManager->style(parentName());
0199         // check, if it's an unmodified named style
0200         keysToStore = difference(*namedStyle);
0201         if (type() == AUTO) {
0202             const QList<Key> keys = keysToStore.toList();
0203             if ((keysToStore.count() == 0) ||
0204                     (keysToStore.count() == 1 && keysToStore.toList().first() == NamedStyleKey)) {
0205                 // just save the name and we are done.
0206                 format.setAttribute("style-name", parentName());
0207                 return;
0208             } else
0209                 format.setAttribute("parent", parentName());
0210         } else { // custom style
0211             if (d->subStyles.contains(NamedStyleKey))
0212                 format.setAttribute("parent", parentName());
0213         }
0214     } else
0215         keysToStore = QSet<Key>::fromList(d->subStyles.keys());
0216 
0217     if (keysToStore.contains(HorizontalAlignment) && halign() != HAlignUndefined)
0218         format.setAttribute(type() == AUTO ? "align" : "alignX", (int) halign());
0219 
0220     if (keysToStore.contains(VerticalAlignment) && valign() != VAlignUndefined)
0221         format.setAttribute("alignY", QString::number((int) valign()));
0222 
0223     if (keysToStore.contains(BackgroundColor) && backgroundColor().isValid())
0224         format.setAttribute("bgcolor", backgroundColor().name());
0225 
0226     if (keysToStore.contains(MultiRow) && wrapText())
0227         format.setAttribute("multirow", "yes");
0228 
0229     if (keysToStore.contains(VerticalText) && verticalText())
0230         format.setAttribute("verticaltext", "yes");
0231 
0232     if (keysToStore.contains(ShrinkToFit) && shrinkToFit())
0233         format.setAttribute("shrinktofit", "yes");
0234 
0235     if (keysToStore.contains(Precision))
0236         format.setAttribute("precision", QString::number(precision()));
0237 
0238     if (keysToStore.contains(Prefix) && !prefix().isEmpty())
0239         format.setAttribute("prefix", prefix());
0240 
0241     if (keysToStore.contains(Postfix) && !postfix().isEmpty())
0242         format.setAttribute("postfix", postfix());
0243 
0244     if (keysToStore.contains(FloatFormatKey))
0245         format.setAttribute("float", QString::number((int) floatFormat()));
0246 
0247     if (keysToStore.contains(FloatColorKey))
0248         format.setAttribute("floatcolor", QString::number((int)floatColor()));
0249 
0250     if (keysToStore.contains(FormatTypeKey))
0251         format.setAttribute("format", QString::number((int) formatType()));
0252 
0253     if (keysToStore.contains(CustomFormat) && !customFormat().isEmpty())
0254         format.setAttribute("custom", customFormat());
0255 
0256     if (keysToStore.contains(FormatTypeKey) && formatType() == Format::Money) {
0257         format.setAttribute("type", (int) currency().index());
0258         format.setAttribute("symbol", currency().symbol());
0259     }
0260 
0261     if (keysToStore.contains(Angle))
0262         format.setAttribute("angle", QString::number(angle()));
0263 
0264     if (keysToStore.contains(Indentation))
0265         format.setAttribute("indent", QString::number(indentation()));
0266 
0267     if (keysToStore.contains(DontPrintText))
0268         format.setAttribute("dontprinttext", printText() ? "no" : "yes");
0269 
0270     if (keysToStore.contains(NotProtected))
0271         format.setAttribute("noprotection", notProtected() ? "yes" : "no");
0272 
0273     if (keysToStore.contains(HideAll))
0274         format.setAttribute("hideall", hideAll() ? "yes" : "no");
0275 
0276     if (keysToStore.contains(HideFormula))
0277         format.setAttribute("hideformula", hideFormula() ? "yes" : "no");
0278 
0279     if (type() == AUTO) {
0280         if (keysToStore.contains(FontFamily) ||
0281                 keysToStore.contains(FontSize) ||
0282                 keysToStore.contains(FontBold) ||
0283                 keysToStore.contains(FontItalic) ||
0284                 keysToStore.contains(FontStrike) ||
0285                 keysToStore.contains(FontUnderline)) {
0286             format.appendChild(NativeFormat::createElement("font", font(), doc));
0287         }
0288     } else { // custom style
0289         if (keysToStore.contains(FontFamily))
0290             format.setAttribute("font-family", fontFamily());
0291         if (keysToStore.contains(FontSize))
0292             format.setAttribute("font-size", QString::number(fontSize()));
0293         if (keysToStore.contains(FontBold) || keysToStore.contains(FontItalic) ||
0294                 keysToStore.contains(FontUnderline) || keysToStore.contains(FontStrike)) {
0295             enum FontFlags {
0296                 FBold      = 0x01,
0297                 FUnderline = 0x02,
0298                 FItalic    = 0x04,
0299                 FStrike    = 0x08
0300             };
0301             int fontFlags = 0;
0302             fontFlags |= bold()      ? FBold      : 0;
0303             fontFlags |= italic()    ? FItalic    : 0;
0304             fontFlags |= underline() ? FUnderline : 0;
0305             fontFlags |= strikeOut() ? FStrike    : 0;
0306             format.setAttribute("font-flags", QString::number(fontFlags));
0307         }
0308     }
0309 
0310     if (keysToStore.contains(FontColor) && fontColor().isValid())
0311         format.appendChild(NativeFormat::createElement("pen", fontColor(), doc));
0312 
0313     if (keysToStore.contains(BackgroundBrush)) {
0314         format.setAttribute("brushcolor", backgroundBrush().color().name());
0315         format.setAttribute("brushstyle", QString::number((int) backgroundBrush().style()));
0316     }
0317 
0318     if (keysToStore.contains(LeftPen)) {
0319         QDomElement left = doc.createElement("left-border");
0320         left.appendChild(NativeFormat::createElement("pen", leftBorderPen(), doc));
0321         format.appendChild(left);
0322     }
0323 
0324     if (keysToStore.contains(TopPen)) {
0325         QDomElement top = doc.createElement("top-border");
0326         top.appendChild(NativeFormat::createElement("pen", topBorderPen(), doc));
0327         format.appendChild(top);
0328     }
0329 
0330     if (keysToStore.contains(RightPen)) {
0331         QDomElement right = doc.createElement("right-border");
0332         right.appendChild(NativeFormat::createElement("pen", rightBorderPen(), doc));
0333         format.appendChild(right);
0334     }
0335 
0336     if (keysToStore.contains(BottomPen)) {
0337         QDomElement bottom = doc.createElement("bottom-border");
0338         bottom.appendChild(NativeFormat::createElement("pen", bottomBorderPen(), doc));
0339         format.appendChild(bottom);
0340     }
0341 
0342     if (keysToStore.contains(FallDiagonalPen)) {
0343         QDomElement fallDiagonal  = doc.createElement("fall-diagonal");
0344         fallDiagonal.appendChild(NativeFormat::createElement("pen", fallDiagonalPen(), doc));
0345         format.appendChild(fallDiagonal);
0346     }
0347 
0348     if (keysToStore.contains(GoUpDiagonalPen)) {
0349         QDomElement goUpDiagonal = doc.createElement("up-diagonal");
0350         goUpDiagonal.appendChild(NativeFormat::createElement("pen", goUpDiagonalPen(), doc));
0351         format.appendChild(goUpDiagonal);
0352     }
0353 }
0354 
0355 bool Style::loadXML(KoXmlElement& format, Paste::Mode mode)
0356 {
0357     if (format.hasAttribute("style-name")) {
0358         // Simply set the style name and we are done.
0359         insertSubStyle(NamedStyleKey, format.attribute("style-name"));
0360         return true;
0361     } else if (format.hasAttribute("parent"))
0362         insertSubStyle(NamedStyleKey, format.attribute("parent"));
0363 
0364     bool ok;
0365     if (format.hasAttribute(type() == AUTO ? "align" : "alignX")) {
0366         HAlign a = (HAlign) format.attribute(type() == AUTO ? "align" : "alignX").toInt(&ok);
0367         if (!ok)
0368             return false;
0369         if ((unsigned int) a >= 1 && (unsigned int) a <= 4) {
0370             setHAlign(a);
0371         }
0372     }
0373     if (format.hasAttribute("alignY")) {
0374         VAlign a = (VAlign) format.attribute("alignY").toInt(&ok);
0375         if (!ok)
0376             return false;
0377         if ((unsigned int) a >= 1 && (unsigned int) a < 4) {
0378             setVAlign(a);
0379         }
0380     }
0381 
0382     if (format.hasAttribute("bgcolor")) {
0383         QColor color(format.attribute("bgcolor"));
0384         if (color.isValid())
0385             setBackgroundColor(color);
0386     }
0387 
0388     if (format.hasAttribute("multirow")) {
0389         setWrapText(true);
0390     }
0391 
0392     if (format.hasAttribute("shrinktofit")) {
0393         setShrinkToFit(true);
0394     }
0395 
0396     if (format.hasAttribute("precision")) {
0397         int i = format.attribute("precision").toInt(&ok);
0398         if (i < -1) {
0399             debugSheetsODF << "Value out of range Cell::precision=" << i;
0400             return false;
0401         }
0402         // special handling for precision
0403         // The Style default (-1) and the storage default (0) differ.
0404         if (type() == AUTO && i == -1)
0405             i = 0;
0406         // The maximum is 10. Replace the Style value 0 with -11, which always results
0407         // in a storage value < 0 and is interpreted as Style value 0.
0408         else if (type() == AUTO && i == 0)
0409             i = -11;
0410         setPrecision(i);
0411     }
0412 
0413     if (format.hasAttribute("float")) {
0414         FloatFormat a = (FloatFormat)format.attribute("float").toInt(&ok);
0415         if (!ok)
0416             return false;
0417         if ((unsigned int) a >= 1 && (unsigned int) a <= 3) {
0418             setFloatFormat(a);
0419         }
0420     }
0421 
0422     if (format.hasAttribute("floatcolor")) {
0423         FloatColor a = (FloatColor) format.attribute("floatcolor").toInt(&ok);
0424         if (!ok) return false;
0425         if ((unsigned int) a >= 1 && (unsigned int) a <= 2) {
0426             setFloatColor(a);
0427         }
0428     }
0429 
0430     if (format.hasAttribute("format")) {
0431         int fo = format.attribute("format").toInt(&ok);
0432         if (! ok)
0433             return false;
0434         setFormatType(static_cast<Format::Type>(fo));
0435     }
0436     if (format.hasAttribute("custom")) {
0437         setCustomFormat(format.attribute("custom"));
0438     }
0439     if (formatType() == Format::Money) {
0440         ok = true;
0441         Currency currency;
0442         if (format.hasAttribute("type")) {
0443             currency = Currency(format.attribute("type").toInt(&ok));
0444             if (!ok) {
0445                 if (format.hasAttribute("symbol"))
0446                     currency = Currency(format.attribute("symbol"));
0447             }
0448         } else if (format.hasAttribute("symbol"))
0449             currency = Currency(format.attribute("symbol"));
0450         setCurrency(currency);
0451     }
0452     if (format.hasAttribute("angle")) {
0453         setAngle(format.attribute("angle").toInt(&ok));
0454         if (!ok)
0455             return false;
0456     }
0457     if (format.hasAttribute("indent")) {
0458         setIndentation(format.attribute("indent").toDouble(&ok));
0459         if (!ok)
0460             return false;
0461     }
0462     if (format.hasAttribute("dontprinttext")) {
0463         setDontPrintText(true);
0464     }
0465 
0466     if (format.hasAttribute("noprotection")) {
0467         setNotProtected(true);
0468     }
0469 
0470     if (format.hasAttribute("hideall")) {
0471         setHideAll(true);
0472     }
0473 
0474     if (format.hasAttribute("hideformula")) {
0475         setHideFormula(true);
0476     }
0477 
0478     if (type() == AUTO) {
0479         KoXmlElement fontElement = format.namedItem("font").toElement();
0480         if (!fontElement.isNull()) {
0481             QFont font(NativeFormat::toFont(fontElement));
0482             setFontFamily(font.family());
0483             setFontSize(font.pointSize());
0484             if (font.italic())
0485                 setFontItalic(true);
0486             if (font.bold())
0487                 setFontBold(true);
0488             if (font.underline())
0489                 setFontUnderline(true);
0490             if (font.strikeOut())
0491                 setFontStrikeOut(true);
0492         }
0493     } else { // custom style
0494         if (format.hasAttribute("font-family"))
0495             setFontFamily(format.attribute("font-family"));
0496         if (format.hasAttribute("font-size")) {
0497             setFontSize(format.attribute("font-size").toInt(&ok));
0498             if (!ok)
0499                 return false;
0500         }
0501         if (format.hasAttribute("font-flags")) {
0502             int fontFlags = format.attribute("font-flags").toInt(&ok);
0503             if (!ok)
0504                 return false;
0505 
0506             enum FontFlags {
0507                 FBold      = 0x01,
0508                 FUnderline = 0x02,
0509                 FItalic    = 0x04,
0510                 FStrike    = 0x08
0511             };
0512             setFontBold(fontFlags & FBold);
0513             setFontItalic(fontFlags & FItalic);
0514             setFontUnderline(fontFlags & FUnderline);
0515             setFontStrikeOut(fontFlags & FStrike);
0516         }
0517     }
0518 
0519     if (format.hasAttribute("brushcolor")) {
0520         QColor color(format.attribute("brushcolor"));
0521         if (color.isValid()) {
0522             QBrush brush = backgroundBrush();
0523             brush.setColor(color);
0524             setBackgroundBrush(brush);
0525         }
0526     }
0527 
0528     if (format.hasAttribute("brushstyle")) {
0529         QBrush brush = backgroundBrush();
0530         brush.setStyle((Qt::BrushStyle) format.attribute("brushstyle").toInt(&ok));
0531         if (!ok)
0532             return false;
0533         setBackgroundBrush(brush);
0534     }
0535 
0536     KoXmlElement pen = format.namedItem("pen").toElement();
0537     if (!pen.isNull()) {
0538         setFontColor(NativeFormat::toPen(pen).color());
0539     }
0540 
0541     if (mode != Paste::NoBorder) {
0542         KoXmlElement left = format.namedItem("left-border").toElement();
0543         if (!left.isNull()) {
0544             KoXmlElement pen = left.namedItem("pen").toElement();
0545             if (!pen.isNull())
0546                 setLeftBorderPen(NativeFormat::toPen(pen));
0547         }
0548 
0549         KoXmlElement top = format.namedItem("top-border").toElement();
0550         if (!top.isNull()) {
0551             KoXmlElement pen = top.namedItem("pen").toElement();
0552             if (!pen.isNull())
0553                 setTopBorderPen(NativeFormat::toPen(pen));
0554         }
0555 
0556         KoXmlElement right = format.namedItem("right-border").toElement();
0557         if (!right.isNull()) {
0558             KoXmlElement pen = right.namedItem("pen").toElement();
0559             if (!pen.isNull())
0560                 setRightBorderPen(NativeFormat::toPen(pen));
0561         }
0562 
0563         KoXmlElement bottom = format.namedItem("bottom-border").toElement();
0564         if (!bottom.isNull()) {
0565             KoXmlElement pen = bottom.namedItem("pen").toElement();
0566             if (!pen.isNull())
0567                 setBottomBorderPen(NativeFormat::toPen(pen));
0568         }
0569 
0570         KoXmlElement fallDiagonal = format.namedItem("fall-diagonal").toElement();
0571         if (!fallDiagonal.isNull()) {
0572             KoXmlElement pen = fallDiagonal.namedItem("pen").toElement();
0573             if (!pen.isNull())
0574                 setFallDiagonalPen(NativeFormat::toPen(pen));
0575         }
0576 
0577         KoXmlElement goUpDiagonal = format.namedItem("up-diagonal").toElement();
0578         if (!goUpDiagonal.isNull()) {
0579             KoXmlElement pen = goUpDiagonal.namedItem("pen").toElement();
0580             if (!pen.isNull())
0581                 setGoUpDiagonalPen(NativeFormat::toPen(pen));
0582         }
0583     }
0584 
0585     if (format.hasAttribute("prefix")) {
0586         setPrefix(format.attribute("prefix"));
0587     }
0588     if (format.hasAttribute("postfix")) {
0589         setPostfix(format.attribute("postfix"));
0590     }
0591 
0592     return true;
0593 }
0594 
0595 uint Style::bottomPenValue() const
0596 {
0597     if (!d->subStyles.contains(BottomPen))
0598         return BorderPenStyle<BottomPen>().value;
0599     return static_cast<const BorderPenStyle<BottomPen>*>(d->subStyles[BottomPen].data())->value;
0600 }
0601 
0602 uint Style::rightPenValue() const
0603 {
0604     if (!d->subStyles.contains(RightPen))
0605         return BorderPenStyle<RightPen>().value;
0606     return static_cast<const BorderPenStyle<RightPen>*>(d->subStyles[RightPen].data())->value;
0607 }
0608 
0609 uint Style::leftPenValue() const
0610 {
0611     if (!d->subStyles.contains(LeftPen))
0612         return BorderPenStyle<LeftPen>().value;
0613     return static_cast<const BorderPenStyle<LeftPen>*>(d->subStyles[LeftPen].data())->value;
0614 }
0615 
0616 uint Style::topPenValue() const
0617 {
0618     if (!d->subStyles.contains(TopPen))
0619         return BorderPenStyle<TopPen>().value;
0620     return static_cast<const BorderPenStyle<TopPen>*>(d->subStyles[TopPen].data())->value;
0621 }
0622 
0623 QColor Style::fontColor() const
0624 {
0625     if (!d->subStyles.contains(FontColor))
0626         return SubStyleOne<FontColor, QColor>(Qt::black).value1;
0627     return static_cast<const SubStyleOne<FontColor, QColor>*>(d->subStyles[FontColor].data())->value1;
0628 }
0629 
0630 QColor Style::backgroundColor() const
0631 {
0632     if (!d->subStyles.contains(BackgroundColor))
0633         return SubStyleOne<BackgroundColor, QColor>().value1;
0634     return static_cast<const SubStyleOne<BackgroundColor, QColor>*>(d->subStyles[BackgroundColor].data())->value1;
0635 }
0636 
0637 QPen Style::rightBorderPen() const
0638 {
0639     if (!d->subStyles.contains(RightPen))
0640         return BorderPenStyle<RightPen>().value1;
0641     return static_cast<const BorderPenStyle<RightPen>*>(d->subStyles[RightPen].data())->value1;
0642 }
0643 
0644 QPen Style::bottomBorderPen() const
0645 {
0646     if (!d->subStyles.contains(BottomPen))
0647         return BorderPenStyle<BottomPen>().value1;
0648     return static_cast<const BorderPenStyle<BottomPen>*>(d->subStyles[BottomPen].data())->value1;
0649 }
0650 
0651 QPen Style::leftBorderPen() const
0652 {
0653     if (!d->subStyles.contains(LeftPen))
0654         return BorderPenStyle<LeftPen>().value1;
0655     return static_cast<const BorderPenStyle<LeftPen>*>(d->subStyles[LeftPen].data())->value1;
0656 }
0657 
0658 QPen Style::topBorderPen() const
0659 {
0660     if (!d->subStyles.contains(TopPen))
0661         return BorderPenStyle<TopPen>().value1;
0662     return static_cast<const BorderPenStyle<TopPen>*>(d->subStyles[TopPen].data())->value1;
0663 }
0664 
0665 QPen Style::fallDiagonalPen() const
0666 {
0667     if (!d->subStyles.contains(FallDiagonalPen))
0668         return PenStyle<FallDiagonalPen>().value1;
0669     return static_cast<const PenStyle<FallDiagonalPen>*>(d->subStyles[FallDiagonalPen].data())->value1;
0670 }
0671 
0672 QPen Style::goUpDiagonalPen() const
0673 {
0674     if (!d->subStyles.contains(GoUpDiagonalPen))
0675         return PenStyle<GoUpDiagonalPen>().value1;
0676     return static_cast<const PenStyle<GoUpDiagonalPen>*>(d->subStyles[GoUpDiagonalPen].data())->value1;
0677 }
0678 
0679 QBrush Style::backgroundBrush() const
0680 {
0681     if (!d->subStyles.contains(BackgroundBrush))
0682         return SubStyleOne<BackgroundBrush, QBrush>(Qt::white).value1;
0683     return static_cast<const SubStyleOne<BackgroundBrush, QBrush>*>(d->subStyles[BackgroundBrush].data())->value1;
0684 }
0685 
0686 QString Style::customFormat() const
0687 {
0688     if (!d->subStyles.contains(CustomFormat))
0689         return SubStyleOne<CustomFormat, QString>().value1;
0690     return static_cast<const SubStyleOne<CustomFormat, QString>*>(d->subStyles[CustomFormat].data())->value1;
0691 }
0692 
0693 QString Style::prefix() const
0694 {
0695     if (!d->subStyles.contains(Prefix))
0696         return SubStyleOne<Prefix, QString>().value1;
0697     return static_cast<const SubStyleOne<Prefix, QString>*>(d->subStyles[Prefix].data())->value1;
0698 }
0699 
0700 QString Style::postfix() const
0701 {
0702     if (!d->subStyles.contains(Postfix))
0703         return SubStyleOne<Postfix, QString>().value1;
0704     return static_cast<const SubStyleOne<Postfix, QString>*>(d->subStyles[Postfix].data())->value1;
0705 }
0706 
0707 QString Style::fontFamily() const
0708 {
0709     if (!d->subStyles.contains(FontFamily))
0710         return KoGlobal::defaultFont().family(); // SubStyleOne<FontFamily, QString>().value1;
0711     return static_cast<const SubStyleOne<FontFamily, QString>*>(d->subStyles[FontFamily].data())->value1;
0712 }
0713 
0714 Style::HAlign Style::halign() const
0715 {
0716     if (!d->subStyles.contains(HorizontalAlignment))
0717         return SubStyleOne<HorizontalAlignment, Style::HAlign>().value1;
0718     return static_cast<const SubStyleOne<HorizontalAlignment, Style::HAlign>*>(d->subStyles[HorizontalAlignment].data())->value1;
0719 }
0720 
0721 Style::VAlign Style::valign() const
0722 {
0723     if (!d->subStyles.contains(VerticalAlignment))
0724         return SubStyleOne<VerticalAlignment, Style::VAlign>().value1;
0725     return static_cast<const SubStyleOne<VerticalAlignment, Style::VAlign>*>(d->subStyles[VerticalAlignment].data())->value1;
0726 }
0727 
0728 Style::FloatFormat Style::floatFormat() const
0729 {
0730     if (!d->subStyles.contains(FloatFormatKey))
0731         return SubStyleOne<FloatFormatKey, FloatFormat>().value1;
0732     return static_cast<const SubStyleOne<FloatFormatKey, FloatFormat>*>(d->subStyles[FloatFormatKey].data())->value1;
0733 }
0734 
0735 Style::FloatColor Style::floatColor() const
0736 {
0737     if (!d->subStyles.contains(FloatColorKey))
0738         return SubStyleOne<FloatColorKey, FloatColor>().value1;
0739     return static_cast<const SubStyleOne<FloatColorKey, FloatColor>*>(d->subStyles[FloatColorKey].data())->value1;
0740 }
0741 
0742 Format::Type Style::formatType() const
0743 {
0744     if (!d->subStyles.contains(FormatTypeKey))
0745         return SubStyleOne<FormatTypeKey, Format::Type>().value1;
0746     return static_cast<const SubStyleOne<FormatTypeKey, Format::Type>*>(d->subStyles[FormatTypeKey].data())->value1;
0747 }
0748 
0749 Currency Style::currency() const
0750 {
0751     if (!d->subStyles.contains(CurrencyFormat))
0752         return Currency();
0753     return static_cast<const SubStyleOne<CurrencyFormat, Currency>*>(d->subStyles[CurrencyFormat].data())->value1;
0754 }
0755 
0756 QFont Style::font() const
0757 {
0758     QFont font;
0759     font.setFamily(fontFamily());
0760     font.setPointSize(fontSize());
0761     font.setBold(bold());
0762     font.setItalic(italic());
0763     font.setUnderline(underline());
0764     font.setStrikeOut(strikeOut());
0765     return font;
0766 }
0767 
0768 bool Style::bold() const
0769 {
0770     if (!d->subStyles.contains(FontBold))
0771         return SubStyleOne<FontBold, bool>().value1;
0772     return static_cast<const SubStyleOne<FontBold, bool>*>(d->subStyles[FontBold].data())->value1;
0773 }
0774 
0775 bool Style::italic() const
0776 {
0777     if (!d->subStyles.contains(FontItalic))
0778         return SubStyleOne<FontItalic, bool>().value1;
0779     return static_cast<const SubStyleOne<FontItalic, bool>*>(d->subStyles[FontItalic].data())->value1;
0780 }
0781 
0782 bool Style::underline() const
0783 {
0784     if (!d->subStyles.contains(FontUnderline))
0785         return SubStyleOne<FontUnderline, bool>().value1;
0786     return static_cast<const SubStyleOne<FontUnderline, bool>*>(d->subStyles[FontUnderline].data())->value1;
0787 }
0788 
0789 bool Style::strikeOut() const
0790 {
0791     if (!d->subStyles.contains(FontStrike))
0792         return SubStyleOne<FontStrike, bool>().value1;
0793     return static_cast<const SubStyleOne<FontStrike, bool>*>(d->subStyles[FontStrike].data())->value1;
0794 }
0795 
0796 int Style::fontSize() const
0797 {
0798     if (!d->subStyles.contains(FontSize))
0799         return KoGlobal::defaultFont().pointSize(); //SubStyleOne<FontSize, int>().value1;
0800     return static_cast<const SubStyleOne<FontSize, int>*>(d->subStyles[FontSize].data())->value1;
0801 }
0802 
0803 int Style::precision() const
0804 {
0805     if (!d->subStyles.contains(Precision))
0806         return -1; //SubStyleOne<Precision, int>().value1;
0807     return static_cast<const SubStyleOne<Precision, int>*>(d->subStyles[Precision].data())->value1;
0808 }
0809 
0810 bool Style::thousandsSep() const
0811 {
0812     if (!d->subStyles.contains(ThousandsSep))
0813         return false;
0814     return static_cast<const SubStyleOne<ThousandsSep, bool>*>(d->subStyles[ThousandsSep].data())->value1;
0815 }
0816 
0817 int Style::angle() const
0818 {
0819     if (!d->subStyles.contains(Angle))
0820         return SubStyleOne<Angle, int>().value1;
0821     return static_cast<const SubStyleOne<Angle, int>*>(d->subStyles[Angle].data())->value1;
0822 }
0823 
0824 double Style::indentation() const
0825 {
0826     if (!d->subStyles.contains(Indentation))
0827         return SubStyleOne<Indentation, int>().value1;
0828     return static_cast<const SubStyleOne<Indentation, int>*>(d->subStyles[Indentation].data())->value1;
0829 }
0830 
0831 bool Style::shrinkToFit() const
0832 {
0833     if (!d->subStyles.contains(ShrinkToFit))
0834         return SubStyleOne<ShrinkToFit, bool>().value1;
0835     return static_cast<const SubStyleOne<ShrinkToFit, bool>*>(d->subStyles[ShrinkToFit].data())->value1;
0836 }
0837 
0838 bool Style::verticalText() const
0839 {
0840     if (!d->subStyles.contains(VerticalText))
0841         return SubStyleOne<VerticalText, bool>().value1;
0842     return static_cast<const SubStyleOne<VerticalText, bool>*>(d->subStyles[VerticalText].data())->value1;
0843 }
0844 
0845 bool Style::wrapText() const
0846 {
0847     if (!d->subStyles.contains(MultiRow))
0848         return SubStyleOne<MultiRow, bool>().value1;
0849     return static_cast<const SubStyleOne<MultiRow, bool>*>(d->subStyles[MultiRow].data())->value1;
0850 }
0851 
0852 bool Style::printText() const
0853 {
0854     if (!d->subStyles.contains(DontPrintText))
0855         return !SubStyleOne<DontPrintText, bool>().value1;
0856     return !static_cast<const SubStyleOne<DontPrintText, bool>*>(d->subStyles[DontPrintText].data())->value1;
0857 }
0858 
0859 bool Style::hideAll() const
0860 {
0861     if (!d->subStyles.contains(HideAll))
0862         return SubStyleOne<HideAll, bool>().value1;
0863     return static_cast<const SubStyleOne<HideAll, bool>*>(d->subStyles[HideAll].data())->value1;
0864 }
0865 
0866 bool Style::hideFormula() const
0867 {
0868     if (!d->subStyles.contains(HideFormula))
0869         return SubStyleOne<HideFormula, bool>().value1;
0870     return static_cast<const SubStyleOne<HideFormula, bool>*>(d->subStyles[HideFormula].data())->value1;
0871 }
0872 
0873 bool Style::notProtected() const
0874 {
0875     if (!d->subStyles.contains(NotProtected))
0876         return SubStyleOne<NotProtected, bool>().value1;
0877     return static_cast<const SubStyleOne<NotProtected, bool>*>(d->subStyles[NotProtected].data())->value1;
0878 }
0879 
0880 bool Style::isDefault() const
0881 {
0882     return isEmpty() || d->subStyles.contains(DefaultStyleKey);
0883 }
0884 
0885 bool Style::isEmpty() const
0886 {
0887     return d->subStyles.isEmpty();
0888 }
0889 
0890 void Style::setHAlign(HAlign align)
0891 {
0892     insertSubStyle(HorizontalAlignment, align);
0893 }
0894 
0895 void Style::setVAlign(VAlign align)
0896 {
0897     insertSubStyle(VerticalAlignment, align);
0898 }
0899 
0900 void Style::setFont(QFont const & font)
0901 {
0902     insertSubStyle(FontFamily,     font.family());
0903     insertSubStyle(FontSize,       font.pointSize());
0904     insertSubStyle(FontBold,       font.bold());
0905     insertSubStyle(FontItalic,     font.italic());
0906     insertSubStyle(FontStrike,     font.strikeOut());
0907     insertSubStyle(FontUnderline,  font.underline());
0908 }
0909 
0910 void Style::setFontFamily(QString const & family)
0911 {
0912     QString font = family;
0913     // use the KDE default for sans serif, not Qt's default - this is because Qt doesn't return the default system font here
0914     if (font.toLower() == "sans serif") {
0915         QFont f = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
0916         font = f.family();
0917     }
0918 
0919     insertSubStyle(FontFamily, font);
0920 }
0921 
0922 void Style::setFontBold(bool enabled)
0923 {
0924     insertSubStyle(FontBold, enabled);
0925 }
0926 
0927 void Style::setFontItalic(bool enabled)
0928 {
0929     insertSubStyle(FontItalic, enabled);
0930 }
0931 
0932 void Style::setFontUnderline(bool enabled)
0933 {
0934     insertSubStyle(FontUnderline, enabled);
0935 }
0936 
0937 void Style::setFontStrikeOut(bool enabled)
0938 {
0939     insertSubStyle(FontStrike, enabled);
0940 }
0941 
0942 void Style::setFontSize(int size)
0943 {
0944     insertSubStyle(FontSize, size);
0945 }
0946 
0947 void Style::setFontColor(QColor const & color)
0948 {
0949     insertSubStyle(FontColor, color);
0950 }
0951 
0952 void Style::setBackgroundColor(QColor const & color)
0953 {
0954     insertSubStyle(BackgroundColor, color);
0955 }
0956 
0957 void Style::setRightBorderPen(QPen const & pen)
0958 {
0959     insertSubStyle(RightPen, pen);
0960 }
0961 
0962 void Style::setBottomBorderPen(QPen const & pen)
0963 {
0964     insertSubStyle(BottomPen, pen);
0965 }
0966 
0967 void Style::setLeftBorderPen(QPen const & pen)
0968 {
0969     insertSubStyle(LeftPen, pen);
0970 }
0971 
0972 void Style::setTopBorderPen(QPen const & pen)
0973 {
0974     insertSubStyle(TopPen, pen);
0975 }
0976 
0977 void Style::setFallDiagonalPen(QPen const & pen)
0978 {
0979     insertSubStyle(FallDiagonalPen, pen);
0980 }
0981 
0982 void Style::setGoUpDiagonalPen(QPen const & pen)
0983 {
0984     insertSubStyle(GoUpDiagonalPen, pen);
0985 }
0986 
0987 void Style::setAngle(int angle)
0988 {
0989     insertSubStyle(Angle, angle);
0990 }
0991 
0992 void Style::setIndentation(double indent)
0993 {
0994     insertSubStyle(Indentation, indent);
0995 }
0996 
0997 void Style::setBackgroundBrush(QBrush const & brush)
0998 {
0999     insertSubStyle(BackgroundBrush, brush);
1000 }
1001 
1002 void Style::setFloatFormat(FloatFormat format)
1003 {
1004     insertSubStyle(FloatFormatKey, format);
1005 }
1006 
1007 void Style::setFloatColor(FloatColor color)
1008 {
1009     insertSubStyle(FloatColorKey, color);
1010 }
1011 
1012 void Style::setFormatType(Format::Type format)
1013 {
1014     insertSubStyle(FormatTypeKey, format);
1015 }
1016 
1017 void Style::setCustomFormat(QString const & strFormat)
1018 {
1019     insertSubStyle(CustomFormat, strFormat);
1020 }
1021 
1022 void Style::setPrecision(int precision)
1023 {
1024     insertSubStyle(Precision, precision);
1025 }
1026 
1027 void Style::setThousandsSep(bool thousandsSep)
1028 {
1029     insertSubStyle(ThousandsSep, thousandsSep);
1030 }
1031 
1032 void Style::setPrefix(QString const & prefix)
1033 {
1034     insertSubStyle(Prefix, prefix);
1035 }
1036 
1037 void Style::setPostfix(QString const & postfix)
1038 {
1039     insertSubStyle(Postfix, postfix);
1040 }
1041 
1042 void Style::setCurrency(Currency const & currency)
1043 {
1044     QVariant variant;
1045     variant.setValue(currency);
1046     insertSubStyle(CurrencyFormat, variant);
1047 }
1048 
1049 void Style::setWrapText(bool enable)
1050 {
1051     insertSubStyle(MultiRow, enable);
1052 }
1053 
1054 void Style::setHideAll(bool enable)
1055 {
1056     insertSubStyle(HideAll, enable);
1057 }
1058 
1059 void Style::setHideFormula(bool enable)
1060 {
1061     insertSubStyle(HideFormula, enable);
1062 }
1063 
1064 void Style::setNotProtected(bool enable)
1065 {
1066     insertSubStyle(NotProtected, enable);
1067 }
1068 
1069 void Style::setDontPrintText(bool enable)
1070 {
1071     insertSubStyle(DontPrintText, enable);
1072 }
1073 
1074 void Style::setVerticalText(bool enable)
1075 {
1076     insertSubStyle(VerticalText, enable);
1077 }
1078 
1079 void Style::setShrinkToFit(bool enable)
1080 {
1081     insertSubStyle(ShrinkToFit, enable);
1082 }
1083 
1084 void Style::setDefault()
1085 {
1086     insertSubStyle(DefaultStyleKey, true);
1087 }
1088 
1089 void Style::clear()
1090 {
1091     d->subStyles.clear();
1092 }
1093 
1094 bool Style::compare(const SubStyle* one, const SubStyle* two)
1095 {
1096     if (!one || !two)
1097         return one == two;
1098     if (one->type() != two->type())
1099         return false;
1100     switch (one->type()) {
1101     case DefaultStyleKey:
1102         return true;
1103     case NamedStyleKey:
1104         return static_cast<const NamedStyle*>(one)->name == static_cast<const NamedStyle*>(two)->name;
1105         // borders
1106     case LeftPen:
1107         return static_cast<const SubStyleOne<LeftPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<LeftPen, QPen>*>(two)->value1;
1108     case RightPen:
1109         return static_cast<const SubStyleOne<RightPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<RightPen, QPen>*>(two)->value1;
1110     case TopPen:
1111         return static_cast<const SubStyleOne<TopPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<TopPen, QPen>*>(two)->value1;
1112     case BottomPen:
1113         return static_cast<const SubStyleOne<BottomPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<BottomPen, QPen>*>(two)->value1;
1114     case FallDiagonalPen:
1115         return static_cast<const SubStyleOne<FallDiagonalPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<FallDiagonalPen, QPen>*>(two)->value1;
1116     case GoUpDiagonalPen:
1117         return static_cast<const SubStyleOne<GoUpDiagonalPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<GoUpDiagonalPen, QPen>*>(two)->value1;
1118         // layout
1119     case HorizontalAlignment:
1120         return static_cast<const SubStyleOne<HorizontalAlignment, HAlign>*>(one)->value1 == static_cast<const SubStyleOne<HorizontalAlignment, HAlign>*>(two)->value1;
1121     case VerticalAlignment:
1122         return static_cast<const SubStyleOne<VerticalAlignment, VAlign>*>(one)->value1 == static_cast<const SubStyleOne<VerticalAlignment, VAlign>*>(two)->value1;
1123     case MultiRow:
1124         return static_cast<const SubStyleOne<MultiRow, bool>*>(one)->value1 == static_cast<const SubStyleOne<MultiRow, bool>*>(two)->value1;
1125     case VerticalText:
1126         return static_cast<const SubStyleOne<VerticalText, bool>*>(one)->value1 == static_cast<const SubStyleOne<VerticalText, bool>*>(two)->value1;
1127     case ShrinkToFit:
1128         return static_cast<const SubStyleOne<ShrinkToFit, bool>*>(one)->value1 == static_cast<const SubStyleOne<ShrinkToFit, bool>*>(two)->value1;
1129     case Angle:
1130         return static_cast<const SubStyleOne<Angle, int>*>(one)->value1 == static_cast<const SubStyleOne<Angle, int>*>(two)->value1;
1131     case Indentation:
1132         return static_cast<const SubStyleOne<Indentation, int>*>(one)->value1 == static_cast<const SubStyleOne<Indentation, int>*>(two)->value1;
1133         // content format
1134     case Prefix:
1135         return static_cast<const SubStyleOne<Prefix, QString>*>(one)->value1 == static_cast<const SubStyleOne<Prefix, QString>*>(two)->value1;
1136     case Postfix:
1137         return static_cast<const SubStyleOne<Postfix, QString>*>(one)->value1 == static_cast<const SubStyleOne<Postfix, QString>*>(two)->value1;
1138     case Precision:
1139         return static_cast<const SubStyleOne<Precision, int>*>(one)->value1 == static_cast<const SubStyleOne<Precision, int>*>(two)->value1;
1140     case ThousandsSep:
1141         return static_cast<const SubStyleOne<ThousandsSep, bool>*>(one)->value1 == static_cast<const SubStyleOne<ThousandsSep, bool>*>(two)->value1;
1142     case FormatTypeKey:
1143         return static_cast<const SubStyleOne<FormatTypeKey, Format::Type>*>(one)->value1 == static_cast<const SubStyleOne<FormatTypeKey, Format::Type>*>(two)->value1;
1144     case FloatFormatKey:
1145         return static_cast<const SubStyleOne<FloatFormatKey, FloatFormat>*>(one)->value1 == static_cast<const SubStyleOne<FloatFormatKey, FloatFormat>*>(two)->value1;
1146     case FloatColorKey:
1147         return static_cast<const SubStyleOne<FloatColorKey, FloatColor>*>(one)->value1 == static_cast<const SubStyleOne<FloatColorKey, FloatColor>*>(two)->value1;
1148     case CurrencyFormat: {
1149         Currency currencyOne = static_cast<const SubStyleOne<CurrencyFormat, Currency>*>(one)->value1;
1150         Currency currencyTwo = static_cast<const SubStyleOne<CurrencyFormat, Currency>*>(two)->value1;
1151         if (currencyOne != currencyTwo)
1152             return false;
1153         return true;
1154     }
1155     case CustomFormat:
1156         return static_cast<const SubStyleOne<CustomFormat, QString>*>(one)->value1 == static_cast<const SubStyleOne<CustomFormat, QString>*>(two)->value1;
1157         // background
1158     case BackgroundBrush:
1159         return static_cast<const SubStyleOne<BackgroundBrush, QBrush>*>(one)->value1 == static_cast<const SubStyleOne<BackgroundBrush, QBrush>*>(two)->value1;
1160     case BackgroundColor:
1161         return static_cast<const SubStyleOne<BackgroundColor, QColor>*>(one)->value1 == static_cast<const SubStyleOne<BackgroundColor, QColor>*>(two)->value1;
1162         // font
1163     case FontColor:
1164         return static_cast<const SubStyleOne<FontColor, QColor>*>(one)->value1 == static_cast<const SubStyleOne<FontColor, QColor>*>(two)->value1;
1165     case FontFamily:
1166         return static_cast<const SubStyleOne<FontFamily, QString>*>(one)->value1 == static_cast<const SubStyleOne<FontFamily, QString>*>(two)->value1;
1167     case FontSize:
1168         return static_cast<const SubStyleOne<FontSize, int>*>(one)->value1 == static_cast<const SubStyleOne<FontSize, int>*>(two)->value1;
1169     case FontBold:
1170         return static_cast<const SubStyleOne<FontBold, bool>*>(one)->value1 == static_cast<const SubStyleOne<FontBold, bool>*>(two)->value1;
1171     case FontItalic:
1172         return static_cast<const SubStyleOne<FontItalic, bool>*>(one)->value1 == static_cast<const SubStyleOne<FontItalic, bool>*>(two)->value1;
1173     case FontStrike:
1174         return static_cast<const SubStyleOne<FontStrike, bool>*>(one)->value1 == static_cast<const SubStyleOne<FontStrike, bool>*>(two)->value1;
1175     case FontUnderline:
1176         return static_cast<const SubStyleOne<FontUnderline, bool>*>(one)->value1 == static_cast<const SubStyleOne<FontUnderline, bool>*>(two)->value1;
1177         //misc
1178     case DontPrintText:
1179         return static_cast<const SubStyleOne<DontPrintText, bool>*>(one)->value1 == static_cast<const SubStyleOne<DontPrintText, bool>*>(two)->value1;
1180     case NotProtected:
1181         return static_cast<const SubStyleOne<NotProtected, bool>*>(one)->value1 == static_cast<const SubStyleOne<NotProtected, bool>*>(two)->value1;
1182     case HideAll:
1183         return static_cast<const SubStyleOne<HideAll, bool>*>(one)->value1 == static_cast<const SubStyleOne<HideAll, bool>*>(two)->value1;
1184     case HideFormula:
1185         return static_cast<const SubStyleOne<HideFormula, bool>*>(one)->value1 == static_cast<const SubStyleOne<HideFormula, bool>*>(two)->value1;
1186     default:
1187         return false;
1188     }
1189 }
1190 
1191 bool Style::operator==(const Style& other) const
1192 {
1193     if (other.isEmpty())
1194         return isEmpty() ? true : false;
1195     const QSet<Key> keys = QSet<Key>::fromList(d->subStyles.keys() + other.d->subStyles.keys());
1196     const QSet<Key>::ConstIterator end = keys.constEnd();
1197     for (QSet<Key>::ConstIterator it = keys.constBegin(); it != end; ++it) {
1198         if (!compare(d->subStyles.value(*it).data(), other.d->subStyles.value(*it).data()))
1199             return false;
1200     }
1201     return true;
1202 }
1203 
1204 uint Calligra::Sheets::qHash(const Style& style)
1205 {
1206     uint hash = 0;
1207     foreach (const SharedSubStyle& ss, style.subStyles()) {
1208         hash ^= ss->koHash();
1209     }
1210     return hash;
1211 }
1212 
1213 void Style::operator=(const Style & other)
1214 {
1215     d = other.d;
1216 }
1217 
1218 Style Style::operator-(const Style& other) const
1219 {
1220     Style style;
1221     const QSet<Key> keys = difference(other);
1222     const QSet<Key>::ConstIterator end = keys.constEnd();
1223     for (QSet<Key>::ConstIterator it = keys.constBegin(); it != end; ++it)
1224         style.insertSubStyle(d->subStyles[*it]);
1225     return style;
1226 }
1227 
1228 void Style::merge(const Style& style)
1229 {
1230     const QList<SharedSubStyle> subStyles(style.subStyles());
1231 //     debugSheetsStyle <<"merging" << subStyles.count() <<" attributes.";
1232     for (int i = 0; i < subStyles.count(); ++i) {
1233 //         debugSheetsStyle << subStyles[i]->debugData();
1234         insertSubStyle(subStyles[i]);
1235     }
1236 }
1237 
1238 QSet<Style::Key> Style::difference(const Style& other) const
1239 {
1240     QSet<Key> result;
1241     const QSet<Key> keys = QSet<Key>::fromList(d->subStyles.keys() + other.d->subStyles.keys());
1242     const QSet<Key>::ConstIterator end = keys.constEnd();
1243     for (QSet<Key>::ConstIterator it = keys.constBegin(); it != end; ++it) {
1244         if (!other.d->subStyles.contains(*it))
1245             result.insert(*it);
1246         else if (d->subStyles.contains(*it)) { // both contain this key
1247             if (!compare(d->subStyles.value(*it).data(), other.d->subStyles.value(*it).data()))
1248                 result.insert(*it);
1249         }
1250     }
1251     return result;
1252 }
1253 
1254 void Style::dump() const
1255 {
1256     for (int i = 0; i < subStyles().count(); ++i)
1257         subStyles()[i]->dump();
1258 }
1259 
1260 QTextCharFormat Style::asCharFormat() const
1261 {
1262     QTextCharFormat format;
1263     format.setFont(font());
1264     format.setFontWeight(bold() ? QFont::Bold : QFont::Normal);
1265     format.setFontItalic(italic());
1266     format.setFontUnderline(underline());
1267     format.setFontStrikeOut(strikeOut());
1268     return format;
1269 }
1270 
1271 QSet<Style::Key> Style::definedKeys(const StyleManager *styles) const
1272 {
1273     QSet<Style::Key> keys;
1274 
1275     if (isDefault()) return keys;
1276 
1277     if (hasAttribute(Style::NamedStyleKey)) 
1278     {
1279         // it's not really the parent name in this case
1280         CustomStyle* namedStyle = styles->style(parentName());
1281         // remove substyles already present in named style
1282         if (namedStyle) keys = difference(*namedStyle);
1283     }
1284     else
1285         keys = QSet<Style::Key>::fromList(d->subStyles.keys());
1286 
1287     return keys;
1288 }
1289 
1290 QList<SharedSubStyle> Style::subStyles() const
1291 {
1292     return d->subStyles.values();
1293 }
1294 
1295 SharedSubStyle Style::createSubStyle(Key key, const QVariant& value)
1296 {
1297     SharedSubStyle newSubStyle;
1298     switch (key) {
1299         // special cases
1300     case DefaultStyleKey:
1301         newSubStyle = new SubStyle();
1302         break;
1303     case NamedStyleKey:
1304         newSubStyle = new NamedStyle(value.value<QString>());
1305         break;
1306     case LeftPen:
1307         newSubStyle = new BorderPenStyle<LeftPen>(value.value<QPen>());
1308         break;
1309     case RightPen:
1310         newSubStyle = new BorderPenStyle<RightPen>(value.value<QPen>());
1311         break;
1312     case TopPen:
1313         newSubStyle = new BorderPenStyle<TopPen>(value.value<QPen>());
1314         break;
1315     case BottomPen:
1316         newSubStyle = new BorderPenStyle<BottomPen>(value.value<QPen>());
1317         break;
1318     case FallDiagonalPen:
1319         newSubStyle = new BorderPenStyle<FallDiagonalPen>(value.value<QPen>());
1320         break;
1321     case GoUpDiagonalPen:
1322         newSubStyle = new BorderPenStyle<GoUpDiagonalPen>(value.value<QPen>());
1323         break;
1324         // layout
1325     case HorizontalAlignment:
1326         newSubStyle = new SubStyleOne<HorizontalAlignment, HAlign>((HAlign)value.value<int>());
1327         break;
1328     case VerticalAlignment:
1329         newSubStyle = new SubStyleOne<VerticalAlignment, VAlign>((VAlign)value.value<int>());
1330         break;
1331     case MultiRow:
1332         newSubStyle = new SubStyleOne<MultiRow, bool>(value.value<bool>());
1333         break;
1334     case VerticalText:
1335         newSubStyle = new SubStyleOne<VerticalText, bool>(value.value<bool>());
1336         break;
1337     case Angle:
1338         newSubStyle = new SubStyleOne<Angle, int>(value.value<int>());
1339         break;
1340     case Indentation:
1341         newSubStyle = new SubStyleOne<Indentation, int>(value.value<int>());
1342         break;
1343     case ShrinkToFit:
1344         newSubStyle = new SubStyleOne<ShrinkToFit,bool>(value.value<bool>());
1345         break;
1346         // content format
1347     case Prefix:
1348         newSubStyle = new SubStyleOne<Prefix, QString>(value.value<QString>());
1349         break;
1350     case Postfix:
1351         newSubStyle = new SubStyleOne<Postfix, QString>(value.value<QString>());
1352         break;
1353     case Precision:
1354         newSubStyle = new SubStyleOne<Precision, int>(value.value<int>());
1355         break;
1356     case ThousandsSep:
1357         newSubStyle = new SubStyleOne<ThousandsSep, bool>(value.value<bool>());
1358         break;
1359     case FormatTypeKey:
1360         newSubStyle = new SubStyleOne<FormatTypeKey, Format::Type>((Format::Type)value.value<int>());
1361         break;
1362     case FloatFormatKey:
1363         newSubStyle = new SubStyleOne<FloatFormatKey, FloatFormat>((FloatFormat)value.value<int>());
1364         break;
1365     case FloatColorKey:
1366         newSubStyle = new SubStyleOne<FloatColorKey, FloatColor>((FloatColor)value.value<int>());
1367         break;
1368     case CurrencyFormat:
1369         newSubStyle = new SubStyleOne<CurrencyFormat, Currency>(value.value<Currency>());
1370         break;
1371     case CustomFormat:
1372         newSubStyle = new SubStyleOne<CustomFormat, QString>(value.value<QString>());
1373         break;
1374         // background
1375     case BackgroundBrush:
1376         newSubStyle = new SubStyleOne<BackgroundBrush, QBrush>(value.value<QBrush>());
1377         break;
1378     case BackgroundColor:
1379         newSubStyle = new SubStyleOne<BackgroundColor, QColor>(value.value<QColor>());
1380         break;
1381         // font
1382     case FontColor:
1383         newSubStyle = new SubStyleOne<FontColor, QColor>(value.value<QColor>());
1384         break;
1385     case FontFamily:
1386         newSubStyle = new SubStyleOne<FontFamily, QString>(value.value<QString>());
1387         break;
1388     case FontSize:
1389         newSubStyle = new SubStyleOne<FontSize, int>(value.value<int>());
1390         break;
1391     case FontBold:
1392         newSubStyle = new SubStyleOne<FontBold, bool>(value.value<bool>());
1393         break;
1394     case FontItalic:
1395         newSubStyle = new SubStyleOne<FontItalic, bool>(value.value<bool>());
1396         break;
1397     case FontStrike:
1398         newSubStyle = new SubStyleOne<FontStrike, bool>(value.value<bool>());
1399         break;
1400     case FontUnderline:
1401         newSubStyle = new SubStyleOne<FontUnderline, bool>(value.value<bool>());
1402         break;
1403         //misc
1404     case DontPrintText:
1405         newSubStyle = new SubStyleOne<DontPrintText, bool>(value.value<bool>());
1406         break;
1407     case NotProtected:
1408         newSubStyle = new SubStyleOne<NotProtected, bool>(value.value<bool>());
1409         break;
1410     case HideAll:
1411         newSubStyle = new SubStyleOne<HideAll, bool>(value.value<bool>());
1412         break;
1413     case HideFormula:
1414         newSubStyle = new SubStyleOne<HideFormula, bool>(value.value<bool>());
1415         break;
1416     }
1417     return newSubStyle;
1418 }
1419 
1420 void Style::insertSubStyle(Key key, const QVariant& value)
1421 {
1422     const SharedSubStyle subStyle = createSubStyle(key, value);
1423     Q_ASSERT(!!subStyle);
1424     insertSubStyle(subStyle);
1425 }
1426 
1427 void Style::insertSubStyle(const SharedSubStyle& subStyle)
1428 {
1429     if (!subStyle)
1430         return;
1431     releaseSubStyle(subStyle->type());
1432     d->subStyles.insert(subStyle->type(), subStyle);
1433 }
1434 
1435 bool Style::releaseSubStyle(Key key)
1436 {
1437     if (!d->subStyles.contains(key))
1438         return false;
1439 
1440     d->subStyles.remove(key);
1441     return true;
1442 }
1443 
1444 /////////////////////////////////////////////////////////////////////////////
1445 //
1446 // CustomStyle::Private
1447 //
1448 /////////////////////////////////////////////////////////////////////////////
1449 
1450 class Q_DECL_HIDDEN CustomStyle::Private : public QSharedData
1451 {
1452 public:
1453     QString name;
1454     StyleType type;
1455 };
1456 
1457 
1458 /////////////////////////////////////////////////////////////////////////////
1459 //
1460 // CustomStyle
1461 //
1462 /////////////////////////////////////////////////////////////////////////////
1463 
1464 CustomStyle::CustomStyle()
1465         : Style()
1466         , d(new Private)
1467 {
1468     d->name = "Default";
1469     d->type = BUILTIN;
1470     setDefault();
1471 }
1472 
1473 CustomStyle::CustomStyle(QString const & name, CustomStyle * parent)
1474         : Style()
1475         , d(new Private)
1476 {
1477     d->name = name;
1478     d->type = CUSTOM;
1479     if (parent)
1480         setParentName(parent->name());
1481 }
1482 
1483 CustomStyle::CustomStyle(const CustomStyle& style)
1484         : Style(style), d(style.d)
1485 {
1486 }
1487 
1488 CustomStyle::~CustomStyle()
1489 {
1490 }
1491 
1492 CustomStyle& CustomStyle::operator=(const CustomStyle& style)
1493 {
1494     Style::operator=(style);
1495     d = style.d;
1496     return *this;
1497 }
1498 
1499 Style::StyleType CustomStyle::type() const
1500 {
1501     return d->type;
1502 }
1503 
1504 void CustomStyle::setType(StyleType type)
1505 {
1506     Q_ASSERT(type != AUTO);
1507     d->type = type;
1508 }
1509 
1510 const QString& CustomStyle::name() const
1511 {
1512     return d->name;
1513 }
1514 
1515 void CustomStyle::setName(QString const & name)
1516 {
1517     d->name = name;
1518 }
1519 
1520 void CustomStyle::save(QDomDocument& doc, QDomElement& styles, const StyleManager* styleManager)
1521 {
1522     if (name().isEmpty())
1523         return;
1524 
1525     QDomElement style(doc.createElement("style"));
1526     style.setAttribute("type", QString::number((int) type()));
1527     if (!parentName().isNull())
1528         style.setAttribute("parent", parentName());
1529     style.setAttribute("name", name());
1530 
1531     QDomElement format(doc.createElement("format"));
1532     saveXML(doc, format, styleManager);
1533     style.appendChild(format);
1534 
1535     styles.appendChild(style);
1536 }
1537 
1538 bool CustomStyle::loadXML(KoXmlElement const & style, QString const & name)
1539 {
1540     setName(name);
1541 
1542     if (style.hasAttribute("parent"))
1543         setParentName(style.attribute("parent"));
1544 
1545     if (!style.hasAttribute("type"))
1546         return false;
1547 
1548     bool ok = true;
1549     setType((StyleType) style.attribute("type").toInt(&ok));
1550     if (!ok)
1551         return false;
1552 
1553     KoXmlElement f(style.namedItem("format").toElement());
1554     if (!f.isNull())
1555         if (!Style::loadXML(f))
1556             return false;
1557 
1558     return true;
1559 }
1560 
1561 int CustomStyle::usage() const
1562 {
1563     return d->ref;
1564 }
1565 
1566 QSet<Style::Key> CustomStyle::definedKeys(const StyleManager *) const
1567 {
1568     QList<SharedSubStyle> subs = subStyles();
1569     QSet<Style::Key> keys;
1570     for (int i = 0; i < subs.count(); ++i)
1571         keys.insert(subs[i].data()->type());
1572     return keys;
1573 }
1574 
1575 QDebug operator<<(QDebug dbg, const Calligra::Sheets::Style *s)
1576 {
1577     if (s) {
1578         dbg << (*s);
1579     } else {
1580         dbg << "Style[0x0]";
1581     }
1582     return dbg;
1583 }
1584 
1585 QDebug operator<<(QDebug dbg, const Calligra::Sheets::Style &s)
1586 {
1587     static const char *types[] = {"Builtin", "Custom", "Auto", "Tentative"};
1588     dbg << "Style["<<types[s.type()]<<"]";
1589     return dbg;
1590 }