1 /* This file is part of the KDE project
2    Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org>
3    Copyright 2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
4    Copyright 2003 Norbert Andres <nandres@web.de>
5 
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10 
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public License
17    along with this library; see the file COPYING.LIB.  If not, write to
18    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19    Boston, MA 02110-1301, USA.
20 */
21 
22 // Local
23 #include "Style.h"
24 
25 #include <QBrush>
26 #include <QHash>
27 #include <QPen>
28 #include <QFontDatabase>
29 
30 #include <KoGlobal.h>
31 
32 #include "SheetsDebug.h"
33 #include "Currency.h"
34 #include "Global.h"
35 #include "StyleManager.h"
36 #include "Util.h"
37 
38 using namespace Calligra::Sheets;
39 
40 /////////////////////////////////////////////////////////////////////////////
41 //
42 // SubStyles
43 //
44 /////////////////////////////////////////////////////////////////////////////
45 
46 namespace Calligra
47 {
48 namespace Sheets
49 {
50 
calculateValue(QPen const & pen)51 static uint calculateValue(QPen const & pen)
52 {
53     uint n = pen.color().red() + pen.color().green() + pen.color().blue();
54     n += 1000 * pen.width();
55     n += 10000 * (uint) pen.style();
56     return n;
57 }
58 
59 // specialized debug method
60 template<>
debugData(bool withName) const61 QString SubStyleOne<Style::CurrencyFormat, Currency>::debugData(bool withName) const
62 {
63     QString out; if (withName) out = name(Style::CurrencyFormat) + ' '; QDebug qdbg(&out); qdbg << value1.symbol(); return out;
64 }
65 
66 template<Style::Key key>
67 class PenStyle : public SubStyleOne<key, QPen>
68 {
69 public:
PenStyle(const QPen & p=Qt::NoPen)70     PenStyle(const QPen& p = Qt::NoPen) : SubStyleOne<key, QPen>(p) {}
71 };
72 
73 template<Style::Key key>
74 class BorderPenStyle : public PenStyle<key>
75 {
76 public:
BorderPenStyle(const QPen & p=Qt::NoPen)77     BorderPenStyle(const QPen& p = Qt::NoPen) : PenStyle<key>(p), value(calculateValue(p)) {}
78     int value;
79 };
80 
name(Style::Key key)81 QString SubStyle::name(Style::Key key)
82 {
83     QString name;
84     switch (key) {
85     case Style::DefaultStyleKey:        name = "Default style"; break;
86     case Style::NamedStyleKey:          name = "Named style"; break;
87     case Style::LeftPen:                name = "Left pen"; break;
88     case Style::RightPen:               name = "Right pen"; break;
89     case Style::TopPen:                 name = "Top pen"; break;
90     case Style::BottomPen:              name = "Bottom pen"; break;
91     case Style::FallDiagonalPen:        name = "Fall diagonal pen"; break;
92     case Style::GoUpDiagonalPen:        name = "Go up diagonal pen"; break;
93     case Style::HorizontalAlignment:    name = "Horz. alignment"; break;
94     case Style::VerticalAlignment:      name = "Vert. alignment"; break;
95     case Style::MultiRow:               name = "Wrap text"; break;
96     case Style::VerticalText:           name = "Vertical text"; break;
97     case Style::Angle:                  name = "Angle"; break;
98     case Style::Indentation:            name = "Indentation"; break;
99     case Style::ShrinkToFit:            name = "Shrink to Fit"; break;
100     case Style::Prefix:                 name = "Prefix"; break;
101     case Style::Postfix:                name = "Postfix"; break;
102     case Style::Precision:              name = "Precision"; break;
103     case Style::ThousandsSep:           name = "Thousands separator"; break;
104     case Style::FormatTypeKey:          name = "Format type"; break;
105     case Style::FloatFormatKey:         name = "Float format"; break;
106     case Style::FloatColorKey:          name = "Float color"; break;
107     case Style::CurrencyFormat:         name = "Currency"; break;
108     case Style::CustomFormat:           name = "Custom format"; break;
109     case Style::BackgroundBrush:        name = "Background brush"; break;
110     case Style::BackgroundColor:        name = "Background color"; break;
111     case Style::FontColor:              name = "Font color"; break;
112     case Style::FontFamily:             name = "Font family"; break;
113     case Style::FontSize:               name = "Font size"; break;
114     case Style::FontBold:               name = "Font bold"; break;
115     case Style::FontItalic:             name = "Font italic"; break;
116     case Style::FontStrike:             name = "Font strikeout"; break;
117     case Style::FontUnderline:          name = "Font underline"; break;
118     case Style::DontPrintText:          name = "Do not print text"; break;
119     case Style::NotProtected:           name = "Not protected"; break;
120     case Style::HideAll:                name = "Hide all"; break;
121     case Style::HideFormula:            name = "Hide formula"; break;
122     }
123     return name;
124 }
125 
126 SharedSubStyle SharedSubStyle::s_defaultStyle(new SubStyle());
127 
128 } // namespace Sheets
129 } // namespace Calligra
130 
131 /////////////////////////////////////////////////////////////////////////////
132 //
133 // Style::Private
134 //
135 /////////////////////////////////////////////////////////////////////////////
136 
137 class Q_DECL_HIDDEN Style::Private : public QSharedData
138 {
139 public:
140     QHash<Key, SharedSubStyle> subStyles;
141 };
142 
143 
144 /////////////////////////////////////////////////////////////////////////////
145 //
146 // Style
147 //
148 /////////////////////////////////////////////////////////////////////////////
149 
Style()150 Style::Style()
151         : d(new Private)
152 {
153 }
154 
Style(const Style & style)155 Style::Style(const Style& style)
156         : d(style.d)
157 {
158 }
159 
~Style()160 Style::~Style()
161 {
162 }
163 
type() const164 Style::StyleType Style::type() const
165 {
166     return AUTO;
167 }
168 
parentName() const169 QString Style::parentName() const
170 {
171     if (!d->subStyles.contains(NamedStyleKey))
172         return QString();
173     return static_cast<const NamedStyle*>(d->subStyles[NamedStyleKey].data())->name;
174 }
175 
setParentName(const QString & name)176 void Style::setParentName(const QString& name)
177 {
178     d->subStyles.insert(NamedStyleKey, SharedSubStyle(new NamedStyle(name)));
179 }
180 
clearAttribute(Key key)181 void Style::clearAttribute(Key key)
182 {
183     d->subStyles.remove(key);
184 }
185 
hasAttribute(Key key) const186 bool Style::hasAttribute(Key key) const
187 {
188     return d->subStyles.contains(key);
189 }
190 
191 
saveXML(QDomDocument & doc,QDomElement & format,const StyleManager * styleManager) const192 void Style::saveXML(QDomDocument& doc, QDomElement& format, const StyleManager* styleManager) const
193 {
194     // list of substyles to store
195     QSet<Key> keysToStore;
196 
197     if (d->subStyles.contains(NamedStyleKey)) {
198         const CustomStyle* namedStyle = styleManager->style(parentName());
199         // check, if it's an unmodified named style
200         keysToStore = difference(*namedStyle);
201         if (type() == AUTO) {
202             const QList<Key> keys = keysToStore.toList();
203             if ((keysToStore.count() == 0) ||
204                     (keysToStore.count() == 1 && keysToStore.toList().first() == NamedStyleKey)) {
205                 // just save the name and we are done.
206                 format.setAttribute("style-name", parentName());
207                 return;
208             } else
209                 format.setAttribute("parent", parentName());
210         } else { // custom style
211             if (d->subStyles.contains(NamedStyleKey))
212                 format.setAttribute("parent", parentName());
213         }
214     } else
215         keysToStore = QSet<Key>::fromList(d->subStyles.keys());
216 
217     if (keysToStore.contains(HorizontalAlignment) && halign() != HAlignUndefined)
218         format.setAttribute(type() == AUTO ? "align" : "alignX", (int) halign());
219 
220     if (keysToStore.contains(VerticalAlignment) && valign() != VAlignUndefined)
221         format.setAttribute("alignY", QString::number((int) valign()));
222 
223     if (keysToStore.contains(BackgroundColor) && backgroundColor().isValid())
224         format.setAttribute("bgcolor", backgroundColor().name());
225 
226     if (keysToStore.contains(MultiRow) && wrapText())
227         format.setAttribute("multirow", "yes");
228 
229     if (keysToStore.contains(VerticalText) && verticalText())
230         format.setAttribute("verticaltext", "yes");
231 
232     if (keysToStore.contains(ShrinkToFit) && shrinkToFit())
233         format.setAttribute("shrinktofit", "yes");
234 
235     if (keysToStore.contains(Precision))
236         format.setAttribute("precision", QString::number(precision()));
237 
238     if (keysToStore.contains(Prefix) && !prefix().isEmpty())
239         format.setAttribute("prefix", prefix());
240 
241     if (keysToStore.contains(Postfix) && !postfix().isEmpty())
242         format.setAttribute("postfix", postfix());
243 
244     if (keysToStore.contains(FloatFormatKey))
245         format.setAttribute("float", QString::number((int) floatFormat()));
246 
247     if (keysToStore.contains(FloatColorKey))
248         format.setAttribute("floatcolor", QString::number((int)floatColor()));
249 
250     if (keysToStore.contains(FormatTypeKey))
251         format.setAttribute("format", QString::number((int) formatType()));
252 
253     if (keysToStore.contains(CustomFormat) && !customFormat().isEmpty())
254         format.setAttribute("custom", customFormat());
255 
256     if (keysToStore.contains(FormatTypeKey) && formatType() == Format::Money) {
257         format.setAttribute("type", (int) currency().index());
258         format.setAttribute("symbol", currency().symbol());
259     }
260 
261     if (keysToStore.contains(Angle))
262         format.setAttribute("angle", QString::number(angle()));
263 
264     if (keysToStore.contains(Indentation))
265         format.setAttribute("indent", QString::number(indentation()));
266 
267     if (keysToStore.contains(DontPrintText))
268         format.setAttribute("dontprinttext", printText() ? "no" : "yes");
269 
270     if (keysToStore.contains(NotProtected))
271         format.setAttribute("noprotection", notProtected() ? "yes" : "no");
272 
273     if (keysToStore.contains(HideAll))
274         format.setAttribute("hideall", hideAll() ? "yes" : "no");
275 
276     if (keysToStore.contains(HideFormula))
277         format.setAttribute("hideformula", hideFormula() ? "yes" : "no");
278 
279     if (type() == AUTO) {
280         if (keysToStore.contains(FontFamily) ||
281                 keysToStore.contains(FontSize) ||
282                 keysToStore.contains(FontBold) ||
283                 keysToStore.contains(FontItalic) ||
284                 keysToStore.contains(FontStrike) ||
285                 keysToStore.contains(FontUnderline)) {
286             format.appendChild(NativeFormat::createElement("font", font(), doc));
287         }
288     } else { // custom style
289         if (keysToStore.contains(FontFamily))
290             format.setAttribute("font-family", fontFamily());
291         if (keysToStore.contains(FontSize))
292             format.setAttribute("font-size", QString::number(fontSize()));
293         if (keysToStore.contains(FontBold) || keysToStore.contains(FontItalic) ||
294                 keysToStore.contains(FontUnderline) || keysToStore.contains(FontStrike)) {
295             enum FontFlags {
296                 FBold      = 0x01,
297                 FUnderline = 0x02,
298                 FItalic    = 0x04,
299                 FStrike    = 0x08
300             };
301             int fontFlags = 0;
302             fontFlags |= bold()      ? FBold      : 0;
303             fontFlags |= italic()    ? FItalic    : 0;
304             fontFlags |= underline() ? FUnderline : 0;
305             fontFlags |= strikeOut() ? FStrike    : 0;
306             format.setAttribute("font-flags", QString::number(fontFlags));
307         }
308     }
309 
310     if (keysToStore.contains(FontColor) && fontColor().isValid())
311         format.appendChild(NativeFormat::createElement("pen", fontColor(), doc));
312 
313     if (keysToStore.contains(BackgroundBrush)) {
314         format.setAttribute("brushcolor", backgroundBrush().color().name());
315         format.setAttribute("brushstyle", QString::number((int) backgroundBrush().style()));
316     }
317 
318     if (keysToStore.contains(LeftPen)) {
319         QDomElement left = doc.createElement("left-border");
320         left.appendChild(NativeFormat::createElement("pen", leftBorderPen(), doc));
321         format.appendChild(left);
322     }
323 
324     if (keysToStore.contains(TopPen)) {
325         QDomElement top = doc.createElement("top-border");
326         top.appendChild(NativeFormat::createElement("pen", topBorderPen(), doc));
327         format.appendChild(top);
328     }
329 
330     if (keysToStore.contains(RightPen)) {
331         QDomElement right = doc.createElement("right-border");
332         right.appendChild(NativeFormat::createElement("pen", rightBorderPen(), doc));
333         format.appendChild(right);
334     }
335 
336     if (keysToStore.contains(BottomPen)) {
337         QDomElement bottom = doc.createElement("bottom-border");
338         bottom.appendChild(NativeFormat::createElement("pen", bottomBorderPen(), doc));
339         format.appendChild(bottom);
340     }
341 
342     if (keysToStore.contains(FallDiagonalPen)) {
343         QDomElement fallDiagonal  = doc.createElement("fall-diagonal");
344         fallDiagonal.appendChild(NativeFormat::createElement("pen", fallDiagonalPen(), doc));
345         format.appendChild(fallDiagonal);
346     }
347 
348     if (keysToStore.contains(GoUpDiagonalPen)) {
349         QDomElement goUpDiagonal = doc.createElement("up-diagonal");
350         goUpDiagonal.appendChild(NativeFormat::createElement("pen", goUpDiagonalPen(), doc));
351         format.appendChild(goUpDiagonal);
352     }
353 }
354 
loadXML(KoXmlElement & format,Paste::Mode mode)355 bool Style::loadXML(KoXmlElement& format, Paste::Mode mode)
356 {
357     if (format.hasAttribute("style-name")) {
358         // Simply set the style name and we are done.
359         insertSubStyle(NamedStyleKey, format.attribute("style-name"));
360         return true;
361     } else if (format.hasAttribute("parent"))
362         insertSubStyle(NamedStyleKey, format.attribute("parent"));
363 
364     bool ok;
365     if (format.hasAttribute(type() == AUTO ? "align" : "alignX")) {
366         HAlign a = (HAlign) format.attribute(type() == AUTO ? "align" : "alignX").toInt(&ok);
367         if (!ok)
368             return false;
369         if ((unsigned int) a >= 1 && (unsigned int) a <= 4) {
370             setHAlign(a);
371         }
372     }
373     if (format.hasAttribute("alignY")) {
374         VAlign a = (VAlign) format.attribute("alignY").toInt(&ok);
375         if (!ok)
376             return false;
377         if ((unsigned int) a >= 1 && (unsigned int) a < 4) {
378             setVAlign(a);
379         }
380     }
381 
382     if (format.hasAttribute("bgcolor")) {
383         QColor color(format.attribute("bgcolor"));
384         if (color.isValid())
385             setBackgroundColor(color);
386     }
387 
388     if (format.hasAttribute("multirow")) {
389         setWrapText(true);
390     }
391 
392     if (format.hasAttribute("shrinktofit")) {
393         setShrinkToFit(true);
394     }
395 
396     if (format.hasAttribute("precision")) {
397         int i = format.attribute("precision").toInt(&ok);
398         if (i < -1) {
399             debugSheetsODF << "Value out of range Cell::precision=" << i;
400             return false;
401         }
402         // special handling for precision
403         // The Style default (-1) and the storage default (0) differ.
404         if (type() == AUTO && i == -1)
405             i = 0;
406         // The maximum is 10. Replace the Style value 0 with -11, which always results
407         // in a storage value < 0 and is interpreted as Style value 0.
408         else if (type() == AUTO && i == 0)
409             i = -11;
410         setPrecision(i);
411     }
412 
413     if (format.hasAttribute("float")) {
414         FloatFormat a = (FloatFormat)format.attribute("float").toInt(&ok);
415         if (!ok)
416             return false;
417         if ((unsigned int) a >= 1 && (unsigned int) a <= 3) {
418             setFloatFormat(a);
419         }
420     }
421 
422     if (format.hasAttribute("floatcolor")) {
423         FloatColor a = (FloatColor) format.attribute("floatcolor").toInt(&ok);
424         if (!ok) return false;
425         if ((unsigned int) a >= 1 && (unsigned int) a <= 2) {
426             setFloatColor(a);
427         }
428     }
429 
430     if (format.hasAttribute("format")) {
431         int fo = format.attribute("format").toInt(&ok);
432         if (! ok)
433             return false;
434         setFormatType(static_cast<Format::Type>(fo));
435     }
436     if (format.hasAttribute("custom")) {
437         setCustomFormat(format.attribute("custom"));
438     }
439     if (formatType() == Format::Money) {
440         ok = true;
441         Currency currency;
442         if (format.hasAttribute("type")) {
443             currency = Currency(format.attribute("type").toInt(&ok));
444             if (!ok) {
445                 if (format.hasAttribute("symbol"))
446                     currency = Currency(format.attribute("symbol"));
447             }
448         } else if (format.hasAttribute("symbol"))
449             currency = Currency(format.attribute("symbol"));
450         setCurrency(currency);
451     }
452     if (format.hasAttribute("angle")) {
453         setAngle(format.attribute("angle").toInt(&ok));
454         if (!ok)
455             return false;
456     }
457     if (format.hasAttribute("indent")) {
458         setIndentation(format.attribute("indent").toDouble(&ok));
459         if (!ok)
460             return false;
461     }
462     if (format.hasAttribute("dontprinttext")) {
463         setDontPrintText(true);
464     }
465 
466     if (format.hasAttribute("noprotection")) {
467         setNotProtected(true);
468     }
469 
470     if (format.hasAttribute("hideall")) {
471         setHideAll(true);
472     }
473 
474     if (format.hasAttribute("hideformula")) {
475         setHideFormula(true);
476     }
477 
478     if (type() == AUTO) {
479         KoXmlElement fontElement = format.namedItem("font").toElement();
480         if (!fontElement.isNull()) {
481             QFont font(NativeFormat::toFont(fontElement));
482             setFontFamily(font.family());
483             setFontSize(font.pointSize());
484             if (font.italic())
485                 setFontItalic(true);
486             if (font.bold())
487                 setFontBold(true);
488             if (font.underline())
489                 setFontUnderline(true);
490             if (font.strikeOut())
491                 setFontStrikeOut(true);
492         }
493     } else { // custom style
494         if (format.hasAttribute("font-family"))
495             setFontFamily(format.attribute("font-family"));
496         if (format.hasAttribute("font-size")) {
497             setFontSize(format.attribute("font-size").toInt(&ok));
498             if (!ok)
499                 return false;
500         }
501         if (format.hasAttribute("font-flags")) {
502             int fontFlags = format.attribute("font-flags").toInt(&ok);
503             if (!ok)
504                 return false;
505 
506             enum FontFlags {
507                 FBold      = 0x01,
508                 FUnderline = 0x02,
509                 FItalic    = 0x04,
510                 FStrike    = 0x08
511             };
512             setFontBold(fontFlags & FBold);
513             setFontItalic(fontFlags & FItalic);
514             setFontUnderline(fontFlags & FUnderline);
515             setFontStrikeOut(fontFlags & FStrike);
516         }
517     }
518 
519     if (format.hasAttribute("brushcolor")) {
520         QColor color(format.attribute("brushcolor"));
521         if (color.isValid()) {
522             QBrush brush = backgroundBrush();
523             brush.setColor(color);
524             setBackgroundBrush(brush);
525         }
526     }
527 
528     if (format.hasAttribute("brushstyle")) {
529         QBrush brush = backgroundBrush();
530         brush.setStyle((Qt::BrushStyle) format.attribute("brushstyle").toInt(&ok));
531         if (!ok)
532             return false;
533         setBackgroundBrush(brush);
534     }
535 
536     KoXmlElement pen = format.namedItem("pen").toElement();
537     if (!pen.isNull()) {
538         setFontColor(NativeFormat::toPen(pen).color());
539     }
540 
541     if (mode != Paste::NoBorder) {
542         KoXmlElement left = format.namedItem("left-border").toElement();
543         if (!left.isNull()) {
544             KoXmlElement pen = left.namedItem("pen").toElement();
545             if (!pen.isNull())
546                 setLeftBorderPen(NativeFormat::toPen(pen));
547         }
548 
549         KoXmlElement top = format.namedItem("top-border").toElement();
550         if (!top.isNull()) {
551             KoXmlElement pen = top.namedItem("pen").toElement();
552             if (!pen.isNull())
553                 setTopBorderPen(NativeFormat::toPen(pen));
554         }
555 
556         KoXmlElement right = format.namedItem("right-border").toElement();
557         if (!right.isNull()) {
558             KoXmlElement pen = right.namedItem("pen").toElement();
559             if (!pen.isNull())
560                 setRightBorderPen(NativeFormat::toPen(pen));
561         }
562 
563         KoXmlElement bottom = format.namedItem("bottom-border").toElement();
564         if (!bottom.isNull()) {
565             KoXmlElement pen = bottom.namedItem("pen").toElement();
566             if (!pen.isNull())
567                 setBottomBorderPen(NativeFormat::toPen(pen));
568         }
569 
570         KoXmlElement fallDiagonal = format.namedItem("fall-diagonal").toElement();
571         if (!fallDiagonal.isNull()) {
572             KoXmlElement pen = fallDiagonal.namedItem("pen").toElement();
573             if (!pen.isNull())
574                 setFallDiagonalPen(NativeFormat::toPen(pen));
575         }
576 
577         KoXmlElement goUpDiagonal = format.namedItem("up-diagonal").toElement();
578         if (!goUpDiagonal.isNull()) {
579             KoXmlElement pen = goUpDiagonal.namedItem("pen").toElement();
580             if (!pen.isNull())
581                 setGoUpDiagonalPen(NativeFormat::toPen(pen));
582         }
583     }
584 
585     if (format.hasAttribute("prefix")) {
586         setPrefix(format.attribute("prefix"));
587     }
588     if (format.hasAttribute("postfix")) {
589         setPostfix(format.attribute("postfix"));
590     }
591 
592     return true;
593 }
594 
bottomPenValue() const595 uint Style::bottomPenValue() const
596 {
597     if (!d->subStyles.contains(BottomPen))
598         return BorderPenStyle<BottomPen>().value;
599     return static_cast<const BorderPenStyle<BottomPen>*>(d->subStyles[BottomPen].data())->value;
600 }
601 
rightPenValue() const602 uint Style::rightPenValue() const
603 {
604     if (!d->subStyles.contains(RightPen))
605         return BorderPenStyle<RightPen>().value;
606     return static_cast<const BorderPenStyle<RightPen>*>(d->subStyles[RightPen].data())->value;
607 }
608 
leftPenValue() const609 uint Style::leftPenValue() const
610 {
611     if (!d->subStyles.contains(LeftPen))
612         return BorderPenStyle<LeftPen>().value;
613     return static_cast<const BorderPenStyle<LeftPen>*>(d->subStyles[LeftPen].data())->value;
614 }
615 
topPenValue() const616 uint Style::topPenValue() const
617 {
618     if (!d->subStyles.contains(TopPen))
619         return BorderPenStyle<TopPen>().value;
620     return static_cast<const BorderPenStyle<TopPen>*>(d->subStyles[TopPen].data())->value;
621 }
622 
fontColor() const623 QColor Style::fontColor() const
624 {
625     if (!d->subStyles.contains(FontColor))
626         return SubStyleOne<FontColor, QColor>(Qt::black).value1;
627     return static_cast<const SubStyleOne<FontColor, QColor>*>(d->subStyles[FontColor].data())->value1;
628 }
629 
backgroundColor() const630 QColor Style::backgroundColor() const
631 {
632     if (!d->subStyles.contains(BackgroundColor))
633         return SubStyleOne<BackgroundColor, QColor>().value1;
634     return static_cast<const SubStyleOne<BackgroundColor, QColor>*>(d->subStyles[BackgroundColor].data())->value1;
635 }
636 
rightBorderPen() const637 QPen Style::rightBorderPen() const
638 {
639     if (!d->subStyles.contains(RightPen))
640         return BorderPenStyle<RightPen>().value1;
641     return static_cast<const BorderPenStyle<RightPen>*>(d->subStyles[RightPen].data())->value1;
642 }
643 
bottomBorderPen() const644 QPen Style::bottomBorderPen() const
645 {
646     if (!d->subStyles.contains(BottomPen))
647         return BorderPenStyle<BottomPen>().value1;
648     return static_cast<const BorderPenStyle<BottomPen>*>(d->subStyles[BottomPen].data())->value1;
649 }
650 
leftBorderPen() const651 QPen Style::leftBorderPen() const
652 {
653     if (!d->subStyles.contains(LeftPen))
654         return BorderPenStyle<LeftPen>().value1;
655     return static_cast<const BorderPenStyle<LeftPen>*>(d->subStyles[LeftPen].data())->value1;
656 }
657 
topBorderPen() const658 QPen Style::topBorderPen() const
659 {
660     if (!d->subStyles.contains(TopPen))
661         return BorderPenStyle<TopPen>().value1;
662     return static_cast<const BorderPenStyle<TopPen>*>(d->subStyles[TopPen].data())->value1;
663 }
664 
fallDiagonalPen() const665 QPen Style::fallDiagonalPen() const
666 {
667     if (!d->subStyles.contains(FallDiagonalPen))
668         return PenStyle<FallDiagonalPen>().value1;
669     return static_cast<const PenStyle<FallDiagonalPen>*>(d->subStyles[FallDiagonalPen].data())->value1;
670 }
671 
goUpDiagonalPen() const672 QPen Style::goUpDiagonalPen() const
673 {
674     if (!d->subStyles.contains(GoUpDiagonalPen))
675         return PenStyle<GoUpDiagonalPen>().value1;
676     return static_cast<const PenStyle<GoUpDiagonalPen>*>(d->subStyles[GoUpDiagonalPen].data())->value1;
677 }
678 
backgroundBrush() const679 QBrush Style::backgroundBrush() const
680 {
681     if (!d->subStyles.contains(BackgroundBrush))
682         return SubStyleOne<BackgroundBrush, QBrush>(Qt::white).value1;
683     return static_cast<const SubStyleOne<BackgroundBrush, QBrush>*>(d->subStyles[BackgroundBrush].data())->value1;
684 }
685 
customFormat() const686 QString Style::customFormat() const
687 {
688     if (!d->subStyles.contains(CustomFormat))
689         return SubStyleOne<CustomFormat, QString>().value1;
690     return static_cast<const SubStyleOne<CustomFormat, QString>*>(d->subStyles[CustomFormat].data())->value1;
691 }
692 
prefix() const693 QString Style::prefix() const
694 {
695     if (!d->subStyles.contains(Prefix))
696         return SubStyleOne<Prefix, QString>().value1;
697     return static_cast<const SubStyleOne<Prefix, QString>*>(d->subStyles[Prefix].data())->value1;
698 }
699 
postfix() const700 QString Style::postfix() const
701 {
702     if (!d->subStyles.contains(Postfix))
703         return SubStyleOne<Postfix, QString>().value1;
704     return static_cast<const SubStyleOne<Postfix, QString>*>(d->subStyles[Postfix].data())->value1;
705 }
706 
fontFamily() const707 QString Style::fontFamily() const
708 {
709     if (!d->subStyles.contains(FontFamily))
710         return KoGlobal::defaultFont().family(); // SubStyleOne<FontFamily, QString>().value1;
711     return static_cast<const SubStyleOne<FontFamily, QString>*>(d->subStyles[FontFamily].data())->value1;
712 }
713 
halign() const714 Style::HAlign Style::halign() const
715 {
716     if (!d->subStyles.contains(HorizontalAlignment))
717         return SubStyleOne<HorizontalAlignment, Style::HAlign>().value1;
718     return static_cast<const SubStyleOne<HorizontalAlignment, Style::HAlign>*>(d->subStyles[HorizontalAlignment].data())->value1;
719 }
720 
valign() const721 Style::VAlign Style::valign() const
722 {
723     if (!d->subStyles.contains(VerticalAlignment))
724         return SubStyleOne<VerticalAlignment, Style::VAlign>().value1;
725     return static_cast<const SubStyleOne<VerticalAlignment, Style::VAlign>*>(d->subStyles[VerticalAlignment].data())->value1;
726 }
727 
floatFormat() const728 Style::FloatFormat Style::floatFormat() const
729 {
730     if (!d->subStyles.contains(FloatFormatKey))
731         return SubStyleOne<FloatFormatKey, FloatFormat>().value1;
732     return static_cast<const SubStyleOne<FloatFormatKey, FloatFormat>*>(d->subStyles[FloatFormatKey].data())->value1;
733 }
734 
floatColor() const735 Style::FloatColor Style::floatColor() const
736 {
737     if (!d->subStyles.contains(FloatColorKey))
738         return SubStyleOne<FloatColorKey, FloatColor>().value1;
739     return static_cast<const SubStyleOne<FloatColorKey, FloatColor>*>(d->subStyles[FloatColorKey].data())->value1;
740 }
741 
formatType() const742 Format::Type Style::formatType() const
743 {
744     if (!d->subStyles.contains(FormatTypeKey))
745         return SubStyleOne<FormatTypeKey, Format::Type>().value1;
746     return static_cast<const SubStyleOne<FormatTypeKey, Format::Type>*>(d->subStyles[FormatTypeKey].data())->value1;
747 }
748 
currency() const749 Currency Style::currency() const
750 {
751     if (!d->subStyles.contains(CurrencyFormat))
752         return Currency();
753     return static_cast<const SubStyleOne<CurrencyFormat, Currency>*>(d->subStyles[CurrencyFormat].data())->value1;
754 }
755 
font() const756 QFont Style::font() const
757 {
758     QFont font;
759     font.setFamily(fontFamily());
760     font.setPointSize(fontSize());
761     font.setBold(bold());
762     font.setItalic(italic());
763     font.setUnderline(underline());
764     font.setStrikeOut(strikeOut());
765     return font;
766 }
767 
bold() const768 bool Style::bold() const
769 {
770     if (!d->subStyles.contains(FontBold))
771         return SubStyleOne<FontBold, bool>().value1;
772     return static_cast<const SubStyleOne<FontBold, bool>*>(d->subStyles[FontBold].data())->value1;
773 }
774 
italic() const775 bool Style::italic() const
776 {
777     if (!d->subStyles.contains(FontItalic))
778         return SubStyleOne<FontItalic, bool>().value1;
779     return static_cast<const SubStyleOne<FontItalic, bool>*>(d->subStyles[FontItalic].data())->value1;
780 }
781 
underline() const782 bool Style::underline() const
783 {
784     if (!d->subStyles.contains(FontUnderline))
785         return SubStyleOne<FontUnderline, bool>().value1;
786     return static_cast<const SubStyleOne<FontUnderline, bool>*>(d->subStyles[FontUnderline].data())->value1;
787 }
788 
strikeOut() const789 bool Style::strikeOut() const
790 {
791     if (!d->subStyles.contains(FontStrike))
792         return SubStyleOne<FontStrike, bool>().value1;
793     return static_cast<const SubStyleOne<FontStrike, bool>*>(d->subStyles[FontStrike].data())->value1;
794 }
795 
fontSize() const796 int Style::fontSize() const
797 {
798     if (!d->subStyles.contains(FontSize))
799         return KoGlobal::defaultFont().pointSize(); //SubStyleOne<FontSize, int>().value1;
800     return static_cast<const SubStyleOne<FontSize, int>*>(d->subStyles[FontSize].data())->value1;
801 }
802 
precision() const803 int Style::precision() const
804 {
805     if (!d->subStyles.contains(Precision))
806         return -1; //SubStyleOne<Precision, int>().value1;
807     return static_cast<const SubStyleOne<Precision, int>*>(d->subStyles[Precision].data())->value1;
808 }
809 
thousandsSep() const810 bool Style::thousandsSep() const
811 {
812     if (!d->subStyles.contains(ThousandsSep))
813         return false;
814     return static_cast<const SubStyleOne<ThousandsSep, bool>*>(d->subStyles[ThousandsSep].data())->value1;
815 }
816 
angle() const817 int Style::angle() const
818 {
819     if (!d->subStyles.contains(Angle))
820         return SubStyleOne<Angle, int>().value1;
821     return static_cast<const SubStyleOne<Angle, int>*>(d->subStyles[Angle].data())->value1;
822 }
823 
indentation() const824 double Style::indentation() const
825 {
826     if (!d->subStyles.contains(Indentation))
827         return SubStyleOne<Indentation, int>().value1;
828     return static_cast<const SubStyleOne<Indentation, int>*>(d->subStyles[Indentation].data())->value1;
829 }
830 
shrinkToFit() const831 bool Style::shrinkToFit() const
832 {
833     if (!d->subStyles.contains(ShrinkToFit))
834         return SubStyleOne<ShrinkToFit, bool>().value1;
835     return static_cast<const SubStyleOne<ShrinkToFit, bool>*>(d->subStyles[ShrinkToFit].data())->value1;
836 }
837 
verticalText() const838 bool Style::verticalText() const
839 {
840     if (!d->subStyles.contains(VerticalText))
841         return SubStyleOne<VerticalText, bool>().value1;
842     return static_cast<const SubStyleOne<VerticalText, bool>*>(d->subStyles[VerticalText].data())->value1;
843 }
844 
wrapText() const845 bool Style::wrapText() const
846 {
847     if (!d->subStyles.contains(MultiRow))
848         return SubStyleOne<MultiRow, bool>().value1;
849     return static_cast<const SubStyleOne<MultiRow, bool>*>(d->subStyles[MultiRow].data())->value1;
850 }
851 
printText() const852 bool Style::printText() const
853 {
854     if (!d->subStyles.contains(DontPrintText))
855         return !SubStyleOne<DontPrintText, bool>().value1;
856     return !static_cast<const SubStyleOne<DontPrintText, bool>*>(d->subStyles[DontPrintText].data())->value1;
857 }
858 
hideAll() const859 bool Style::hideAll() const
860 {
861     if (!d->subStyles.contains(HideAll))
862         return SubStyleOne<HideAll, bool>().value1;
863     return static_cast<const SubStyleOne<HideAll, bool>*>(d->subStyles[HideAll].data())->value1;
864 }
865 
hideFormula() const866 bool Style::hideFormula() const
867 {
868     if (!d->subStyles.contains(HideFormula))
869         return SubStyleOne<HideFormula, bool>().value1;
870     return static_cast<const SubStyleOne<HideFormula, bool>*>(d->subStyles[HideFormula].data())->value1;
871 }
872 
notProtected() const873 bool Style::notProtected() const
874 {
875     if (!d->subStyles.contains(NotProtected))
876         return SubStyleOne<NotProtected, bool>().value1;
877     return static_cast<const SubStyleOne<NotProtected, bool>*>(d->subStyles[NotProtected].data())->value1;
878 }
879 
isDefault() const880 bool Style::isDefault() const
881 {
882     return isEmpty() || d->subStyles.contains(DefaultStyleKey);
883 }
884 
isEmpty() const885 bool Style::isEmpty() const
886 {
887     return d->subStyles.isEmpty();
888 }
889 
setHAlign(HAlign align)890 void Style::setHAlign(HAlign align)
891 {
892     insertSubStyle(HorizontalAlignment, align);
893 }
894 
setVAlign(VAlign align)895 void Style::setVAlign(VAlign align)
896 {
897     insertSubStyle(VerticalAlignment, align);
898 }
899 
setFont(QFont const & font)900 void Style::setFont(QFont const & font)
901 {
902     insertSubStyle(FontFamily,     font.family());
903     insertSubStyle(FontSize,       font.pointSize());
904     insertSubStyle(FontBold,       font.bold());
905     insertSubStyle(FontItalic,     font.italic());
906     insertSubStyle(FontStrike,     font.strikeOut());
907     insertSubStyle(FontUnderline,  font.underline());
908 }
909 
setFontFamily(QString const & family)910 void Style::setFontFamily(QString const & family)
911 {
912     QString font = family;
913     // use the KDE default for sans serif, not Qt's default - this is because Qt doesn't return the default system font here
914     if (font.toLower() == "sans serif") {
915         QFont f = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
916         font = f.family();
917     }
918 
919     insertSubStyle(FontFamily, font);
920 }
921 
setFontBold(bool enabled)922 void Style::setFontBold(bool enabled)
923 {
924     insertSubStyle(FontBold, enabled);
925 }
926 
setFontItalic(bool enabled)927 void Style::setFontItalic(bool enabled)
928 {
929     insertSubStyle(FontItalic, enabled);
930 }
931 
setFontUnderline(bool enabled)932 void Style::setFontUnderline(bool enabled)
933 {
934     insertSubStyle(FontUnderline, enabled);
935 }
936 
setFontStrikeOut(bool enabled)937 void Style::setFontStrikeOut(bool enabled)
938 {
939     insertSubStyle(FontStrike, enabled);
940 }
941 
setFontSize(int size)942 void Style::setFontSize(int size)
943 {
944     insertSubStyle(FontSize, size);
945 }
946 
setFontColor(QColor const & color)947 void Style::setFontColor(QColor const & color)
948 {
949     insertSubStyle(FontColor, color);
950 }
951 
setBackgroundColor(QColor const & color)952 void Style::setBackgroundColor(QColor const & color)
953 {
954     insertSubStyle(BackgroundColor, color);
955 }
956 
setRightBorderPen(QPen const & pen)957 void Style::setRightBorderPen(QPen const & pen)
958 {
959     insertSubStyle(RightPen, pen);
960 }
961 
setBottomBorderPen(QPen const & pen)962 void Style::setBottomBorderPen(QPen const & pen)
963 {
964     insertSubStyle(BottomPen, pen);
965 }
966 
setLeftBorderPen(QPen const & pen)967 void Style::setLeftBorderPen(QPen const & pen)
968 {
969     insertSubStyle(LeftPen, pen);
970 }
971 
setTopBorderPen(QPen const & pen)972 void Style::setTopBorderPen(QPen const & pen)
973 {
974     insertSubStyle(TopPen, pen);
975 }
976 
setFallDiagonalPen(QPen const & pen)977 void Style::setFallDiagonalPen(QPen const & pen)
978 {
979     insertSubStyle(FallDiagonalPen, pen);
980 }
981 
setGoUpDiagonalPen(QPen const & pen)982 void Style::setGoUpDiagonalPen(QPen const & pen)
983 {
984     insertSubStyle(GoUpDiagonalPen, pen);
985 }
986 
setAngle(int angle)987 void Style::setAngle(int angle)
988 {
989     insertSubStyle(Angle, angle);
990 }
991 
setIndentation(double indent)992 void Style::setIndentation(double indent)
993 {
994     insertSubStyle(Indentation, indent);
995 }
996 
setBackgroundBrush(QBrush const & brush)997 void Style::setBackgroundBrush(QBrush const & brush)
998 {
999     insertSubStyle(BackgroundBrush, brush);
1000 }
1001 
setFloatFormat(FloatFormat format)1002 void Style::setFloatFormat(FloatFormat format)
1003 {
1004     insertSubStyle(FloatFormatKey, format);
1005 }
1006 
setFloatColor(FloatColor color)1007 void Style::setFloatColor(FloatColor color)
1008 {
1009     insertSubStyle(FloatColorKey, color);
1010 }
1011 
setFormatType(Format::Type format)1012 void Style::setFormatType(Format::Type format)
1013 {
1014     insertSubStyle(FormatTypeKey, format);
1015 }
1016 
setCustomFormat(QString const & strFormat)1017 void Style::setCustomFormat(QString const & strFormat)
1018 {
1019     insertSubStyle(CustomFormat, strFormat);
1020 }
1021 
setPrecision(int precision)1022 void Style::setPrecision(int precision)
1023 {
1024     insertSubStyle(Precision, precision);
1025 }
1026 
setThousandsSep(bool thousandsSep)1027 void Style::setThousandsSep(bool thousandsSep)
1028 {
1029     insertSubStyle(ThousandsSep, thousandsSep);
1030 }
1031 
setPrefix(QString const & prefix)1032 void Style::setPrefix(QString const & prefix)
1033 {
1034     insertSubStyle(Prefix, prefix);
1035 }
1036 
setPostfix(QString const & postfix)1037 void Style::setPostfix(QString const & postfix)
1038 {
1039     insertSubStyle(Postfix, postfix);
1040 }
1041 
setCurrency(Currency const & currency)1042 void Style::setCurrency(Currency const & currency)
1043 {
1044     QVariant variant;
1045     variant.setValue(currency);
1046     insertSubStyle(CurrencyFormat, variant);
1047 }
1048 
setWrapText(bool enable)1049 void Style::setWrapText(bool enable)
1050 {
1051     insertSubStyle(MultiRow, enable);
1052 }
1053 
setHideAll(bool enable)1054 void Style::setHideAll(bool enable)
1055 {
1056     insertSubStyle(HideAll, enable);
1057 }
1058 
setHideFormula(bool enable)1059 void Style::setHideFormula(bool enable)
1060 {
1061     insertSubStyle(HideFormula, enable);
1062 }
1063 
setNotProtected(bool enable)1064 void Style::setNotProtected(bool enable)
1065 {
1066     insertSubStyle(NotProtected, enable);
1067 }
1068 
setDontPrintText(bool enable)1069 void Style::setDontPrintText(bool enable)
1070 {
1071     insertSubStyle(DontPrintText, enable);
1072 }
1073 
setVerticalText(bool enable)1074 void Style::setVerticalText(bool enable)
1075 {
1076     insertSubStyle(VerticalText, enable);
1077 }
1078 
setShrinkToFit(bool enable)1079 void Style::setShrinkToFit(bool enable)
1080 {
1081     insertSubStyle(ShrinkToFit, enable);
1082 }
1083 
setDefault()1084 void Style::setDefault()
1085 {
1086     insertSubStyle(DefaultStyleKey, true);
1087 }
1088 
clear()1089 void Style::clear()
1090 {
1091     d->subStyles.clear();
1092 }
1093 
compare(const SubStyle * one,const SubStyle * two)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 
operator ==(const Style & other) const1191 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 
qHash(const Style & style)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 
operator =(const Style & other)1213 void Style::operator=(const Style & other)
1214 {
1215     d = other.d;
1216 }
1217 
operator -(const Style & other) const1218 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 
merge(const Style & style)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 
difference(const Style & other) const1238 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 
dump() const1254 void Style::dump() const
1255 {
1256     for (int i = 0; i < subStyles().count(); ++i)
1257         subStyles()[i]->dump();
1258 }
1259 
asCharFormat() const1260 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 
definedKeys(const StyleManager * styles) const1271 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 
subStyles() const1290 QList<SharedSubStyle> Style::subStyles() const
1291 {
1292     return d->subStyles.values();
1293 }
1294 
createSubStyle(Key key,const QVariant & value)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 
insertSubStyle(Key key,const QVariant & value)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 
insertSubStyle(const SharedSubStyle & subStyle)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 
releaseSubStyle(Key key)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 
CustomStyle()1464 CustomStyle::CustomStyle()
1465         : Style()
1466         , d(new Private)
1467 {
1468     d->name = "Default";
1469     d->type = BUILTIN;
1470     setDefault();
1471 }
1472 
CustomStyle(QString const & name,CustomStyle * parent)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 
CustomStyle(const CustomStyle & style)1483 CustomStyle::CustomStyle(const CustomStyle& style)
1484         : Style(style), d(style.d)
1485 {
1486 }
1487 
~CustomStyle()1488 CustomStyle::~CustomStyle()
1489 {
1490 }
1491 
operator =(const CustomStyle & style)1492 CustomStyle& CustomStyle::operator=(const CustomStyle& style)
1493 {
1494 	Style::operator=(style);
1495 	d = style.d;
1496 	return *this;
1497 }
1498 
type() const1499 Style::StyleType CustomStyle::type() const
1500 {
1501     return d->type;
1502 }
1503 
setType(StyleType type)1504 void CustomStyle::setType(StyleType type)
1505 {
1506     Q_ASSERT(type != AUTO);
1507     d->type = type;
1508 }
1509 
name() const1510 const QString& CustomStyle::name() const
1511 {
1512     return d->name;
1513 }
1514 
setName(QString const & name)1515 void CustomStyle::setName(QString const & name)
1516 {
1517     d->name = name;
1518 }
1519 
save(QDomDocument & doc,QDomElement & styles,const StyleManager * styleManager)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 
loadXML(KoXmlElement const & style,QString const & name)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 
usage() const1561 int CustomStyle::usage() const
1562 {
1563     return d->ref;
1564 }
1565 
definedKeys(const StyleManager *) const1566 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 
operator <<(QDebug dbg,const Calligra::Sheets::Style * s)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 
operator <<(QDebug dbg,const Calligra::Sheets::Style & s)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 }
1591