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