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 | |
29 | #include <kdebug.h> |
30 | #include <kglobal.h> |
31 | #include <klocale.h> |
32 | |
33 | #include <KoGenStyles.h> |
34 | #include <KoGlobal.h> |
35 | #include <KoOdfStylesReader.h> |
36 | #include <KoOdfGraphicStyles.h> |
37 | #include <KoStyleStack.h> |
38 | #include <KoUnit.h> |
39 | #include <KoXmlNS.h> |
40 | #include <KoXmlWriter.h> |
41 | #include <KoOdfWorkaround.h> |
42 | |
43 | #include "Condition.h" |
44 | #include "Currency.h" |
45 | #include "Global.h" |
46 | #include "StyleManager.h" |
47 | #include "Util.h" |
48 | |
49 | using namespace Calligra::Sheets; |
50 | |
51 | ///////////////////////////////////////////////////////////////////////////// |
52 | // |
53 | // SubStyles |
54 | // |
55 | ///////////////////////////////////////////////////////////////////////////// |
56 | |
57 | namespace Calligra |
58 | { |
59 | namespace Sheets |
60 | { |
61 | |
62 | static uint calculateValue(QPen const & pen) |
63 | { |
64 | uint n = pen.color().red() + pen.color().green() + pen.color().blue(); |
65 | n += 1000 * pen.width(); |
66 | n += 10000 * (uint) pen.style(); |
67 | return n; |
68 | } |
69 | |
70 | // specialized debug method |
71 | template<> |
72 | QString SubStyleOne<Style::CurrencyFormat, Currency>::debugData(bool withName) const |
73 | { |
74 | QString out; if (withName) out = name(Style::CurrencyFormat) + ' '; QDebug qdbg(&out); qdbg << value1.symbol(); return out; |
75 | } |
76 | |
77 | template<Style::Key key> |
78 | class PenStyle : public SubStyleOne<key, QPen> |
79 | { |
80 | public: |
81 | PenStyle(const QPen& p = Qt::NoPen) : SubStyleOne<key, QPen>(p) {} |
82 | }; |
83 | |
84 | template<Style::Key key> |
85 | class BorderPenStyle : public PenStyle<key> |
86 | { |
87 | public: |
88 | BorderPenStyle(const QPen& p = Qt::NoPen) : PenStyle<key>(p), value(calculateValue(p)) {} |
89 | int value; |
90 | }; |
91 | |
92 | QString SubStyle::name(Style::Key key) |
93 | { |
94 | QString name; |
95 | switch (key) { |
96 | case Style::DefaultStyleKey: name = "Default style" ; break; |
97 | case Style::NamedStyleKey: name = "Named style" ; break; |
98 | case Style::LeftPen: name = "Left pen" ; break; |
99 | case Style::RightPen: name = "Right pen" ; break; |
100 | case Style::TopPen: name = "Top pen" ; break; |
101 | case Style::BottomPen: name = "Bottom pen" ; break; |
102 | case Style::FallDiagonalPen: name = "Fall diagonal pen" ; break; |
103 | case Style::GoUpDiagonalPen: name = "Go up diagonal pen" ; break; |
104 | case Style::HorizontalAlignment: name = "Horz. alignment" ; break; |
105 | case Style::VerticalAlignment: name = "Vert. alignment" ; break; |
106 | case Style::MultiRow: name = "Wrap text" ; break; |
107 | case Style::VerticalText: name = "Vertical text" ; break; |
108 | case Style::Angle: name = "Angle" ; break; |
109 | case Style::Indentation: name = "Indentation" ; break; |
110 | case Style::ShrinkToFit: name = "Shrink to Fit" ; break; |
111 | case Style::Prefix: name = "Prefix" ; break; |
112 | case Style::Postfix: name = "Postfix" ; break; |
113 | case Style::Precision: name = "Precision" ; break; |
114 | case Style::ThousandsSep: name = "Thousands separator" ; break; |
115 | case Style::FormatTypeKey: name = "Format type" ; break; |
116 | case Style::FloatFormatKey: name = "Float format" ; break; |
117 | case Style::FloatColorKey: name = "Float color" ; break; |
118 | case Style::CurrencyFormat: name = "Currency" ; break; |
119 | case Style::CustomFormat: name = "Custom format" ; break; |
120 | case Style::BackgroundBrush: name = "Background brush" ; break; |
121 | case Style::BackgroundColor: name = "Background color" ; break; |
122 | case Style::FontColor: name = "Font color" ; break; |
123 | case Style::FontFamily: name = "Font family" ; break; |
124 | case Style::FontSize: name = "Font size" ; break; |
125 | case Style::FontBold: name = "Font bold" ; break; |
126 | case Style::FontItalic: name = "Font italic" ; break; |
127 | case Style::FontStrike: name = "Font strikeout" ; break; |
128 | case Style::FontUnderline: name = "Font underline" ; break; |
129 | case Style::DontPrintText: name = "Do not print text" ; break; |
130 | case Style::NotProtected: name = "Not protected" ; break; |
131 | case Style::HideAll: name = "Hide all" ; break; |
132 | case Style::HideFormula: name = "Hide formula" ; break; |
133 | } |
134 | return name; |
135 | } |
136 | |
137 | SharedSubStyle SharedSubStyle::s_defaultStyle(new SubStyle()); |
138 | |
139 | } // namespace Sheets |
140 | } // namespace Calligra |
141 | |
142 | ///////////////////////////////////////////////////////////////////////////// |
143 | // |
144 | // Style::Private |
145 | // |
146 | ///////////////////////////////////////////////////////////////////////////// |
147 | |
148 | class Style::Private : public QSharedData |
149 | { |
150 | public: |
151 | QHash<Key, SharedSubStyle> subStyles; |
152 | }; |
153 | |
154 | |
155 | ///////////////////////////////////////////////////////////////////////////// |
156 | // |
157 | // Style |
158 | // |
159 | ///////////////////////////////////////////////////////////////////////////// |
160 | |
161 | Style::Style() |
162 | : d(new Private) |
163 | { |
164 | } |
165 | |
166 | Style::Style(const Style& style) |
167 | : d(style.d) |
168 | { |
169 | } |
170 | |
171 | Style::~Style() |
172 | { |
173 | } |
174 | |
175 | Style::StyleType Style::type() const |
176 | { |
177 | return AUTO; |
178 | } |
179 | |
180 | QString Style::parentName() const |
181 | { |
182 | if (!d->subStyles.contains(NamedStyleKey)) |
183 | return QString(); |
184 | return static_cast<const NamedStyle*>(d->subStyles[NamedStyleKey].data())->name; |
185 | } |
186 | |
187 | void Style::setParentName(const QString& name) |
188 | { |
189 | d->subStyles.insert(NamedStyleKey, SharedSubStyle(new NamedStyle(name))); |
190 | } |
191 | |
192 | void Style::clearAttribute(Key key) |
193 | { |
194 | d->subStyles.remove(key); |
195 | } |
196 | |
197 | bool Style::hasAttribute(Key key) const |
198 | { |
199 | return d->subStyles.contains(key); |
200 | } |
201 | |
202 | void Style::loadAttributes(const QList<SharedSubStyle>& subStyles) |
203 | { |
204 | d->subStyles.clear(); |
205 | for (int i = 0; i < subStyles.count(); ++i) { |
206 | // already existing items are replaced |
207 | d->subStyles.insert(subStyles[i]->type(), subStyles[i]); |
208 | } |
209 | } |
210 | |
211 | void Style::loadOdfStyle(KoOdfStylesReader& stylesReader, const KoXmlElement& element, |
212 | Conditions& conditions, const StyleManager* styleManager, |
213 | const ValueParser *parser) |
214 | { |
215 | // NOTE Stefan: Do not fill the style stack with the parent styles! |
216 | KoStyleStack styleStack; |
217 | styleStack.push(element); |
218 | |
219 | styleStack.setTypeProperties("table-cell" ); |
220 | loadOdfTableCellProperties(stylesReader, styleStack); |
221 | |
222 | styleStack.setTypeProperties("text" ); |
223 | loadOdfTextProperties(stylesReader, styleStack); |
224 | |
225 | styleStack.setTypeProperties("paragraph" ); |
226 | loadOdfParagraphProperties(stylesReader, styleStack); |
227 | |
228 | KoXmlElement e; |
229 | forEachElement(e, element) { |
230 | if (e.namespaceURI() == KoXmlNS::style && e.localName() == "map" ) |
231 | conditions.loadOdfConditions(e, parser, styleManager); |
232 | } |
233 | |
234 | loadOdfDataStyle(stylesReader, element, conditions, styleManager, parser); |
235 | } |
236 | |
237 | typedef QPair<QString,QString> StringPair; |
238 | |
239 | void Style::loadOdfDataStyle(KoOdfStylesReader& stylesReader, const KoXmlElement& element, |
240 | Conditions& conditions, const StyleManager* styleManager, |
241 | const ValueParser *parser) |
242 | { |
243 | QString str; |
244 | if (element.hasAttributeNS(KoXmlNS::style, "data-style-name" )) { |
245 | const QString styleName = element.attributeNS(KoXmlNS::style, "data-style-name" , QString()); |
246 | loadOdfDataStyle(stylesReader, styleName, conditions, styleManager, parser); |
247 | } |
248 | } |
249 | |
250 | void Style::loadOdfDataStyle(KoOdfStylesReader &stylesReader, const QString &styleName, Conditions &conditions, const StyleManager *styleManager, const ValueParser *parser) |
251 | { |
252 | if (stylesReader.dataFormats().contains(styleName)) { |
253 | Style* theStyle = this; |
254 | |
255 | QPair<KoOdfNumberStyles::NumericStyleFormat, KoXmlElement*> dataStylePair = stylesReader.dataFormats()[styleName]; |
256 | |
257 | const KoOdfNumberStyles::NumericStyleFormat& dataStyle = dataStylePair.first; |
258 | const QList<QPair<QString,QString> > styleMaps = dataStyle.styleMaps; |
259 | if(styleMaps.count() > 0) { |
260 | theStyle = new Style(); |
261 | for (QList<QPair<QString,QString> >::const_iterator it = styleMaps.begin(); it != styleMaps.end(); ++it) { |
262 | const Conditional c = conditions.loadOdfCondition(it->first, it->second, QString(), parser); |
263 | if (styleManager->style(c.styleName) == 0) { |
264 | CustomStyle* const s = new CustomStyle(c.styleName); |
265 | s->loadOdfDataStyle(stylesReader, c.styleName, conditions, styleManager, parser); |
266 | const_cast<StyleManager*>(styleManager)->insertStyle(s); |
267 | } |
268 | } |
269 | } |
270 | |
271 | KoStyleStack styleStack; |
272 | styleStack.push(*dataStylePair.second); |
273 | styleStack.setTypeProperties("text" ); |
274 | theStyle->loadOdfTextProperties(stylesReader, styleStack); |
275 | |
276 | QString tmp = dataStyle.prefix; |
277 | if (!tmp.isEmpty()) { |
278 | theStyle->setPrefix(tmp); |
279 | } |
280 | tmp = dataStyle.suffix; |
281 | if (!tmp.isEmpty()) { |
282 | theStyle->setPostfix(tmp); |
283 | } |
284 | // determine data formatting |
285 | switch (dataStyle.type) { |
286 | case KoOdfNumberStyles::Number: |
287 | theStyle->setFormatType(Format::Number); |
288 | if (!dataStyle.currencySymbol.isEmpty()) |
289 | theStyle->setCurrency(numberCurrency(dataStyle.currencySymbol)); |
290 | else |
291 | theStyle->setCurrency(numberCurrency(dataStyle.formatStr)); |
292 | break; |
293 | case KoOdfNumberStyles::Scientific: |
294 | theStyle->setFormatType(Format::Scientific); |
295 | break; |
296 | case KoOdfNumberStyles::Currency: |
297 | kDebug(36003) << " currency-symbol:" << dataStyle.currencySymbol; |
298 | if (!dataStyle.currencySymbol.isEmpty()) |
299 | theStyle->setCurrency(numberCurrency(dataStyle.currencySymbol)); |
300 | else |
301 | theStyle->setCurrency(numberCurrency(dataStyle.formatStr)); |
302 | break; |
303 | case KoOdfNumberStyles::Percentage: |
304 | theStyle->setFormatType(Format::Percentage); |
305 | break; |
306 | case KoOdfNumberStyles::Fraction: |
307 | // determine format of fractions, dates and times by using the |
308 | // formatting string |
309 | tmp = dataStyle.formatStr; |
310 | if (!tmp.isEmpty()) { |
311 | theStyle->setFormatType(Style::fractionType(tmp)); |
312 | } |
313 | break; |
314 | case KoOdfNumberStyles::Date: |
315 | // determine format of fractions, dates and times by using the |
316 | // formatting string |
317 | tmp = dataStyle.formatStr; |
318 | if (!tmp.isEmpty()) { |
319 | theStyle->setFormatType(Style::dateType(tmp)); |
320 | } |
321 | break; |
322 | case KoOdfNumberStyles::Time: |
323 | // determine format of fractions, dates and times by using the |
324 | // formatting string |
325 | tmp = dataStyle.formatStr; |
326 | if (!tmp.isEmpty()) { |
327 | theStyle->setFormatType(Style::timeType(tmp)); |
328 | } |
329 | break; |
330 | case KoOdfNumberStyles::Boolean: |
331 | theStyle->setFormatType(Format::Number); |
332 | break; |
333 | case KoOdfNumberStyles::Text: |
334 | theStyle->setFormatType(Format::Text); |
335 | break; |
336 | } |
337 | |
338 | if (dataStyle.precision > -1) { |
339 | // special handling for precision |
340 | // The Style default (-1) and the storage default (0) differ. |
341 | // The maximum is 10. Replace the Style value 0 with -11, which always results |
342 | // in a storage value < 0 and is interpreted as Style value 0. |
343 | int precision = dataStyle.precision; |
344 | if (type() == AUTO && precision == 0) |
345 | precision = -11; |
346 | theStyle->setPrecision(precision); |
347 | } |
348 | |
349 | theStyle->setThousandsSep(dataStyle.thousandsSep); |
350 | |
351 | theStyle->setCustomFormat(dataStyle.formatStr); |
352 | |
353 | if(styleMaps.count() > 0) { |
354 | conditions.setDefaultStyle(*theStyle); |
355 | delete theStyle; |
356 | } |
357 | } |
358 | } |
359 | |
360 | void Style::loadOdfParagraphProperties(KoOdfStylesReader& stylesReader, const KoStyleStack& styleStack) |
361 | { |
362 | Q_UNUSED(stylesReader); |
363 | kDebug(36003) << "\t paragraph-properties" ; |
364 | if (styleStack.hasProperty(KoXmlNS::fo, "text-align" )) { |
365 | QString str = styleStack.property(KoXmlNS::fo, "text-align" ); |
366 | if (str == "center" ) |
367 | setHAlign(Style::Center); |
368 | else if (str == "end" || str=="right" ) |
369 | setHAlign(Style::Right); |
370 | else if (str == "start" || str=="left" ) |
371 | setHAlign(Style::Left); |
372 | else if (str == "justify" ) |
373 | setHAlign(Style::Justified); |
374 | else |
375 | setHAlign(Style::HAlignUndefined); |
376 | kDebug(36003) << "\t\t text-align:" << str; |
377 | } |
378 | |
379 | if (styleStack.hasProperty(KoXmlNS::fo, "margin-left" )) { |
380 | //todo fix me |
381 | setIndentation(KoUnit::parseValue(styleStack.property(KoXmlNS::fo, "margin-left" ), 0.0)); |
382 | } |
383 | } |
384 | |
385 | void Style::loadOdfTableCellProperties(KoOdfStylesReader& stylesReader, const KoStyleStack& styleStack) |
386 | { |
387 | QString str; |
388 | if (styleStack.hasProperty(KoXmlNS::style, "vertical-align" )) { |
389 | str = styleStack.property(KoXmlNS::style, "vertical-align" ); |
390 | if (str == "bottom" ) |
391 | setVAlign(Style::Bottom); |
392 | else if (str == "top" ) |
393 | setVAlign(Style::Top); |
394 | else if (str == "middle" ) |
395 | setVAlign(Style::Middle); |
396 | else |
397 | setVAlign(Style::VAlignUndefined); |
398 | } |
399 | if (styleStack.property(KoXmlNS::calligra, "vertical-distributed" ) == "distributed" ) { |
400 | if (valign() == Style::Top) |
401 | setVAlign(Style::VJustified); |
402 | else |
403 | setVAlign(Style::VDistributed); |
404 | } |
405 | if (styleStack.hasProperty(KoXmlNS::fo, "background-color" )) { |
406 | str = styleStack.property(KoXmlNS::fo, "background-color" ); |
407 | if (str == "transparent" ) { |
408 | kDebug(36003) << "\t\t fo:background-color: transparent" ; |
409 | setBackgroundColor(QColor()); |
410 | } else { |
411 | QColor color(str); |
412 | if (color.isValid()) { |
413 | kDebug(36003) << "\t\t fo:background-color:" << color.name(); |
414 | setBackgroundColor(color); |
415 | } |
416 | } |
417 | } |
418 | |
419 | if (styleStack.hasProperty(KoXmlNS::fo, "wrap-option" ) && (styleStack.property(KoXmlNS::fo, "wrap-option" ) == "wrap" )) { |
420 | setWrapText(true); |
421 | } |
422 | if (styleStack.hasProperty(KoXmlNS::style, "cell-protect" )) { |
423 | str = styleStack.property(KoXmlNS::style, "cell-protect" ); |
424 | #ifndef NWORKAROUND_ODF_BUGS |
425 | KoOdfWorkaround::fixBadFormulaHiddenForStyleCellProtect(str); |
426 | #endif |
427 | if (str == "none" ) |
428 | setNotProtected(true); |
429 | else if (str == "hidden-and-protected" ) |
430 | setHideAll(true); |
431 | else if (str == "protected formula-hidden" || str == "formula-hidden protected" ) |
432 | setHideFormula(true); |
433 | else if (str == "formula-hidden" ) { |
434 | setNotProtected(true); |
435 | setHideFormula(true); |
436 | } |
437 | } |
438 | if (styleStack.hasProperty(KoXmlNS::style, "print-content" ) && |
439 | (styleStack.property(KoXmlNS::style, "print-content" ) == "false" )) { |
440 | setDontPrintText(true); |
441 | } |
442 | if (styleStack.hasProperty(KoXmlNS::style, "shrink-to-fit" ) && |
443 | (styleStack.property(KoXmlNS::style, "shrink-to-fit" ) == "true" )) { |
444 | setShrinkToFit(true); |
445 | } |
446 | if (styleStack.hasProperty(KoXmlNS::style, "direction" ) && |
447 | (styleStack.property(KoXmlNS::style, "direction" ) == "ttb" )) { |
448 | setVerticalText(true); |
449 | } |
450 | if (styleStack.hasProperty(KoXmlNS::style, "rotation-angle" )) { |
451 | bool ok; |
452 | int a = styleStack.property(KoXmlNS::style, "rotation-angle" ).toInt(&ok); |
453 | kDebug(36003) << " rotation-angle :" << a; |
454 | if (a != 0) { |
455 | setAngle(-a); |
456 | } |
457 | } |
458 | if (styleStack.hasProperty(KoXmlNS::fo, "border" )) { |
459 | str = styleStack.property(KoXmlNS::fo, "border" ); |
460 | QPen pen = Odf::decodePen(str); |
461 | setLeftBorderPen(pen); |
462 | setTopBorderPen(pen); |
463 | setBottomBorderPen(pen); |
464 | setRightBorderPen(pen); |
465 | } |
466 | if (styleStack.hasProperty(KoXmlNS::fo, "border-left" )) { |
467 | str = styleStack.property(KoXmlNS::fo, "border-left" ); |
468 | setLeftBorderPen(Odf::decodePen(str)); |
469 | } |
470 | if (styleStack.hasProperty(KoXmlNS::fo, "border-right" )) { |
471 | str = styleStack.property(KoXmlNS::fo, "border-right" ); |
472 | setRightBorderPen(Odf::decodePen(str)); |
473 | } |
474 | if (styleStack.hasProperty(KoXmlNS::fo, "border-top" )) { |
475 | str = styleStack.property(KoXmlNS::fo, "border-top" ); |
476 | setTopBorderPen(Odf::decodePen(str)); |
477 | } |
478 | if (styleStack.hasProperty(KoXmlNS::fo, "border-bottom" )) { |
479 | str = styleStack.property(KoXmlNS::fo, "border-bottom" ); |
480 | setBottomBorderPen(Odf::decodePen(str)); |
481 | } |
482 | if (styleStack.hasProperty(KoXmlNS::style, "diagonal-tl-br" )) { |
483 | str = styleStack.property(KoXmlNS::style, "diagonal-tl-br" ); |
484 | setFallDiagonalPen(Odf::decodePen(str)); |
485 | } |
486 | if (styleStack.hasProperty(KoXmlNS::style, "diagonal-bl-tr" )) { |
487 | str = styleStack.property(KoXmlNS::style, "diagonal-bl-tr" ); |
488 | setGoUpDiagonalPen(Odf::decodePen(str)); |
489 | } |
490 | |
491 | if (styleStack.hasProperty(KoXmlNS::draw, "style-name" ) || styleStack.hasProperty(KoXmlNS::calligra, "fill-style-name" )) { |
492 | QString styleName = styleStack.hasProperty(KoXmlNS::calligra, "fill-style-name" ) ? styleStack.property(KoXmlNS::calligra, "fill-style-name" ) |
493 | : styleStack.property(KoXmlNS::draw, "style-name" ); |
494 | kDebug(36003) << " style name :" << styleName; |
495 | |
496 | const KoXmlElement * style = stylesReader.findStyle(styleName, "graphic" ); |
497 | kDebug(36003) << " style :" << style; |
498 | if (style) { |
499 | KoStyleStack drawStyleStack; |
500 | drawStyleStack.push(*style); |
501 | drawStyleStack.setTypeProperties("graphic" ); |
502 | if (drawStyleStack.hasProperty(KoXmlNS::draw, "fill" )) { |
503 | const QString fill = drawStyleStack.property(KoXmlNS::draw, "fill" ); |
504 | kDebug(36003) << " load object gradient fill type :" << fill; |
505 | |
506 | if (fill == "solid" || fill == "hatch" ) { |
507 | kDebug(36003) << " Style ******************************************************" ; |
508 | setBackgroundBrush(KoOdfGraphicStyles::loadOdfFillStyle(drawStyleStack, fill, stylesReader)); |
509 | |
510 | } else |
511 | kDebug(36003) << " fill style not supported into kspread :" << fill; |
512 | } |
513 | } |
514 | } |
515 | } |
516 | |
517 | void Style::loadOdfTextProperties(KoOdfStylesReader& stylesReader, const KoStyleStack& styleStack) |
518 | { |
519 | Q_UNUSED(stylesReader); |
520 | // fo:font-size="13pt" |
521 | // fo:font-style="italic" |
522 | // style:text-underline="double" |
523 | // style:text-underline-color="font-color" |
524 | // fo:font-weight="bold" |
525 | kDebug(36003) << "\t text-properties" ; |
526 | if (styleStack.hasProperty(KoXmlNS::fo, "font-family" )) { |
527 | setFontFamily(styleStack.property(KoXmlNS::fo, "font-family" )); // FIXME Stefan: sanity check |
528 | kDebug(36003) << "\t\t fo:font-family:" << fontFamily(); |
529 | } |
530 | if (styleStack.hasProperty(KoXmlNS::fo, "font-size" )) { |
531 | setFontSize((int) KoUnit::parseValue(styleStack.property(KoXmlNS::fo, "font-size" ), 10.0)); // FIXME Stefan: fallback to default |
532 | kDebug(36003) << "\t\t fo:font-size:" << fontSize(); |
533 | } |
534 | if (styleStack.hasProperty(KoXmlNS::fo, "font-style" )) { |
535 | if (styleStack.property(KoXmlNS::fo, "font-style" ) == "italic" ) { // "normal", "oblique" |
536 | setFontItalic(true); |
537 | kDebug(36003) << "\t\t fo:font-style:" << "italic" ; |
538 | } |
539 | } |
540 | if (styleStack.hasProperty(KoXmlNS::fo, "font-weight" )) { |
541 | if (styleStack.property(KoXmlNS::fo, "font-weight" ) == "bold" ) { // "normal", "100", "200", ... |
542 | setFontBold(true); |
543 | kDebug(36003) << "\t\t fo:font-weight:" << "bold" ; |
544 | } |
545 | } |
546 | if (styleStack.hasProperty(KoXmlNS::style, "text-underline-style" )) { |
547 | if (styleStack.property(KoXmlNS::style, "text-underline-style" ) != "none" ) { |
548 | setFontUnderline(true); |
549 | kDebug(36003) << "\t\t style:text-underline-style:" << "solid (actually: !none)" ; |
550 | } |
551 | } |
552 | if (styleStack.hasProperty(KoXmlNS::style, "text-underline-width" )) { |
553 | //TODO |
554 | } |
555 | if (styleStack.hasProperty(KoXmlNS::style, "text-underline-color" )) { |
556 | //TODO |
557 | } |
558 | if (styleStack.hasProperty(KoXmlNS::fo, "color" )) { |
559 | QColor color = QColor(styleStack.property(KoXmlNS::fo, "color" )); |
560 | if (color.isValid()) { |
561 | setFontColor(color); |
562 | kDebug(36003) << "\t\t fo:color:" << color.name(); |
563 | } |
564 | } |
565 | if (styleStack.hasProperty(KoXmlNS::style, "text-line-through-style" )) { |
566 | if (styleStack.property(KoXmlNS::style, "text-line-through-style" ) != "none" |
567 | /*&& styleStack.property("text-line-through-style")=="solid"*/) { |
568 | setFontStrikeOut(true); |
569 | kDebug(36003) << "\t\t text-line-through-style:" << "solid (actually: !none)" ; |
570 | } |
571 | } |
572 | if (styleStack.hasProperty(KoXmlNS::style, "font-name" )) { |
573 | QString fontName = styleStack.property(KoXmlNS::style, "font-name" ); |
574 | kDebug(36003) << "\t\t style:font-name:" << fontName; |
575 | const KoXmlElement * style = stylesReader.findStyle(fontName); |
576 | // TODO: sanity check that it is a font-face style? |
577 | kDebug(36003) << "\t\t\t style:" << style; |
578 | if (style) { |
579 | setFontFamily(style->attributeNS(KoXmlNS::svg, "font-family" )); |
580 | kDebug(36003) << "\t\t\t svg:font-family:" << fontFamily(); |
581 | } |
582 | } |
583 | } |
584 | |
585 | static QString convertDateFormat(const QString& date) |
586 | { |
587 | QString result = date; |
588 | result.replace("%Y" , "yyyy" ); |
589 | result.replace("%y" , "yy" ); |
590 | result.replace("%n" , "M" ); |
591 | result.replace("%m" , "MM" ); |
592 | result.replace("%e" , "d" ); |
593 | result.replace("%d" , "dd" ); |
594 | result.replace("%b" , "MMM" ); |
595 | result.replace("%B" , "MMMM" ); |
596 | result.replace("%a" , "ddd" ); |
597 | result.replace("%A" , "dddd" ); |
598 | return result; |
599 | } |
600 | |
601 | Format::Type Style::dateType(const QString &_f) |
602 | { |
603 | const QString dateFormatShort = convertDateFormat(KGlobal::locale()->dateFormatShort()); |
604 | const QString dateFormat = convertDateFormat(KGlobal::locale()->dateFormat()); |
605 | QString _format = _f; |
606 | _format.replace(' ', '-'); |
607 | |
608 | if (_format == "d-MMM-yy" || _format == "dd-MMM-yy" ) |
609 | return Format::Date1; |
610 | else if (_format == "dd-MMM-yyyy" ) |
611 | return Format::Date2; |
612 | else if (_format == "d-MM" ) |
613 | return Format::Date3; |
614 | else if (_format == "dd-MM" ) //TODO ??????? |
615 | return Format::Date4; |
616 | else if (_format == "dd/MM/yy" ) |
617 | return Format::Date5; |
618 | else if (_format == "dd/MM/yyyy" ) |
619 | return Format::Date6; |
620 | else if (_format == "MMM-yy" ) |
621 | return Format::Date7; |
622 | else if (_format == "MMMM-yy" ) |
623 | return Format::Date8; |
624 | else if (_format == "MMMM-yyyy" ) |
625 | return Format::Date9; |
626 | else if (_format == "MMMMM-yy" || _format == "X-yy" ) |
627 | return Format::Date10; |
628 | else if (_format == "dd/MMM" ) |
629 | return Format::Date11; |
630 | else if (_format == "dd/MM" ) |
631 | return Format::Date12; |
632 | else if (_format == "dd/MMM/yyyy" ) |
633 | return Format::Date13; |
634 | else if (_format == "yyyy/MMM/dd" ) |
635 | return Format::Date14; |
636 | else if (_format == "yyyy-MMM-dd" ) |
637 | return Format::Date15; |
638 | else if (_format == "yyyy-MM-dd" ) |
639 | return Format::Date16; |
640 | else if (_format == "d MMMM yyyy" ) |
641 | return Format::Date17; |
642 | else if (_format == "MM/dd/yyyy" ) |
643 | return Format::Date18; |
644 | else if (_format == "MM/dd/yy" ) |
645 | return Format::Date19; |
646 | else if (_format == "MMM/dd/yy" ) |
647 | return Format::Date20; |
648 | else if (_format == "MMM/dd/yyyy" ) |
649 | return Format::Date21; |
650 | else if (_format == "MMM-yyyy" ) |
651 | return Format::Date22; |
652 | else if (_format == "yyyy" ) |
653 | return Format::Date23; |
654 | else if (_format == "yy" ) |
655 | return Format::Date24; |
656 | else if (_format == "yyyy/MM/dd" ) |
657 | return Format::Date25; |
658 | else if (_format == "yyyy/MMM/dd" ) |
659 | return Format::Date26; |
660 | else if (_format == "MMM/yy" ) |
661 | return Format::Date27; |
662 | else if (_format == "MMM/yyyy" ) |
663 | return Format::Date28; |
664 | else if (_format == "MMMM/yy" ) |
665 | return Format::Date29; |
666 | else if (_format == "MMMM/yyyy" ) |
667 | return Format::Date30; |
668 | else if (_format == "dd-MM" ) |
669 | return Format::Date31; |
670 | else if (_format == "MM/yy" ) |
671 | return Format::Date32; |
672 | else if (_format == "MM-yy" ) |
673 | return Format::Date33; |
674 | else if (QRegExp("^[d]+[\\s]*[d]{1,2}[\\s]+[M]{1,4}[\\s]+[y]{2,2}$" ).indexIn(_f) >= 0) |
675 | return Format::Date34; |
676 | else if (QRegExp("^[d]+[\\s]*[d]{1,2}[\\s]+[M]{1,}[\\s]+[y]{2,4}$" ).indexIn(_f) >= 0) |
677 | return Format::Date35; |
678 | else if (_format == dateFormatShort) |
679 | return Format::ShortDate; |
680 | else if (_format == dateFormat) |
681 | return Format::TextDate; |
682 | else { |
683 | kDebug() << "Unhandled date format=" << _format; |
684 | return Format::ShortDate; |
685 | } |
686 | } |
687 | |
688 | Format::Type Style::timeType(const QString &_format) |
689 | { |
690 | if (_format == "h:mm AP" ) |
691 | return Format::Time1; |
692 | else if (_format == "h:mm:ss AP" ) |
693 | return Format::Time2; |
694 | else if (_format == "hh \\h mm \\m\\i\\n ss \\s" ) |
695 | return Format::Time3; |
696 | else if (_format == "hh:mm" ) |
697 | return Format::Time4; |
698 | else if (_format == "hh:mm:ss" ) |
699 | return Format::Time5; |
700 | else if (_format == "m:ss" ) |
701 | return Format::Time6; |
702 | else if (_format == "h:mm:ss" ) |
703 | return Format::Time7; |
704 | else if (_format == "h:mm" ) |
705 | return Format::Time8; |
706 | else |
707 | return Format::Time; |
708 | } |
709 | |
710 | Currency Style::numberCurrency(const QString &_format) |
711 | { |
712 | // Look up if a prefix or postfix is in the currency table, |
713 | // return the currency symbol to use for formatting purposes. |
714 | if(!_format.isEmpty()) { |
715 | QString f = QString(_format.at(0)); |
716 | Currency currStart = Currency(f); |
717 | if (currStart.index() > 1) |
718 | return currStart; |
719 | f = QString(_format.at(_format.size()-1)); |
720 | Currency currEnd = Currency(f); |
721 | if (currEnd.index() > 1) |
722 | return currEnd; |
723 | } |
724 | return Currency(QString()); |
725 | } |
726 | |
727 | Format::Type Style::fractionType(const QString &_format) |
728 | { |
729 | if (_format.endsWith(QLatin1String("/2" ))) |
730 | return Format::fraction_half; |
731 | else if (_format.endsWith(QLatin1String("/4" ))) |
732 | return Format::fraction_quarter; |
733 | else if (_format.endsWith(QLatin1String("/8" ))) |
734 | return Format::fraction_eighth; |
735 | else if (_format.endsWith(QLatin1String("/16" ))) |
736 | return Format::fraction_sixteenth; |
737 | else if (_format.endsWith(QLatin1String("/10" ))) |
738 | return Format::fraction_tenth; |
739 | else if (_format.endsWith(QLatin1String("/100" ))) |
740 | return Format::fraction_hundredth; |
741 | else if (_format.endsWith(QLatin1String("/?" ))) |
742 | return Format::fraction_one_digit; |
743 | else if (_format.endsWith(QLatin1String("/??" ))) |
744 | return Format::fraction_two_digits; |
745 | else if (_format.endsWith(QLatin1String("/???" ))) |
746 | return Format::fraction_three_digits; |
747 | else |
748 | return Format::fraction_three_digits; |
749 | } |
750 | |
751 | QString Style::saveOdfStyleNumeric(KoGenStyle &style, KoGenStyles &mainStyles, |
752 | Format::Type _style, |
753 | const QString &_prefix, const QString &_postfix, |
754 | int _precision, const QString& symbol, |
755 | bool thousandsSep) |
756 | { |
757 | // kDebug(36003) ; |
758 | QString styleName; |
759 | QString valueType; |
760 | switch (_style) { |
761 | case Format::Number: |
762 | styleName = saveOdfStyleNumericNumber(mainStyles, _style, _precision, _prefix, _postfix, thousandsSep); |
763 | valueType = "float" ; |
764 | break; |
765 | case Format::Text: |
766 | styleName = saveOdfStyleNumericText(mainStyles, _style, _precision, _prefix, _postfix); |
767 | valueType = "string" ; |
768 | break; |
769 | case Format::Money: |
770 | styleName = saveOdfStyleNumericMoney(mainStyles, _style, symbol, _precision, _prefix, _postfix); |
771 | valueType = "currency" ; |
772 | break; |
773 | case Format::Percentage: |
774 | styleName = saveOdfStyleNumericPercentage(mainStyles, _style, _precision, _prefix, _postfix); |
775 | valueType = "percentage" ; |
776 | break; |
777 | case Format::Scientific: |
778 | styleName = saveOdfStyleNumericScientific(mainStyles, _style, _prefix, _postfix, _precision, thousandsSep); |
779 | valueType = "float" ; |
780 | break; |
781 | case Format::ShortDate: |
782 | case Format::TextDate: |
783 | styleName = saveOdfStyleNumericDate(mainStyles, _style, _prefix, _postfix); |
784 | valueType = "date" ; |
785 | break; |
786 | case Format::Time: |
787 | case Format::SecondeTime: |
788 | case Format::Time1: |
789 | case Format::Time2: |
790 | case Format::Time3: |
791 | case Format::Time4: |
792 | case Format::Time5: |
793 | case Format::Time6: |
794 | case Format::Time7: |
795 | case Format::Time8: |
796 | styleName = saveOdfStyleNumericTime(mainStyles, _style, _prefix, _postfix); |
797 | valueType = "time" ; |
798 | break; |
799 | case Format::fraction_half: |
800 | case Format::fraction_quarter: |
801 | case Format::fraction_eighth: |
802 | case Format::fraction_sixteenth: |
803 | case Format::fraction_tenth: |
804 | case Format::fraction_hundredth: |
805 | case Format::fraction_one_digit: |
806 | case Format::fraction_two_digits: |
807 | case Format::fraction_three_digits: |
808 | styleName = saveOdfStyleNumericFraction(mainStyles, _style, _prefix, _postfix); |
809 | valueType = "float" ; |
810 | break; |
811 | case Format::Date1: |
812 | case Format::Date2: |
813 | case Format::Date3: |
814 | case Format::Date4: |
815 | case Format::Date5: |
816 | case Format::Date6: |
817 | case Format::Date7: |
818 | case Format::Date8: |
819 | case Format::Date9: |
820 | case Format::Date10: |
821 | case Format::Date11: |
822 | case Format::Date12: |
823 | case Format::Date13: |
824 | case Format::Date14: |
825 | case Format::Date15: |
826 | case Format::Date16: |
827 | case Format::Date17: |
828 | case Format::Date18: |
829 | case Format::Date19: |
830 | case Format::Date20: |
831 | case Format::Date21: |
832 | case Format::Date22: |
833 | case Format::Date23: |
834 | case Format::Date24: |
835 | case Format::Date25: |
836 | case Format::Date26: |
837 | case Format::Date27: |
838 | case Format::Date28: |
839 | case Format::Date29: |
840 | case Format::Date30: |
841 | case Format::Date31: |
842 | case Format::Date32: |
843 | case Format::Date33: |
844 | case Format::Date34: |
845 | case Format::Date35: |
846 | styleName = saveOdfStyleNumericDate(mainStyles, _style, _prefix, _postfix); |
847 | valueType = "date" ; |
848 | break; |
849 | case Format::Custom: |
850 | styleName = saveOdfStyleNumericCustom(mainStyles, _style, _prefix, _postfix); |
851 | break; |
852 | case Format::Generic: |
853 | case Format::None: |
854 | if (_precision > -1 || !_prefix.isEmpty() || !_postfix.isEmpty()) { |
855 | styleName = saveOdfStyleNumericNumber(mainStyles, _style, _precision, _prefix, _postfix, thousandsSep); |
856 | valueType = "float" ; |
857 | } |
858 | break; |
859 | case Format::DateTime: |
860 | default: |
861 | ; |
862 | } |
863 | if (!styleName.isEmpty()) { |
864 | style.addAttribute("style:data-style-name" , styleName); |
865 | } |
866 | return styleName; |
867 | } |
868 | |
869 | QString Style::saveOdfStyleNumericNumber(KoGenStyles& mainStyles, Format::Type /*_style*/, int _precision, |
870 | const QString& _prefix, const QString& _postfix, bool thousandsSep) |
871 | { |
872 | QString format; |
873 | if (_precision == -1) |
874 | format = '0'; |
875 | else { |
876 | QString tmp; |
877 | for (int i = 0; i < _precision; i++) { |
878 | tmp += '0'; |
879 | } |
880 | format = "0." + tmp; |
881 | } |
882 | return KoOdfNumberStyles::saveOdfNumberStyle(mainStyles, format, _prefix, _postfix, thousandsSep); |
883 | } |
884 | |
885 | QString Style::saveOdfStyleNumericText(KoGenStyles& /*mainStyles*/, Format::Type /*_style*/, int /*_precision*/, |
886 | const QString& /*_prefix*/, const QString& /*_postfix*/) |
887 | { |
888 | return "" ; |
889 | } |
890 | |
891 | QString Style::saveOdfStyleNumericMoney(KoGenStyles& mainStyles, Format::Type /*_style*/, |
892 | const QString& symbol, int _precision, |
893 | const QString& _prefix, const QString& _postfix) |
894 | { |
895 | QString format; |
896 | if (_precision == -1) |
897 | format = '0'; |
898 | else { |
899 | QString tmp; |
900 | for (int i = 0; i < _precision; i++) { |
901 | tmp += '0'; |
902 | } |
903 | format = "0." + tmp; |
904 | } |
905 | return KoOdfNumberStyles::saveOdfCurrencyStyle(mainStyles, format, symbol, _prefix, _postfix); |
906 | } |
907 | |
908 | QString Style::saveOdfStyleNumericPercentage(KoGenStyles&mainStyles, Format::Type /*_style*/, int _precision, |
909 | const QString& _prefix, const QString& _postfix) |
910 | { |
911 | //<number:percentage-style style:name="N106" style:family="data-style"> |
912 | //<number:number number:decimal-places="6" number:min-integer-digits="1"/> |
913 | //<number:text>%</number:text> |
914 | //</number:percentage-style> |
915 | //TODO add decimal etc. |
916 | QString format; |
917 | if (_precision == -1) |
918 | format = '0'; |
919 | else { |
920 | QString tmp; |
921 | for (int i = 0; i < _precision; i++) { |
922 | tmp += '0'; |
923 | } |
924 | format = "0." + tmp; |
925 | } |
926 | return KoOdfNumberStyles::saveOdfPercentageStyle(mainStyles, format, _prefix, _postfix); |
927 | } |
928 | |
929 | |
930 | QString Style::saveOdfStyleNumericScientific(KoGenStyles&mainStyles, Format::Type /*_style*/, |
931 | const QString &_prefix, const QString &_suffix, int _precision, bool thousandsSep) |
932 | { |
933 | //<number:number-style style:name="N60" style:family="data-style"> |
934 | // <number:scientific-number number:decimal-places="2" number:min-integer-digits="1" number:min-exponent-digits="3"/> |
935 | //</number:number-style> |
936 | QString format; |
937 | if (_precision == -1) |
938 | format = "0E+00" ; |
939 | else { |
940 | QString tmp; |
941 | for (int i = 0; i < _precision; i++) { |
942 | tmp += '0'; |
943 | } |
944 | format = "0." + tmp + "E+00" ; |
945 | } |
946 | return KoOdfNumberStyles::saveOdfScientificStyle(mainStyles, format, _prefix, _suffix, thousandsSep); |
947 | } |
948 | |
949 | QString Style::saveOdfStyleNumericDate(KoGenStyles&mainStyles, Format::Type _style, |
950 | const QString& _prefix, const QString& _postfix) |
951 | { |
952 | QString format; |
953 | bool locale = false; |
954 | switch (_style) { |
955 | //TODO fixme use locale of kspread and not kglobal |
956 | case Format::ShortDate: |
957 | format = KGlobal::locale()->dateFormatShort(); |
958 | locale = true; |
959 | break; |
960 | case Format::TextDate: |
961 | format = KGlobal::locale()->dateFormat(); |
962 | locale = true; |
963 | break; |
964 | case Format::Date1: |
965 | format = "dd-MMM-yy" ; |
966 | break; |
967 | case Format::Date2: |
968 | format = "dd-MMM-yyyy" ; |
969 | break; |
970 | case Format::Date3: |
971 | format = "dd-M" ; |
972 | break; |
973 | case Format::Date4: |
974 | format = "dd-MM" ; |
975 | break; |
976 | case Format::Date5: |
977 | format = "dd/MM/yy" ; |
978 | break; |
979 | case Format::Date6: |
980 | format = "dd/MM/yyyy" ; |
981 | break; |
982 | case Format::Date7: |
983 | format = "MMM-yy" ; |
984 | break; |
985 | case Format::Date8: |
986 | format = "MMMM-yy" ; |
987 | break; |
988 | case Format::Date9: |
989 | format = "MMMM-yyyy" ; |
990 | break; |
991 | case Format::Date10: |
992 | format = "MMMMM-yy" ; |
993 | break; |
994 | case Format::Date11: |
995 | format = "dd/MMM" ; |
996 | break; |
997 | case Format::Date12: |
998 | format = "dd/MM" ; |
999 | break; |
1000 | case Format::Date13: |
1001 | format = "dd/MMM/yyyy" ; |
1002 | break; |
1003 | case Format::Date14: |
1004 | format = "yyyy/MMM/dd" ; |
1005 | break; |
1006 | case Format::Date15: |
1007 | format = "yyyy-MMM-dd" ; |
1008 | break; |
1009 | case Format::Date16: |
1010 | format = "yyyy/MM/dd" ; |
1011 | break; |
1012 | case Format::Date17: |
1013 | format = "d MMMM yyyy" ; |
1014 | break; |
1015 | case Format::Date18: |
1016 | format = "MM/dd/yyyy" ; |
1017 | break; |
1018 | case Format::Date19: |
1019 | format = "MM/dd/yy" ; |
1020 | break; |
1021 | case Format::Date20: |
1022 | format = "MMM/dd/yy" ; |
1023 | break; |
1024 | case Format::Date21: |
1025 | format = "MMM/dd/yyyy" ; |
1026 | break; |
1027 | case Format::Date22: |
1028 | format = "MMM-yyyy" ; |
1029 | break; |
1030 | case Format::Date23: |
1031 | format = "yyyy" ; |
1032 | break; |
1033 | case Format::Date24: |
1034 | format = "yy" ; |
1035 | break; |
1036 | case Format::Date25: |
1037 | format = "yyyy/MM/dd" ; |
1038 | break; |
1039 | case Format::Date26: |
1040 | format = "yyyy/MMM/dd" ; |
1041 | break; |
1042 | case Format::Date27: |
1043 | format = "MMM/yy" ; |
1044 | break; |
1045 | case Format::Date28: |
1046 | format = "MMM/yyyy" ; |
1047 | break; |
1048 | case Format::Date29: |
1049 | format = "MMMM/yy" ; |
1050 | break; |
1051 | case Format::Date30: |
1052 | format = "MMMM/yyyy" ; |
1053 | break; |
1054 | case Format::Date31: |
1055 | format = "dd-MM" ; |
1056 | break; |
1057 | case Format::Date32: |
1058 | format = "MM/yy" ; |
1059 | break; |
1060 | case Format::Date33: |
1061 | format = "MM-yy" ; |
1062 | break; |
1063 | case Format::Date34: |
1064 | format = "ddd d MMM yyyy" ; |
1065 | break; |
1066 | case Format::Date35: |
1067 | format = "dddd d MMM yyyy" ; |
1068 | break; |
1069 | default: |
1070 | kDebug(36003) << "this date format is not defined ! :" << _style; |
1071 | break; |
1072 | } |
1073 | return KoOdfNumberStyles::saveOdfDateStyle(mainStyles, format, locale, _prefix, _postfix); |
1074 | } |
1075 | |
1076 | QString Style::saveOdfStyleNumericCustom(KoGenStyles& /*mainStyles*/, Format::Type /*_style*/, |
1077 | const QString& /*_prefix*/, const QString& /*_postfix*/) |
1078 | { |
1079 | //TODO |
1080 | //<number:date-style style:name="N50" style:family="data-style" number:automatic-order="true" number:format-source="language"> |
1081 | //<number:month/> |
1082 | //<number:text>/</number:text> |
1083 | //<number:day/> |
1084 | //<number:text>/</number:text> |
1085 | //<number:year/> |
1086 | //<number:text> </number:text> |
1087 | //<number:hours number:style="long"/> |
1088 | //<number:text>:</number:text> |
1089 | //<number:minutes number:style="long"/> |
1090 | // <number:text> </number:text> |
1091 | //<number:am-pm/> |
1092 | //</number:date-style> |
1093 | return "" ; |
1094 | } |
1095 | |
1096 | QString Style::saveOdfStyleNumericTime(KoGenStyles& mainStyles, Format::Type _style, |
1097 | const QString& _prefix, const QString& _postfix) |
1098 | { |
1099 | //<number:time-style style:name="N42" style:family="data-style"> |
1100 | //<number:hours number:style="long"/> |
1101 | //<number:text>:</number:text> |
1102 | //<number:minutes number:style="long"/> |
1103 | //<number:text> </number:text> |
1104 | //<number:am-pm/> |
1105 | //</number:time-style> |
1106 | |
1107 | QString format; |
1108 | bool locale = false; |
1109 | //TODO use format |
1110 | switch (_style) { |
1111 | case Format::Time: //TODO FIXME |
1112 | format = "hh:mm:ss" ; |
1113 | break; |
1114 | case Format::SecondeTime: //TODO FIXME |
1115 | format = "hh:mm" ; |
1116 | break; |
1117 | case Format::Time1: |
1118 | format = "h:mm AP" ; |
1119 | break; |
1120 | case Format::Time2: |
1121 | format = "h:mm:ss AP" ; |
1122 | break; |
1123 | case Format::Time3: // 9 h 01 min 28 s |
1124 | format = "hh \\h mm \\m\\i\\n ss \\s" ; |
1125 | break; |
1126 | case Format::Time4: |
1127 | format = "hh:mm" ; |
1128 | break; |
1129 | case Format::Time5: |
1130 | format = "hh:mm:ss" ; |
1131 | break; |
1132 | case Format::Time6: |
1133 | format = "m:ss" ; |
1134 | break; |
1135 | case Format::Time7: |
1136 | format = "h:mm:ss" ; |
1137 | break; |
1138 | case Format::Time8: |
1139 | format = "h:mm" ; |
1140 | break; |
1141 | default: |
1142 | kDebug(36003) << "time format not defined :" << _style; |
1143 | break; |
1144 | } |
1145 | return KoOdfNumberStyles::saveOdfTimeStyle(mainStyles, format, locale, _prefix, _postfix); |
1146 | } |
1147 | |
1148 | |
1149 | QString Style::saveOdfStyleNumericFraction(KoGenStyles &mainStyles, Format::Type formatType, |
1150 | const QString &_prefix, const QString &_suffix) |
1151 | { |
1152 | //<number:number-style style:name="N71" style:family="data-style"> |
1153 | //<number:fraction number:min-integer-digits="0" number:min-numerator-digits="2" number:min-denominator-digits="2"/> |
1154 | //</number:number-style> |
1155 | QString format; |
1156 | switch (formatType) { |
1157 | case Format::fraction_half: |
1158 | format = "# ?/2" ; |
1159 | break; |
1160 | case Format::fraction_quarter: |
1161 | format = "# ?/4" ; |
1162 | break; |
1163 | case Format::fraction_eighth: |
1164 | format = "# ?/8" ; |
1165 | break; |
1166 | case Format::fraction_sixteenth: |
1167 | format = "# ?/16" ; |
1168 | break; |
1169 | case Format::fraction_tenth: |
1170 | format = "# ?/10" ; |
1171 | break; |
1172 | case Format::fraction_hundredth: |
1173 | format = "# ?/100" ; |
1174 | break; |
1175 | case Format::fraction_one_digit: |
1176 | format = "# ?/?" ; |
1177 | break; |
1178 | case Format::fraction_two_digits: |
1179 | format = "# \?\?/\?\?" ; |
1180 | break; |
1181 | case Format::fraction_three_digits: |
1182 | format = "# \?\?\?/\?\?\?" ; |
1183 | break; |
1184 | default: |
1185 | kDebug(36003) << " fraction format not defined :" << formatType; |
1186 | break; |
1187 | } |
1188 | |
1189 | return KoOdfNumberStyles::saveOdfFractionStyle(mainStyles, format, _prefix, _suffix); |
1190 | } |
1191 | |
1192 | QString Style::saveOdf(KoGenStyle& style, KoGenStyles& mainStyles, |
1193 | const StyleManager* manager) const |
1194 | { |
1195 | // list of substyles to store |
1196 | QSet<Key> keysToStore; |
1197 | |
1198 | if (isDefault()) { |
1199 | if (style.isEmpty()) { |
1200 | style = KoGenStyle(KoGenStyle::TableCellStyle, "table-cell" ); |
1201 | style.setDefaultStyle(true); |
1202 | // don't i18n'ize "Default" in this case |
1203 | return "Default" ; // mainStyles.insert( style, "Default", KoGenStyles::DontAddNumberToName ); |
1204 | } |
1205 | // no attributes to store here |
1206 | return mainStyles.insert(style, "ce" ); |
1207 | } else if (hasAttribute(NamedStyleKey)) { |
1208 | // it's not really the parent name in this case |
1209 | CustomStyle* namedStyle = manager->style(parentName()); |
1210 | // remove substyles already present in named style |
1211 | if (namedStyle) |
1212 | keysToStore = difference(*namedStyle); |
1213 | // no differences and not an automatic style yet |
1214 | if (style.isEmpty() && |
1215 | (keysToStore.count() == 0 || |
1216 | (keysToStore.count() == 1 && keysToStore.toList().first() == NamedStyleKey))) { |
1217 | return manager->openDocumentName(parentName()); |
1218 | } |
1219 | } else |
1220 | keysToStore = QSet<Key>::fromList(d->subStyles.keys()); |
1221 | |
1222 | // Calligra::Sheets::Style is definitly an OASIS auto style, |
1223 | // but don't overwrite it, if it already exists |
1224 | if (style.isEmpty()) |
1225 | style = KoGenStyle(KoGenStyle::TableCellAutoStyle, "table-cell" ); |
1226 | |
1227 | // doing the real work |
1228 | saveOdfStyle(keysToStore, style, mainStyles, manager); |
1229 | return mainStyles.insert(style, "ce" ); |
1230 | } |
1231 | |
1232 | void Style::saveOdfStyle(const QSet<Key>& keysToStore, KoGenStyle &style, |
1233 | KoGenStyles &mainStyles, const StyleManager* manager) const |
1234 | { |
1235 | #ifndef NDEBUG |
1236 | //if (type() == BUILTIN ) |
1237 | // kDebug(36006) <<"BUILTIN"; |
1238 | //else if (type() == CUSTOM ) |
1239 | // kDebug(36006) <<"CUSTOM"; |
1240 | //else if (type() == AUTO ) |
1241 | // kDebug(36006) <<"AUTO"; |
1242 | #endif |
1243 | |
1244 | if (!isDefault() && hasAttribute(NamedStyleKey)) { |
1245 | const QString parentName = manager->openDocumentName(this->parentName()); |
1246 | if (!parentName.isEmpty()) |
1247 | style.addAttribute("style:parent-style-name" , parentName); |
1248 | } |
1249 | |
1250 | if (keysToStore.contains(HorizontalAlignment)) { |
1251 | QString value; |
1252 | switch (halign()) { |
1253 | case Center: |
1254 | value = "center" ; |
1255 | break; |
1256 | case Right: |
1257 | value = "end" ; |
1258 | break; |
1259 | case Left: |
1260 | value = "start" ; |
1261 | break; |
1262 | case Justified: |
1263 | value = "justify" ; |
1264 | break; |
1265 | case HAlignUndefined: |
1266 | break; |
1267 | } |
1268 | if (!value.isEmpty()) { |
1269 | style.addProperty("style:text-align-source" , "fix" ); // table-cell-properties |
1270 | style.addProperty("fo:text-align" , value, KoGenStyle::ParagraphType); |
1271 | } |
1272 | } |
1273 | |
1274 | if (keysToStore.contains(VerticalAlignment)) { |
1275 | QString value; |
1276 | switch (valign()) { |
1277 | case Top: |
1278 | case VJustified: |
1279 | value = "top" ; |
1280 | break; |
1281 | case Middle: |
1282 | case VDistributed: |
1283 | value = "middle" ; |
1284 | break; |
1285 | case Bottom: |
1286 | value = "bottom" ; |
1287 | break; |
1288 | case VAlignUndefined: |
1289 | default: |
1290 | break; |
1291 | } |
1292 | if (!value.isEmpty()) // sanity |
1293 | style.addProperty("style:vertical-align" , value); |
1294 | |
1295 | if (valign() == VJustified || valign() == VDistributed) |
1296 | style.addProperty("calligra:vertical-distributed" , "distributed" ); |
1297 | } |
1298 | |
1299 | if (keysToStore.contains(BackgroundColor) && backgroundColor().isValid()) |
1300 | style.addProperty("fo:background-color" , colorName(backgroundColor())); |
1301 | |
1302 | if (keysToStore.contains(MultiRow) && wrapText()) |
1303 | style.addProperty("fo:wrap-option" , "wrap" ); |
1304 | |
1305 | if (keysToStore.contains(VerticalText) && verticalText()) { |
1306 | style.addProperty("style:direction" , "ttb" ); |
1307 | style.addProperty("style:rotation-angle" , "0" ); |
1308 | style.addProperty("style:rotation-align" , "none" ); |
1309 | } |
1310 | |
1311 | if (keysToStore.contains(ShrinkToFit) && shrinkToFit()) |
1312 | style.addProperty("style:shrink-to-fit" , "true" ); |
1313 | |
1314 | #if 0 |
1315 | if (keysToStore.contains(FloatFormat)) |
1316 | format.setAttribute("float" , (int) floatFormat()); |
1317 | |
1318 | if (keysToStore.contains(FloatColor)) |
1319 | format.setAttribute("floatcolor" , (int)floatColor()); |
1320 | |
1321 | if (keysToStore.contains(CustomFormat) && !customFormat().isEmpty()) |
1322 | format.setAttribute("custom" , customFormat()); |
1323 | |
1324 | if (keysToStore.contains(Format::Type) && formatType() == Money) { |
1325 | format.setAttribute("type" , (int) currency().type); |
1326 | format.setAttribute("symbol" , currency().symbol); |
1327 | } |
1328 | #endif |
1329 | if (keysToStore.contains(Angle) && angle() != 0) { |
1330 | style.addProperty("style:rotation-align" , "none" ); |
1331 | style.addProperty("style:rotation-angle" , QString::number(-1.0 * angle())); |
1332 | } |
1333 | |
1334 | if (keysToStore.contains(Indentation) && indentation() != 0.0) { |
1335 | style.addPropertyPt("fo:margin-left" , indentation(), KoGenStyle::ParagraphType); |
1336 | //FIXME |
1337 | //if ( a == HAlignUndefined ) |
1338 | //currentCellStyle.addProperty("fo:text-align", "start" ); |
1339 | } |
1340 | |
1341 | if (keysToStore.contains(DontPrintText) && keysToStore.contains(DontPrintText)) |
1342 | style.addProperty("style:print-content" , "false" ); |
1343 | |
1344 | // protection |
1345 | bool hideAll = false; |
1346 | bool hideFormula = false; |
1347 | bool isNotProtected = false; |
1348 | |
1349 | if (keysToStore.contains(NotProtected)) |
1350 | isNotProtected = notProtected(); |
1351 | |
1352 | if (keysToStore.contains(HideAll)) |
1353 | hideAll = this->hideAll(); |
1354 | |
1355 | if (keysToStore.contains(HideFormula)) |
1356 | hideFormula = this->hideFormula(); |
1357 | |
1358 | if (hideAll) |
1359 | style.addProperty("style:cell-protect" , "hidden-and-protected" ); |
1360 | else { |
1361 | if (isNotProtected && !hideFormula) |
1362 | style.addProperty("style:cell-protect" , "none" ); |
1363 | else if (isNotProtected && hideFormula) |
1364 | style.addProperty("style:cell-protect" , "formula-hidden" ); |
1365 | else if (hideFormula) |
1366 | style.addProperty("style:cell-protect" , "protected formula-hidden" ); |
1367 | else if (keysToStore.contains(NotProtected) && !isNotProtected) |
1368 | // write out, only if it is explicitly set |
1369 | style.addProperty("style:cell-protect" , "protected" ); |
1370 | } |
1371 | |
1372 | // borders |
1373 | // NOTE Stefan: QPen api docs: |
1374 | // A line width of zero indicates a cosmetic pen. This means |
1375 | // that the pen width is always drawn one pixel wide, |
1376 | // independent of the transformation set on the painter. |
1377 | if (keysToStore.contains(LeftPen) && keysToStore.contains(RightPen) && |
1378 | keysToStore.contains(TopPen) && keysToStore.contains(BottomPen) && |
1379 | (leftBorderPen() == topBorderPen()) && |
1380 | (leftBorderPen() == rightBorderPen()) && |
1381 | (leftBorderPen() == bottomBorderPen())) { |
1382 | if (leftBorderPen().style() != Qt::NoPen) |
1383 | style.addProperty("fo:border" , Odf::encodePen(leftBorderPen())); |
1384 | } else { |
1385 | if (keysToStore.contains(LeftPen) && (leftBorderPen().style() != Qt::NoPen)) |
1386 | style.addProperty("fo:border-left" , Odf::encodePen(leftBorderPen())); |
1387 | |
1388 | if (keysToStore.contains(RightPen) && (rightBorderPen().style() != Qt::NoPen)) |
1389 | style.addProperty("fo:border-right" , Odf::encodePen(rightBorderPen())); |
1390 | |
1391 | if (keysToStore.contains(TopPen) && (topBorderPen().style() != Qt::NoPen)) |
1392 | style.addProperty("fo:border-top" , Odf::encodePen(topBorderPen())); |
1393 | |
1394 | if (keysToStore.contains(BottomPen) && (bottomBorderPen().style() != Qt::NoPen)) |
1395 | style.addProperty("fo:border-bottom" , Odf::encodePen(bottomBorderPen())); |
1396 | } |
1397 | if (keysToStore.contains(FallDiagonalPen) && (fallDiagonalPen().style() != Qt::NoPen)) { |
1398 | style.addProperty("style:diagonal-tl-br" , Odf::encodePen(fallDiagonalPen())); |
1399 | } |
1400 | if (keysToStore.contains(GoUpDiagonalPen) && (goUpDiagonalPen().style() != Qt::NoPen)) { |
1401 | style.addProperty("style:diagonal-bl-tr" , Odf::encodePen(goUpDiagonalPen())); |
1402 | } |
1403 | |
1404 | // font |
1405 | if (keysToStore.contains(FontFamily)) { // !fontFamily().isEmpty() == true |
1406 | style.addProperty("fo:font-family" , fontFamily(), KoGenStyle::TextType); |
1407 | } |
1408 | if (keysToStore.contains(FontSize)) { // fontSize() != 0 |
1409 | style.addPropertyPt("fo:font-size" , fontSize(), KoGenStyle::TextType); |
1410 | } |
1411 | |
1412 | if (keysToStore.contains(FontBold) && bold()) |
1413 | style.addProperty("fo:font-weight" , "bold" , KoGenStyle::TextType); |
1414 | |
1415 | if (keysToStore.contains(FontItalic) && italic()) |
1416 | style.addProperty("fo:font-style" , "italic" , KoGenStyle::TextType); |
1417 | |
1418 | if (keysToStore.contains(FontUnderline) && underline()) { |
1419 | //style:text-underline-style="solid" style:text-underline-width="auto" |
1420 | style.addProperty("style:text-underline-style" , "solid" , KoGenStyle::TextType); |
1421 | //copy from oo-129 |
1422 | style.addProperty("style:text-underline-width" , "auto" , KoGenStyle::TextType); |
1423 | style.addProperty("style:text-underline-color" , "font-color" , KoGenStyle::TextType); |
1424 | } |
1425 | |
1426 | if (keysToStore.contains(FontStrike) && strikeOut()) |
1427 | style.addProperty("style:text-line-through-style" , "solid" , KoGenStyle::TextType); |
1428 | |
1429 | if (keysToStore.contains(FontColor) && fontColor().isValid()) { // always save |
1430 | style.addProperty("fo:color" , colorName(fontColor()), KoGenStyle::TextType); |
1431 | } |
1432 | |
1433 | //I don't think there is a reason why the background brush should be saved if it is null, |
1434 | //but remove the check if it causes problems. -- Robert Knight <robertknight@gmail.com> |
1435 | if (keysToStore.contains(BackgroundBrush) && (backgroundBrush().style() != Qt::NoBrush)) { |
1436 | QString tmp = saveOdfBackgroundStyle(mainStyles, backgroundBrush()); |
1437 | if (!tmp.isEmpty()) |
1438 | style.addProperty("calligra:fill-style-name" , tmp); |
1439 | } |
1440 | |
1441 | QString _prefix; |
1442 | QString _postfix; |
1443 | int _precision = -1; |
1444 | if (keysToStore.contains(Prefix) && !prefix().isEmpty()) |
1445 | _prefix = prefix(); |
1446 | if (keysToStore.contains(Postfix) && !postfix().isEmpty()) |
1447 | _postfix = postfix(); |
1448 | if (keysToStore.contains(Precision) && precision() != -1) |
1449 | _precision = precision(); |
1450 | bool _thousandsSep = false; |
1451 | if (keysToStore.contains(ThousandsSep)) { |
1452 | _thousandsSep = thousandsSep(); |
1453 | } |
1454 | |
1455 | QString currencyCode; |
1456 | if (keysToStore.contains(FormatTypeKey) && formatType() == Format::Money) { |
1457 | currencyCode = currency().code(); |
1458 | } |
1459 | |
1460 | QString numericStyle = saveOdfStyleNumeric(style, mainStyles, formatType(), |
1461 | _prefix, _postfix, _precision, |
1462 | currencyCode, _thousandsSep); |
1463 | if (!numericStyle.isEmpty()) |
1464 | style.addAttribute("style:data-style-name" , numericStyle); |
1465 | } |
1466 | |
1467 | QString Style::saveOdfBackgroundStyle(KoGenStyles &mainStyles, const QBrush &brush) |
1468 | { |
1469 | KoGenStyle styleobjectauto = KoGenStyle(KoGenStyle::GraphicAutoStyle, "graphic" ); |
1470 | KoOdfGraphicStyles::saveOdfFillStyle(styleobjectauto, mainStyles, brush); |
1471 | return mainStyles.insert(styleobjectauto, "gr" ); |
1472 | } |
1473 | |
1474 | void Style::saveXML(QDomDocument& doc, QDomElement& format, const StyleManager* styleManager) const |
1475 | { |
1476 | // list of substyles to store |
1477 | QSet<Key> keysToStore; |
1478 | |
1479 | if (d->subStyles.contains(NamedStyleKey)) { |
1480 | const CustomStyle* namedStyle = styleManager->style(parentName()); |
1481 | // check, if it's an unmodified named style |
1482 | keysToStore = difference(*namedStyle); |
1483 | if (type() == AUTO) { |
1484 | const QList<Key> keys = keysToStore.toList(); |
1485 | if ((keysToStore.count() == 0) || |
1486 | (keysToStore.count() == 1 && keysToStore.toList().first() == NamedStyleKey)) { |
1487 | // just save the name and we are done. |
1488 | format.setAttribute("style-name" , parentName()); |
1489 | return; |
1490 | } else |
1491 | format.setAttribute("parent" , parentName()); |
1492 | } else { // custom style |
1493 | if (d->subStyles.contains(NamedStyleKey)) |
1494 | format.setAttribute("parent" , parentName()); |
1495 | } |
1496 | } else |
1497 | keysToStore = QSet<Key>::fromList(d->subStyles.keys()); |
1498 | |
1499 | if (keysToStore.contains(HorizontalAlignment) && halign() != HAlignUndefined) |
1500 | format.setAttribute(type() == AUTO ? "align" : "alignX" , (int) halign()); |
1501 | |
1502 | if (keysToStore.contains(VerticalAlignment) && valign() != VAlignUndefined) |
1503 | format.setAttribute("alignY" , (int) valign()); |
1504 | |
1505 | if (keysToStore.contains(BackgroundColor) && backgroundColor().isValid()) |
1506 | format.setAttribute("bgcolor" , backgroundColor().name()); |
1507 | |
1508 | if (keysToStore.contains(MultiRow) && wrapText()) |
1509 | format.setAttribute("multirow" , "yes" ); |
1510 | |
1511 | if (keysToStore.contains(VerticalText) && verticalText()) |
1512 | format.setAttribute("verticaltext" , "yes" ); |
1513 | |
1514 | if (keysToStore.contains(ShrinkToFit) && shrinkToFit()) |
1515 | format.setAttribute("shrinktofit" , "yes" ); |
1516 | |
1517 | if (keysToStore.contains(Precision)) |
1518 | format.setAttribute("precision" , precision()); |
1519 | |
1520 | if (keysToStore.contains(Prefix) && !prefix().isEmpty()) |
1521 | format.setAttribute("prefix" , prefix()); |
1522 | |
1523 | if (keysToStore.contains(Postfix) && !postfix().isEmpty()) |
1524 | format.setAttribute("postfix" , postfix()); |
1525 | |
1526 | if (keysToStore.contains(FloatFormatKey)) |
1527 | format.setAttribute("float" , (int) floatFormat()); |
1528 | |
1529 | if (keysToStore.contains(FloatColorKey)) |
1530 | format.setAttribute("floatcolor" , (int)floatColor()); |
1531 | |
1532 | if (keysToStore.contains(FormatTypeKey)) |
1533 | format.setAttribute("format" , (int) formatType()); |
1534 | |
1535 | if (keysToStore.contains(CustomFormat) && !customFormat().isEmpty()) |
1536 | format.setAttribute("custom" , customFormat()); |
1537 | |
1538 | if (keysToStore.contains(FormatTypeKey) && formatType() == Format::Money) { |
1539 | format.setAttribute("type" , (int) currency().index()); |
1540 | format.setAttribute("symbol" , currency().symbol()); |
1541 | } |
1542 | |
1543 | if (keysToStore.contains(Angle)) |
1544 | format.setAttribute("angle" , angle()); |
1545 | |
1546 | if (keysToStore.contains(Indentation)) |
1547 | format.setAttribute("indent" , indentation()); |
1548 | |
1549 | if (keysToStore.contains(DontPrintText)) |
1550 | format.setAttribute("dontprinttext" , printText() ? "no" : "yes" ); |
1551 | |
1552 | if (keysToStore.contains(NotProtected)) |
1553 | format.setAttribute("noprotection" , notProtected() ? "yes" : "no" ); |
1554 | |
1555 | if (keysToStore.contains(HideAll)) |
1556 | format.setAttribute("hideall" , hideAll() ? "yes" : "no" ); |
1557 | |
1558 | if (keysToStore.contains(HideFormula)) |
1559 | format.setAttribute("hideformula" , hideFormula() ? "yes" : "no" ); |
1560 | |
1561 | if (type() == AUTO) { |
1562 | if (keysToStore.contains(FontFamily) || |
1563 | keysToStore.contains(FontSize) || |
1564 | keysToStore.contains(FontBold) || |
1565 | keysToStore.contains(FontItalic) || |
1566 | keysToStore.contains(FontStrike) || |
1567 | keysToStore.contains(FontUnderline)) { |
1568 | format.appendChild(NativeFormat::createElement("font" , font(), doc)); |
1569 | } |
1570 | } else { // custom style |
1571 | if (keysToStore.contains(FontFamily)) |
1572 | format.setAttribute("font-family" , fontFamily()); |
1573 | if (keysToStore.contains(FontSize)) |
1574 | format.setAttribute("font-size" , fontSize()); |
1575 | if (keysToStore.contains(FontBold) || keysToStore.contains(FontItalic) || |
1576 | keysToStore.contains(FontUnderline) || keysToStore.contains(FontStrike)) { |
1577 | enum FontFlags { |
1578 | FBold = 0x01, |
1579 | FUnderline = 0x02, |
1580 | FItalic = 0x04, |
1581 | FStrike = 0x08 |
1582 | }; |
1583 | int fontFlags = 0; |
1584 | fontFlags |= bold() ? FBold : 0; |
1585 | fontFlags |= italic() ? FItalic : 0; |
1586 | fontFlags |= underline() ? FUnderline : 0; |
1587 | fontFlags |= strikeOut() ? FStrike : 0; |
1588 | format.setAttribute("font-flags" , fontFlags); |
1589 | } |
1590 | } |
1591 | |
1592 | if (keysToStore.contains(FontColor) && fontColor().isValid()) |
1593 | format.appendChild(NativeFormat::createElement("pen" , fontColor(), doc)); |
1594 | |
1595 | if (keysToStore.contains(BackgroundBrush)) { |
1596 | format.setAttribute("brushcolor" , backgroundBrush().color().name()); |
1597 | format.setAttribute("brushstyle" , (int) backgroundBrush().style()); |
1598 | } |
1599 | |
1600 | if (keysToStore.contains(LeftPen)) { |
1601 | QDomElement left = doc.createElement("left-border" ); |
1602 | left.appendChild(NativeFormat::createElement("pen" , leftBorderPen(), doc)); |
1603 | format.appendChild(left); |
1604 | } |
1605 | |
1606 | if (keysToStore.contains(TopPen)) { |
1607 | QDomElement top = doc.createElement("top-border" ); |
1608 | top.appendChild(NativeFormat::createElement("pen" , topBorderPen(), doc)); |
1609 | format.appendChild(top); |
1610 | } |
1611 | |
1612 | if (keysToStore.contains(RightPen)) { |
1613 | QDomElement right = doc.createElement("right-border" ); |
1614 | right.appendChild(NativeFormat::createElement("pen" , rightBorderPen(), doc)); |
1615 | format.appendChild(right); |
1616 | } |
1617 | |
1618 | if (keysToStore.contains(BottomPen)) { |
1619 | QDomElement bottom = doc.createElement("bottom-border" ); |
1620 | bottom.appendChild(NativeFormat::createElement("pen" , bottomBorderPen(), doc)); |
1621 | format.appendChild(bottom); |
1622 | } |
1623 | |
1624 | if (keysToStore.contains(FallDiagonalPen)) { |
1625 | QDomElement fallDiagonal = doc.createElement("fall-diagonal" ); |
1626 | fallDiagonal.appendChild(NativeFormat::createElement("pen" , fallDiagonalPen(), doc)); |
1627 | format.appendChild(fallDiagonal); |
1628 | } |
1629 | |
1630 | if (keysToStore.contains(GoUpDiagonalPen)) { |
1631 | QDomElement goUpDiagonal = doc.createElement("up-diagonal" ); |
1632 | goUpDiagonal.appendChild(NativeFormat::createElement("pen" , goUpDiagonalPen(), doc)); |
1633 | format.appendChild(goUpDiagonal); |
1634 | } |
1635 | } |
1636 | |
1637 | bool Style::loadXML(KoXmlElement& format, Paste::Mode mode) |
1638 | { |
1639 | if (format.hasAttribute("style-name" )) { |
1640 | // Simply set the style name and we are done. |
1641 | insertSubStyle(NamedStyleKey, format.attribute("style-name" )); |
1642 | return true; |
1643 | } else if (format.hasAttribute("parent" )) |
1644 | insertSubStyle(NamedStyleKey, format.attribute("parent" )); |
1645 | |
1646 | bool ok; |
1647 | if (format.hasAttribute(type() == AUTO ? "align" : "alignX" )) { |
1648 | HAlign a = (HAlign) format.attribute(type() == AUTO ? "align" : "alignX" ).toInt(&ok); |
1649 | if (!ok) |
1650 | return false; |
1651 | if ((unsigned int) a >= 1 && (unsigned int) a <= 4) { |
1652 | setHAlign(a); |
1653 | } |
1654 | } |
1655 | if (format.hasAttribute("alignY" )) { |
1656 | VAlign a = (VAlign) format.attribute("alignY" ).toInt(&ok); |
1657 | if (!ok) |
1658 | return false; |
1659 | if ((unsigned int) a >= 1 && (unsigned int) a < 4) { |
1660 | setVAlign(a); |
1661 | } |
1662 | } |
1663 | |
1664 | if (format.hasAttribute("bgcolor" )) { |
1665 | QColor color(format.attribute("bgcolor" )); |
1666 | if (color.isValid()) |
1667 | setBackgroundColor(color); |
1668 | } |
1669 | |
1670 | if (format.hasAttribute("multirow" )) { |
1671 | setWrapText(true); |
1672 | } |
1673 | |
1674 | if (format.hasAttribute("shrinktofit" )) { |
1675 | setShrinkToFit(true); |
1676 | } |
1677 | |
1678 | if (format.hasAttribute("precision" )) { |
1679 | int i = format.attribute("precision" ).toInt(&ok); |
1680 | if (i < -1) { |
1681 | kDebug(36003) << "Value out of range Cell::precision=" << i; |
1682 | return false; |
1683 | } |
1684 | // special handling for precision |
1685 | // The Style default (-1) and the storage default (0) differ. |
1686 | if (type() == AUTO && i == -1) |
1687 | i = 0; |
1688 | // The maximum is 10. Replace the Style value 0 with -11, which always results |
1689 | // in a storage value < 0 and is interpreted as Style value 0. |
1690 | else if (type() == AUTO && i == 0) |
1691 | i = -11; |
1692 | setPrecision(i); |
1693 | } |
1694 | |
1695 | if (format.hasAttribute("float" )) { |
1696 | FloatFormat a = (FloatFormat)format.attribute("float" ).toInt(&ok); |
1697 | if (!ok) |
1698 | return false; |
1699 | if ((unsigned int) a >= 1 && (unsigned int) a <= 3) { |
1700 | setFloatFormat(a); |
1701 | } |
1702 | } |
1703 | |
1704 | if (format.hasAttribute("floatcolor" )) { |
1705 | FloatColor a = (FloatColor) format.attribute("floatcolor" ).toInt(&ok); |
1706 | if (!ok) return false; |
1707 | if ((unsigned int) a >= 1 && (unsigned int) a <= 2) { |
1708 | setFloatColor(a); |
1709 | } |
1710 | } |
1711 | |
1712 | if (format.hasAttribute("format" )) { |
1713 | int fo = format.attribute("format" ).toInt(&ok); |
1714 | if (! ok) |
1715 | return false; |
1716 | setFormatType(static_cast<Format::Type>(fo)); |
1717 | } |
1718 | if (format.hasAttribute("custom" )) { |
1719 | setCustomFormat(format.attribute("custom" )); |
1720 | } |
1721 | if (formatType() == Format::Money) { |
1722 | ok = true; |
1723 | Currency currency; |
1724 | if (format.hasAttribute("type" )) { |
1725 | currency = Currency(format.attribute("type" ).toInt(&ok)); |
1726 | if (!ok) { |
1727 | if (format.hasAttribute("symbol" )) |
1728 | currency = Currency(format.attribute("symbol" )); |
1729 | } |
1730 | } else if (format.hasAttribute("symbol" )) |
1731 | currency = Currency(format.attribute("symbol" )); |
1732 | setCurrency(currency); |
1733 | } |
1734 | if (format.hasAttribute("angle" )) { |
1735 | setAngle(format.attribute("angle" ).toInt(&ok)); |
1736 | if (!ok) |
1737 | return false; |
1738 | } |
1739 | if (format.hasAttribute("indent" )) { |
1740 | setIndentation(format.attribute("indent" ).toDouble(&ok)); |
1741 | if (!ok) |
1742 | return false; |
1743 | } |
1744 | if (format.hasAttribute("dontprinttext" )) { |
1745 | setDontPrintText(true); |
1746 | } |
1747 | |
1748 | if (format.hasAttribute("noprotection" )) { |
1749 | setNotProtected(true); |
1750 | } |
1751 | |
1752 | if (format.hasAttribute("hideall" )) { |
1753 | setHideAll(true); |
1754 | } |
1755 | |
1756 | if (format.hasAttribute("hideformula" )) { |
1757 | setHideFormula(true); |
1758 | } |
1759 | |
1760 | if (type() == AUTO) { |
1761 | KoXmlElement fontElement = format.namedItem("font" ).toElement(); |
1762 | if (!fontElement.isNull()) { |
1763 | QFont font(NativeFormat::toFont(fontElement)); |
1764 | setFontFamily(font.family()); |
1765 | setFontSize(font.pointSize()); |
1766 | if (font.italic()) |
1767 | setFontItalic(true); |
1768 | if (font.bold()) |
1769 | setFontBold(true); |
1770 | if (font.underline()) |
1771 | setFontUnderline(true); |
1772 | if (font.strikeOut()) |
1773 | setFontStrikeOut(true); |
1774 | } |
1775 | } else { // custom style |
1776 | if (format.hasAttribute("font-family" )) |
1777 | setFontFamily(format.attribute("font-family" )); |
1778 | if (format.hasAttribute("font-size" )) { |
1779 | setFontSize(format.attribute("font-size" ).toInt(&ok)); |
1780 | if (!ok) |
1781 | return false; |
1782 | } |
1783 | if (format.hasAttribute("font-flags" )) { |
1784 | int fontFlags = format.attribute("font-flags" ).toInt(&ok); |
1785 | if (!ok) |
1786 | return false; |
1787 | |
1788 | enum FontFlags { |
1789 | FBold = 0x01, |
1790 | FUnderline = 0x02, |
1791 | FItalic = 0x04, |
1792 | FStrike = 0x08 |
1793 | }; |
1794 | setFontBold(fontFlags & FBold); |
1795 | setFontItalic(fontFlags & FItalic); |
1796 | setFontUnderline(fontFlags & FUnderline); |
1797 | setFontStrikeOut(fontFlags & FStrike); |
1798 | } |
1799 | } |
1800 | |
1801 | if (format.hasAttribute("brushcolor" )) { |
1802 | QColor color(format.attribute("brushcolor" )); |
1803 | if (color.isValid()) { |
1804 | QBrush brush = backgroundBrush(); |
1805 | brush.setColor(color); |
1806 | setBackgroundBrush(brush); |
1807 | } |
1808 | } |
1809 | |
1810 | if (format.hasAttribute("brushstyle" )) { |
1811 | QBrush brush = backgroundBrush(); |
1812 | brush.setStyle((Qt::BrushStyle) format.attribute("brushstyle" ).toInt(&ok)); |
1813 | if (!ok) |
1814 | return false; |
1815 | setBackgroundBrush(brush); |
1816 | } |
1817 | |
1818 | KoXmlElement pen = format.namedItem("pen" ).toElement(); |
1819 | if (!pen.isNull()) { |
1820 | setFontColor(NativeFormat::toPen(pen).color()); |
1821 | } |
1822 | |
1823 | if (mode != Paste::NoBorder) { |
1824 | KoXmlElement left = format.namedItem("left-border" ).toElement(); |
1825 | if (!left.isNull()) { |
1826 | KoXmlElement pen = left.namedItem("pen" ).toElement(); |
1827 | if (!pen.isNull()) |
1828 | setLeftBorderPen(NativeFormat::toPen(pen)); |
1829 | } |
1830 | |
1831 | KoXmlElement top = format.namedItem("top-border" ).toElement(); |
1832 | if (!top.isNull()) { |
1833 | KoXmlElement pen = top.namedItem("pen" ).toElement(); |
1834 | if (!pen.isNull()) |
1835 | setTopBorderPen(NativeFormat::toPen(pen)); |
1836 | } |
1837 | |
1838 | KoXmlElement right = format.namedItem("right-border" ).toElement(); |
1839 | if (!right.isNull()) { |
1840 | KoXmlElement pen = right.namedItem("pen" ).toElement(); |
1841 | if (!pen.isNull()) |
1842 | setRightBorderPen(NativeFormat::toPen(pen)); |
1843 | } |
1844 | |
1845 | KoXmlElement bottom = format.namedItem("bottom-border" ).toElement(); |
1846 | if (!bottom.isNull()) { |
1847 | KoXmlElement pen = bottom.namedItem("pen" ).toElement(); |
1848 | if (!pen.isNull()) |
1849 | setBottomBorderPen(NativeFormat::toPen(pen)); |
1850 | } |
1851 | |
1852 | KoXmlElement fallDiagonal = format.namedItem("fall-diagonal" ).toElement(); |
1853 | if (!fallDiagonal.isNull()) { |
1854 | KoXmlElement pen = fallDiagonal.namedItem("pen" ).toElement(); |
1855 | if (!pen.isNull()) |
1856 | setFallDiagonalPen(NativeFormat::toPen(pen)); |
1857 | } |
1858 | |
1859 | KoXmlElement goUpDiagonal = format.namedItem("up-diagonal" ).toElement(); |
1860 | if (!goUpDiagonal.isNull()) { |
1861 | KoXmlElement pen = goUpDiagonal.namedItem("pen" ).toElement(); |
1862 | if (!pen.isNull()) |
1863 | setGoUpDiagonalPen(NativeFormat::toPen(pen)); |
1864 | } |
1865 | } |
1866 | |
1867 | if (format.hasAttribute("prefix" )) { |
1868 | setPrefix(format.attribute("prefix" )); |
1869 | } |
1870 | if (format.hasAttribute("postfix" )) { |
1871 | setPostfix(format.attribute("postfix" )); |
1872 | } |
1873 | |
1874 | return true; |
1875 | } |
1876 | |
1877 | uint Style::bottomPenValue() const |
1878 | { |
1879 | if (!d->subStyles.contains(BottomPen)) |
1880 | return BorderPenStyle<BottomPen>().value; |
1881 | return static_cast<const BorderPenStyle<BottomPen>*>(d->subStyles[BottomPen].data())->value; |
1882 | } |
1883 | |
1884 | uint Style::rightPenValue() const |
1885 | { |
1886 | if (!d->subStyles.contains(RightPen)) |
1887 | return BorderPenStyle<RightPen>().value; |
1888 | return static_cast<const BorderPenStyle<RightPen>*>(d->subStyles[RightPen].data())->value; |
1889 | } |
1890 | |
1891 | uint Style::leftPenValue() const |
1892 | { |
1893 | if (!d->subStyles.contains(LeftPen)) |
1894 | return BorderPenStyle<LeftPen>().value; |
1895 | return static_cast<const BorderPenStyle<LeftPen>*>(d->subStyles[LeftPen].data())->value; |
1896 | } |
1897 | |
1898 | uint Style::topPenValue() const |
1899 | { |
1900 | if (!d->subStyles.contains(TopPen)) |
1901 | return BorderPenStyle<TopPen>().value; |
1902 | return static_cast<const BorderPenStyle<TopPen>*>(d->subStyles[TopPen].data())->value; |
1903 | } |
1904 | |
1905 | QColor Style::fontColor() const |
1906 | { |
1907 | if (!d->subStyles.contains(FontColor)) |
1908 | return SubStyleOne<FontColor, QColor>().value1; |
1909 | return static_cast<const SubStyleOne<FontColor, QColor>*>(d->subStyles[FontColor].data())->value1; |
1910 | } |
1911 | |
1912 | QColor Style::backgroundColor() const |
1913 | { |
1914 | if (!d->subStyles.contains(BackgroundColor)) |
1915 | return SubStyleOne<BackgroundColor, QColor>().value1; |
1916 | return static_cast<const SubStyleOne<BackgroundColor, QColor>*>(d->subStyles[BackgroundColor].data())->value1; |
1917 | } |
1918 | |
1919 | QPen Style::rightBorderPen() const |
1920 | { |
1921 | if (!d->subStyles.contains(RightPen)) |
1922 | return BorderPenStyle<RightPen>().value1; |
1923 | return static_cast<const BorderPenStyle<RightPen>*>(d->subStyles[RightPen].data())->value1; |
1924 | } |
1925 | |
1926 | QPen Style::bottomBorderPen() const |
1927 | { |
1928 | if (!d->subStyles.contains(BottomPen)) |
1929 | return BorderPenStyle<BottomPen>().value1; |
1930 | return static_cast<const BorderPenStyle<BottomPen>*>(d->subStyles[BottomPen].data())->value1; |
1931 | } |
1932 | |
1933 | QPen Style::leftBorderPen() const |
1934 | { |
1935 | if (!d->subStyles.contains(LeftPen)) |
1936 | return BorderPenStyle<LeftPen>().value1; |
1937 | return static_cast<const BorderPenStyle<LeftPen>*>(d->subStyles[LeftPen].data())->value1; |
1938 | } |
1939 | |
1940 | QPen Style::topBorderPen() const |
1941 | { |
1942 | if (!d->subStyles.contains(TopPen)) |
1943 | return BorderPenStyle<TopPen>().value1; |
1944 | return static_cast<const BorderPenStyle<TopPen>*>(d->subStyles[TopPen].data())->value1; |
1945 | } |
1946 | |
1947 | QPen Style::fallDiagonalPen() const |
1948 | { |
1949 | if (!d->subStyles.contains(FallDiagonalPen)) |
1950 | return PenStyle<FallDiagonalPen>().value1; |
1951 | return static_cast<const PenStyle<FallDiagonalPen>*>(d->subStyles[FallDiagonalPen].data())->value1; |
1952 | } |
1953 | |
1954 | QPen Style::goUpDiagonalPen() const |
1955 | { |
1956 | if (!d->subStyles.contains(GoUpDiagonalPen)) |
1957 | return PenStyle<GoUpDiagonalPen>().value1; |
1958 | return static_cast<const PenStyle<GoUpDiagonalPen>*>(d->subStyles[GoUpDiagonalPen].data())->value1; |
1959 | } |
1960 | |
1961 | QBrush Style::backgroundBrush() const |
1962 | { |
1963 | if (!d->subStyles.contains(BackgroundBrush)) |
1964 | return SubStyleOne<BackgroundBrush, QBrush>().value1; |
1965 | return static_cast<const SubStyleOne<BackgroundBrush, QBrush>*>(d->subStyles[BackgroundBrush].data())->value1; |
1966 | } |
1967 | |
1968 | QString Style::customFormat() const |
1969 | { |
1970 | if (!d->subStyles.contains(CustomFormat)) |
1971 | return SubStyleOne<CustomFormat, QString>().value1; |
1972 | return static_cast<const SubStyleOne<CustomFormat, QString>*>(d->subStyles[CustomFormat].data())->value1; |
1973 | } |
1974 | |
1975 | QString Style::prefix() const |
1976 | { |
1977 | if (!d->subStyles.contains(Prefix)) |
1978 | return SubStyleOne<Prefix, QString>().value1; |
1979 | return static_cast<const SubStyleOne<Prefix, QString>*>(d->subStyles[Prefix].data())->value1; |
1980 | } |
1981 | |
1982 | QString Style::postfix() const |
1983 | { |
1984 | if (!d->subStyles.contains(Postfix)) |
1985 | return SubStyleOne<Postfix, QString>().value1; |
1986 | return static_cast<const SubStyleOne<Postfix, QString>*>(d->subStyles[Postfix].data())->value1; |
1987 | } |
1988 | |
1989 | QString Style::fontFamily() const |
1990 | { |
1991 | if (!d->subStyles.contains(FontFamily)) |
1992 | return KoGlobal::defaultFont().family(); // SubStyleOne<FontFamily, QString>().value1; |
1993 | return static_cast<const SubStyleOne<FontFamily, QString>*>(d->subStyles[FontFamily].data())->value1; |
1994 | } |
1995 | |
1996 | Style::HAlign Style::halign() const |
1997 | { |
1998 | if (!d->subStyles.contains(HorizontalAlignment)) |
1999 | return SubStyleOne<HorizontalAlignment, Style::HAlign>().value1; |
2000 | return static_cast<const SubStyleOne<HorizontalAlignment, Style::HAlign>*>(d->subStyles[HorizontalAlignment].data())->value1; |
2001 | } |
2002 | |
2003 | Style::VAlign Style::valign() const |
2004 | { |
2005 | if (!d->subStyles.contains(VerticalAlignment)) |
2006 | return SubStyleOne<VerticalAlignment, Style::VAlign>().value1; |
2007 | return static_cast<const SubStyleOne<VerticalAlignment, Style::VAlign>*>(d->subStyles[VerticalAlignment].data())->value1; |
2008 | } |
2009 | |
2010 | Style::FloatFormat Style::floatFormat() const |
2011 | { |
2012 | if (!d->subStyles.contains(FloatFormatKey)) |
2013 | return SubStyleOne<FloatFormatKey, FloatFormat>().value1; |
2014 | return static_cast<const SubStyleOne<FloatFormatKey, FloatFormat>*>(d->subStyles[FloatFormatKey].data())->value1; |
2015 | } |
2016 | |
2017 | Style::FloatColor Style::floatColor() const |
2018 | { |
2019 | if (!d->subStyles.contains(FloatColorKey)) |
2020 | return SubStyleOne<FloatColorKey, FloatColor>().value1; |
2021 | return static_cast<const SubStyleOne<FloatColorKey, FloatColor>*>(d->subStyles[FloatColorKey].data())->value1; |
2022 | } |
2023 | |
2024 | Format::Type Style::formatType() const |
2025 | { |
2026 | if (!d->subStyles.contains(FormatTypeKey)) |
2027 | return SubStyleOne<FormatTypeKey, Format::Type>().value1; |
2028 | return static_cast<const SubStyleOne<FormatTypeKey, Format::Type>*>(d->subStyles[FormatTypeKey].data())->value1; |
2029 | } |
2030 | |
2031 | Currency Style::currency() const |
2032 | { |
2033 | if (!d->subStyles.contains(CurrencyFormat)) |
2034 | return Currency(); |
2035 | return static_cast<const SubStyleOne<CurrencyFormat, Currency>*>(d->subStyles[CurrencyFormat].data())->value1; |
2036 | } |
2037 | |
2038 | QFont Style::font() const |
2039 | { |
2040 | QFont font; |
2041 | font.setFamily(fontFamily()); |
2042 | font.setPointSize(fontSize()); |
2043 | font.setBold(bold()); |
2044 | font.setItalic(italic()); |
2045 | font.setUnderline(underline()); |
2046 | font.setStrikeOut(strikeOut()); |
2047 | return font; |
2048 | } |
2049 | |
2050 | bool Style::bold() const |
2051 | { |
2052 | if (!d->subStyles.contains(FontBold)) |
2053 | return SubStyleOne<FontBold, bool>().value1; |
2054 | return static_cast<const SubStyleOne<FontBold, bool>*>(d->subStyles[FontBold].data())->value1; |
2055 | } |
2056 | |
2057 | bool Style::italic() const |
2058 | { |
2059 | if (!d->subStyles.contains(FontItalic)) |
2060 | return SubStyleOne<FontItalic, bool>().value1; |
2061 | return static_cast<const SubStyleOne<FontItalic, bool>*>(d->subStyles[FontItalic].data())->value1; |
2062 | } |
2063 | |
2064 | bool Style::underline() const |
2065 | { |
2066 | if (!d->subStyles.contains(FontUnderline)) |
2067 | return SubStyleOne<FontUnderline, bool>().value1; |
2068 | return static_cast<const SubStyleOne<FontUnderline, bool>*>(d->subStyles[FontUnderline].data())->value1; |
2069 | } |
2070 | |
2071 | bool Style::strikeOut() const |
2072 | { |
2073 | if (!d->subStyles.contains(FontStrike)) |
2074 | return SubStyleOne<FontStrike, bool>().value1; |
2075 | return static_cast<const SubStyleOne<FontStrike, bool>*>(d->subStyles[FontStrike].data())->value1; |
2076 | } |
2077 | |
2078 | int Style::fontSize() const |
2079 | { |
2080 | if (!d->subStyles.contains(FontSize)) |
2081 | return KoGlobal::defaultFont().pointSize(); //SubStyleOne<FontSize, int>().value1; |
2082 | return static_cast<const SubStyleOne<FontSize, int>*>(d->subStyles[FontSize].data())->value1; |
2083 | } |
2084 | |
2085 | int Style::precision() const |
2086 | { |
2087 | if (!d->subStyles.contains(Precision)) |
2088 | return -1; //SubStyleOne<Precision, int>().value1; |
2089 | return static_cast<const SubStyleOne<Precision, int>*>(d->subStyles[Precision].data())->value1; |
2090 | } |
2091 | |
2092 | bool Style::thousandsSep() const |
2093 | { |
2094 | if (!d->subStyles.contains(ThousandsSep)) |
2095 | return false; |
2096 | return static_cast<const SubStyleOne<ThousandsSep, bool>*>(d->subStyles[ThousandsSep].data())->value1; |
2097 | } |
2098 | |
2099 | int Style::angle() const |
2100 | { |
2101 | if (!d->subStyles.contains(Angle)) |
2102 | return SubStyleOne<Angle, int>().value1; |
2103 | return static_cast<const SubStyleOne<Angle, int>*>(d->subStyles[Angle].data())->value1; |
2104 | } |
2105 | |
2106 | double Style::indentation() const |
2107 | { |
2108 | if (!d->subStyles.contains(Indentation)) |
2109 | return SubStyleOne<Indentation, int>().value1; |
2110 | return static_cast<const SubStyleOne<Indentation, int>*>(d->subStyles[Indentation].data())->value1; |
2111 | } |
2112 | |
2113 | bool Style::shrinkToFit() const |
2114 | { |
2115 | if (!d->subStyles.contains(ShrinkToFit)) |
2116 | return SubStyleOne<ShrinkToFit, bool>().value1; |
2117 | return static_cast<const SubStyleOne<ShrinkToFit, bool>*>(d->subStyles[ShrinkToFit].data())->value1; |
2118 | } |
2119 | |
2120 | bool Style::verticalText() const |
2121 | { |
2122 | if (!d->subStyles.contains(VerticalText)) |
2123 | return SubStyleOne<VerticalText, bool>().value1; |
2124 | return static_cast<const SubStyleOne<VerticalText, bool>*>(d->subStyles[VerticalText].data())->value1; |
2125 | } |
2126 | |
2127 | bool Style::wrapText() const |
2128 | { |
2129 | if (!d->subStyles.contains(MultiRow)) |
2130 | return SubStyleOne<MultiRow, bool>().value1; |
2131 | return static_cast<const SubStyleOne<MultiRow, bool>*>(d->subStyles[MultiRow].data())->value1; |
2132 | } |
2133 | |
2134 | bool Style::printText() const |
2135 | { |
2136 | if (!d->subStyles.contains(DontPrintText)) |
2137 | return !SubStyleOne<DontPrintText, bool>().value1; |
2138 | return !static_cast<const SubStyleOne<DontPrintText, bool>*>(d->subStyles[DontPrintText].data())->value1; |
2139 | } |
2140 | |
2141 | bool Style::hideAll() const |
2142 | { |
2143 | if (!d->subStyles.contains(HideAll)) |
2144 | return SubStyleOne<HideAll, bool>().value1; |
2145 | return static_cast<const SubStyleOne<HideAll, bool>*>(d->subStyles[HideAll].data())->value1; |
2146 | } |
2147 | |
2148 | bool Style::hideFormula() const |
2149 | { |
2150 | if (!d->subStyles.contains(HideFormula)) |
2151 | return SubStyleOne<HideFormula, bool>().value1; |
2152 | return static_cast<const SubStyleOne<HideFormula, bool>*>(d->subStyles[HideFormula].data())->value1; |
2153 | } |
2154 | |
2155 | bool Style::notProtected() const |
2156 | { |
2157 | if (!d->subStyles.contains(NotProtected)) |
2158 | return SubStyleOne<NotProtected, bool>().value1; |
2159 | return static_cast<const SubStyleOne<NotProtected, bool>*>(d->subStyles[NotProtected].data())->value1; |
2160 | } |
2161 | |
2162 | bool Style::isDefault() const |
2163 | { |
2164 | return isEmpty() || d->subStyles.contains(DefaultStyleKey); |
2165 | } |
2166 | |
2167 | bool Style::isEmpty() const |
2168 | { |
2169 | return d->subStyles.isEmpty(); |
2170 | } |
2171 | |
2172 | void Style::setHAlign(HAlign align) |
2173 | { |
2174 | insertSubStyle(HorizontalAlignment, align); |
2175 | } |
2176 | |
2177 | void Style::setVAlign(VAlign align) |
2178 | { |
2179 | insertSubStyle(VerticalAlignment, align); |
2180 | } |
2181 | |
2182 | void Style::setFont(QFont const & font) |
2183 | { |
2184 | insertSubStyle(FontFamily, font.family()); |
2185 | insertSubStyle(FontSize, font.pointSize()); |
2186 | insertSubStyle(FontBold, font.bold()); |
2187 | insertSubStyle(FontItalic, font.italic()); |
2188 | insertSubStyle(FontStrike, font.strikeOut()); |
2189 | insertSubStyle(FontUnderline, font.underline()); |
2190 | } |
2191 | |
2192 | void Style::setFontFamily(QString const & family) |
2193 | { |
2194 | insertSubStyle(FontFamily, family); |
2195 | } |
2196 | |
2197 | void Style::setFontBold(bool enabled) |
2198 | { |
2199 | insertSubStyle(FontBold, enabled); |
2200 | } |
2201 | |
2202 | void Style::setFontItalic(bool enabled) |
2203 | { |
2204 | insertSubStyle(FontItalic, enabled); |
2205 | } |
2206 | |
2207 | void Style::setFontUnderline(bool enabled) |
2208 | { |
2209 | insertSubStyle(FontUnderline, enabled); |
2210 | } |
2211 | |
2212 | void Style::setFontStrikeOut(bool enabled) |
2213 | { |
2214 | insertSubStyle(FontStrike, enabled); |
2215 | } |
2216 | |
2217 | void Style::setFontSize(int size) |
2218 | { |
2219 | insertSubStyle(FontSize, size); |
2220 | } |
2221 | |
2222 | void Style::setFontColor(QColor const & color) |
2223 | { |
2224 | insertSubStyle(FontColor, color); |
2225 | } |
2226 | |
2227 | void Style::setBackgroundColor(QColor const & color) |
2228 | { |
2229 | insertSubStyle(BackgroundColor, color); |
2230 | } |
2231 | |
2232 | void Style::setRightBorderPen(QPen const & pen) |
2233 | { |
2234 | insertSubStyle(RightPen, pen); |
2235 | } |
2236 | |
2237 | void Style::setBottomBorderPen(QPen const & pen) |
2238 | { |
2239 | insertSubStyle(BottomPen, pen); |
2240 | } |
2241 | |
2242 | void Style::setLeftBorderPen(QPen const & pen) |
2243 | { |
2244 | insertSubStyle(LeftPen, pen); |
2245 | } |
2246 | |
2247 | void Style::setTopBorderPen(QPen const & pen) |
2248 | { |
2249 | insertSubStyle(TopPen, pen); |
2250 | } |
2251 | |
2252 | void Style::setFallDiagonalPen(QPen const & pen) |
2253 | { |
2254 | insertSubStyle(FallDiagonalPen, pen); |
2255 | } |
2256 | |
2257 | void Style::setGoUpDiagonalPen(QPen const & pen) |
2258 | { |
2259 | insertSubStyle(GoUpDiagonalPen, pen); |
2260 | } |
2261 | |
2262 | void Style::setAngle(int angle) |
2263 | { |
2264 | insertSubStyle(Angle, angle); |
2265 | } |
2266 | |
2267 | void Style::setIndentation(double indent) |
2268 | { |
2269 | insertSubStyle(Indentation, indent); |
2270 | } |
2271 | |
2272 | void Style::setBackgroundBrush(QBrush const & brush) |
2273 | { |
2274 | insertSubStyle(BackgroundBrush, brush); |
2275 | } |
2276 | |
2277 | void Style::setFloatFormat(FloatFormat format) |
2278 | { |
2279 | insertSubStyle(FloatFormatKey, format); |
2280 | } |
2281 | |
2282 | void Style::setFloatColor(FloatColor color) |
2283 | { |
2284 | insertSubStyle(FloatColorKey, color); |
2285 | } |
2286 | |
2287 | void Style::setFormatType(Format::Type format) |
2288 | { |
2289 | insertSubStyle(FormatTypeKey, format); |
2290 | } |
2291 | |
2292 | void Style::setCustomFormat(QString const & strFormat) |
2293 | { |
2294 | insertSubStyle(CustomFormat, strFormat); |
2295 | } |
2296 | |
2297 | void Style::setPrecision(int precision) |
2298 | { |
2299 | insertSubStyle(Precision, precision); |
2300 | } |
2301 | |
2302 | void Style::setThousandsSep(bool thousandsSep) |
2303 | { |
2304 | insertSubStyle(ThousandsSep, thousandsSep); |
2305 | } |
2306 | |
2307 | void Style::setPrefix(QString const & prefix) |
2308 | { |
2309 | insertSubStyle(Prefix, prefix); |
2310 | } |
2311 | |
2312 | void Style::setPostfix(QString const & postfix) |
2313 | { |
2314 | insertSubStyle(Postfix, postfix); |
2315 | } |
2316 | |
2317 | void Style::setCurrency(Currency const & currency) |
2318 | { |
2319 | QVariant variant; |
2320 | variant.setValue(currency); |
2321 | insertSubStyle(CurrencyFormat, variant); |
2322 | } |
2323 | |
2324 | void Style::setWrapText(bool enable) |
2325 | { |
2326 | insertSubStyle(MultiRow, enable); |
2327 | } |
2328 | |
2329 | void Style::setHideAll(bool enable) |
2330 | { |
2331 | insertSubStyle(HideAll, enable); |
2332 | } |
2333 | |
2334 | void Style::setHideFormula(bool enable) |
2335 | { |
2336 | insertSubStyle(HideFormula, enable); |
2337 | } |
2338 | |
2339 | void Style::setNotProtected(bool enable) |
2340 | { |
2341 | insertSubStyle(NotProtected, enable); |
2342 | } |
2343 | |
2344 | void Style::setDontPrintText(bool enable) |
2345 | { |
2346 | insertSubStyle(DontPrintText, enable); |
2347 | } |
2348 | |
2349 | void Style::setVerticalText(bool enable) |
2350 | { |
2351 | insertSubStyle(VerticalText, enable); |
2352 | } |
2353 | |
2354 | void Style::setShrinkToFit(bool enable) |
2355 | { |
2356 | insertSubStyle(ShrinkToFit, enable); |
2357 | } |
2358 | |
2359 | void Style::setDefault() |
2360 | { |
2361 | insertSubStyle(DefaultStyleKey, true); |
2362 | } |
2363 | |
2364 | void Style::clear() |
2365 | { |
2366 | d->subStyles.clear(); |
2367 | } |
2368 | |
2369 | QString Style::colorName(const QColor& color) |
2370 | { |
2371 | static QMap<QRgb, QString> map; |
2372 | QRgb rgb = color.rgb(); |
2373 | if (!map.contains(rgb)) { |
2374 | map[rgb] = color.name(); |
2375 | return map[rgb]; |
2376 | } else { |
2377 | return map[rgb]; |
2378 | } |
2379 | } |
2380 | |
2381 | bool Style::compare(const SubStyle* one, const SubStyle* two) |
2382 | { |
2383 | if (!one || !two) |
2384 | return one == two; |
2385 | if (one->type() != two->type()) |
2386 | return false; |
2387 | switch (one->type()) { |
2388 | case DefaultStyleKey: |
2389 | return true; |
2390 | case NamedStyleKey: |
2391 | return static_cast<const NamedStyle*>(one)->name == static_cast<const NamedStyle*>(two)->name; |
2392 | // borders |
2393 | case LeftPen: |
2394 | return static_cast<const SubStyleOne<LeftPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<LeftPen, QPen>*>(two)->value1; |
2395 | case RightPen: |
2396 | return static_cast<const SubStyleOne<RightPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<RightPen, QPen>*>(two)->value1; |
2397 | case TopPen: |
2398 | return static_cast<const SubStyleOne<TopPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<TopPen, QPen>*>(two)->value1; |
2399 | case BottomPen: |
2400 | return static_cast<const SubStyleOne<BottomPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<BottomPen, QPen>*>(two)->value1; |
2401 | case FallDiagonalPen: |
2402 | return static_cast<const SubStyleOne<FallDiagonalPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<FallDiagonalPen, QPen>*>(two)->value1; |
2403 | case GoUpDiagonalPen: |
2404 | return static_cast<const SubStyleOne<GoUpDiagonalPen, QPen>*>(one)->value1 == static_cast<const SubStyleOne<GoUpDiagonalPen, QPen>*>(two)->value1; |
2405 | // layout |
2406 | case HorizontalAlignment: |
2407 | return static_cast<const SubStyleOne<HorizontalAlignment, HAlign>*>(one)->value1 == static_cast<const SubStyleOne<HorizontalAlignment, HAlign>*>(two)->value1; |
2408 | case VerticalAlignment: |
2409 | return static_cast<const SubStyleOne<VerticalAlignment, VAlign>*>(one)->value1 == static_cast<const SubStyleOne<VerticalAlignment, VAlign>*>(two)->value1; |
2410 | case MultiRow: |
2411 | return static_cast<const SubStyleOne<MultiRow, bool>*>(one)->value1 == static_cast<const SubStyleOne<MultiRow, bool>*>(two)->value1; |
2412 | case VerticalText: |
2413 | return static_cast<const SubStyleOne<VerticalText, bool>*>(one)->value1 == static_cast<const SubStyleOne<VerticalText, bool>*>(two)->value1; |
2414 | case ShrinkToFit: |
2415 | return static_cast<const SubStyleOne<ShrinkToFit, bool>*>(one)->value1 == static_cast<const SubStyleOne<ShrinkToFit, bool>*>(two)->value1; |
2416 | case Angle: |
2417 | return static_cast<const SubStyleOne<Angle, int>*>(one)->value1 == static_cast<const SubStyleOne<Angle, int>*>(two)->value1; |
2418 | case Indentation: |
2419 | return static_cast<const SubStyleOne<Indentation, int>*>(one)->value1 == static_cast<const SubStyleOne<Indentation, int>*>(two)->value1; |
2420 | // content format |
2421 | case Prefix: |
2422 | return static_cast<const SubStyleOne<Prefix, QString>*>(one)->value1 == static_cast<const SubStyleOne<Prefix, QString>*>(two)->value1; |
2423 | case Postfix: |
2424 | return static_cast<const SubStyleOne<Postfix, QString>*>(one)->value1 == static_cast<const SubStyleOne<Postfix, QString>*>(two)->value1; |
2425 | case Precision: |
2426 | return static_cast<const SubStyleOne<Precision, int>*>(one)->value1 == static_cast<const SubStyleOne<Precision, int>*>(two)->value1; |
2427 | case ThousandsSep: |
2428 | return static_cast<const SubStyleOne<ThousandsSep, bool>*>(one)->value1 == static_cast<const SubStyleOne<ThousandsSep, bool>*>(two)->value1; |
2429 | case FormatTypeKey: |
2430 | return static_cast<const SubStyleOne<FormatTypeKey, Format::Type>*>(one)->value1 == static_cast<const SubStyleOne<FormatTypeKey, Format::Type>*>(two)->value1; |
2431 | case FloatFormatKey: |
2432 | return static_cast<const SubStyleOne<FloatFormatKey, FloatFormat>*>(one)->value1 == static_cast<const SubStyleOne<FloatFormatKey, FloatFormat>*>(two)->value1; |
2433 | case FloatColorKey: |
2434 | return static_cast<const SubStyleOne<FloatColorKey, FloatColor>*>(one)->value1 == static_cast<const SubStyleOne<FloatColorKey, FloatColor>*>(two)->value1; |
2435 | case CurrencyFormat: { |
2436 | Currency currencyOne = static_cast<const SubStyleOne<CurrencyFormat, Currency>*>(one)->value1; |
2437 | Currency currencyTwo = static_cast<const SubStyleOne<CurrencyFormat, Currency>*>(two)->value1; |
2438 | if (currencyOne != currencyTwo) |
2439 | return false; |
2440 | return true; |
2441 | } |
2442 | case CustomFormat: |
2443 | return static_cast<const SubStyleOne<CustomFormat, QString>*>(one)->value1 == static_cast<const SubStyleOne<CustomFormat, QString>*>(two)->value1; |
2444 | // background |
2445 | case BackgroundBrush: |
2446 | return static_cast<const SubStyleOne<BackgroundBrush, QBrush>*>(one)->value1 == static_cast<const SubStyleOne<BackgroundBrush, QBrush>*>(two)->value1; |
2447 | case BackgroundColor: |
2448 | return static_cast<const SubStyleOne<BackgroundColor, QColor>*>(one)->value1 == static_cast<const SubStyleOne<BackgroundColor, QColor>*>(two)->value1; |
2449 | // font |
2450 | case FontColor: |
2451 | return static_cast<const SubStyleOne<FontColor, QColor>*>(one)->value1 == static_cast<const SubStyleOne<FontColor, QColor>*>(two)->value1; |
2452 | case FontFamily: |
2453 | return static_cast<const SubStyleOne<FontFamily, QString>*>(one)->value1 == static_cast<const SubStyleOne<FontFamily, QString>*>(two)->value1; |
2454 | case FontSize: |
2455 | return static_cast<const SubStyleOne<FontSize, int>*>(one)->value1 == static_cast<const SubStyleOne<FontSize, int>*>(two)->value1; |
2456 | case FontBold: |
2457 | return static_cast<const SubStyleOne<FontBold, bool>*>(one)->value1 == static_cast<const SubStyleOne<FontBold, bool>*>(two)->value1; |
2458 | case FontItalic: |
2459 | return static_cast<const SubStyleOne<FontItalic, bool>*>(one)->value1 == static_cast<const SubStyleOne<FontItalic, bool>*>(two)->value1; |
2460 | case FontStrike: |
2461 | return static_cast<const SubStyleOne<FontStrike, bool>*>(one)->value1 == static_cast<const SubStyleOne<FontStrike, bool>*>(two)->value1; |
2462 | case FontUnderline: |
2463 | return static_cast<const SubStyleOne<FontUnderline, bool>*>(one)->value1 == static_cast<const SubStyleOne<FontUnderline, bool>*>(two)->value1; |
2464 | //misc |
2465 | case DontPrintText: |
2466 | return static_cast<const SubStyleOne<DontPrintText, bool>*>(one)->value1 == static_cast<const SubStyleOne<DontPrintText, bool>*>(two)->value1; |
2467 | case NotProtected: |
2468 | return static_cast<const SubStyleOne<NotProtected, bool>*>(one)->value1 == static_cast<const SubStyleOne<NotProtected, bool>*>(two)->value1; |
2469 | case HideAll: |
2470 | return static_cast<const SubStyleOne<HideAll, bool>*>(one)->value1 == static_cast<const SubStyleOne<HideAll, bool>*>(two)->value1; |
2471 | case HideFormula: |
2472 | return static_cast<const SubStyleOne<HideFormula, bool>*>(one)->value1 == static_cast<const SubStyleOne<HideFormula, bool>*>(two)->value1; |
2473 | default: |
2474 | return false; |
2475 | } |
2476 | } |
2477 | |
2478 | bool Style::operator==(const Style& other) const |
2479 | { |
2480 | if (other.isEmpty()) |
2481 | return isEmpty() ? true : false; |
2482 | const QSet<Key> keys = QSet<Key>::fromList(d->subStyles.keys() + other.d->subStyles.keys()); |
2483 | const QSet<Key>::ConstIterator end = keys.constEnd(); |
2484 | for (QSet<Key>::ConstIterator it = keys.constBegin(); it != end; ++it) { |
2485 | if (!compare(d->subStyles.value(*it).data(), other.d->subStyles.value(*it).data())) |
2486 | return false; |
2487 | } |
2488 | return true; |
2489 | } |
2490 | |
2491 | uint Calligra::Sheets::qHash(const Style& style) |
2492 | { |
2493 | uint hash = 0; |
2494 | foreach (const SharedSubStyle& ss, style.subStyles()) { |
2495 | hash ^= ss->koHash(); |
2496 | } |
2497 | return hash; |
2498 | } |
2499 | |
2500 | void Style::operator=(const Style & other) |
2501 | { |
2502 | d = other.d; |
2503 | } |
2504 | |
2505 | Style Style::operator-(const Style& other) const |
2506 | { |
2507 | Style style; |
2508 | const QSet<Key> keys = difference(other); |
2509 | const QSet<Key>::ConstIterator end = keys.constEnd(); |
2510 | for (QSet<Key>::ConstIterator it = keys.constBegin(); it != end; ++it) |
2511 | style.insertSubStyle(d->subStyles[*it]); |
2512 | return style; |
2513 | } |
2514 | |
2515 | void Style::merge(const Style& style) |
2516 | { |
2517 | const QList<SharedSubStyle> subStyles(style.subStyles()); |
2518 | // kDebug(36006) <<"merging" << subStyles.count() <<" attributes."; |
2519 | for (int i = 0; i < subStyles.count(); ++i) { |
2520 | // kDebug(36006) << subStyles[i]->debugData(); |
2521 | insertSubStyle(subStyles[i]); |
2522 | } |
2523 | } |
2524 | |
2525 | QSet<Style::Key> Style::difference(const Style& other) const |
2526 | { |
2527 | QSet<Key> result; |
2528 | const QSet<Key> keys = QSet<Key>::fromList(d->subStyles.keys() + other.d->subStyles.keys()); |
2529 | const QSet<Key>::ConstIterator end = keys.constEnd(); |
2530 | for (QSet<Key>::ConstIterator it = keys.constBegin(); it != end; ++it) { |
2531 | if (!other.d->subStyles.contains(*it)) |
2532 | result.insert(*it); |
2533 | else if (d->subStyles.contains(*it)) { // both contain this key |
2534 | if (!compare(d->subStyles.value(*it).data(), other.d->subStyles.value(*it).data())) |
2535 | result.insert(*it); |
2536 | } |
2537 | } |
2538 | return result; |
2539 | } |
2540 | |
2541 | void Style::dump() const |
2542 | { |
2543 | for (int i = 0; i < subStyles().count(); ++i) |
2544 | subStyles()[i]->dump(); |
2545 | } |
2546 | |
2547 | QTextCharFormat Style::asCharFormat() const |
2548 | { |
2549 | QTextCharFormat format; |
2550 | format.setFont(font()); |
2551 | format.setFontWeight(bold() ? QFont::Bold : QFont::Normal); |
2552 | format.setFontItalic(italic()); |
2553 | format.setFontUnderline(underline()); |
2554 | format.setFontStrikeOut(strikeOut()); |
2555 | return format; |
2556 | } |
2557 | |
2558 | |
2559 | QList<SharedSubStyle> Style::subStyles() const |
2560 | { |
2561 | return d->subStyles.values(); |
2562 | } |
2563 | |
2564 | SharedSubStyle Style::createSubStyle(Key key, const QVariant& value) |
2565 | { |
2566 | SharedSubStyle newSubStyle; |
2567 | switch (key) { |
2568 | // special cases |
2569 | case DefaultStyleKey: |
2570 | newSubStyle = new SubStyle(); |
2571 | break; |
2572 | case NamedStyleKey: |
2573 | newSubStyle = new NamedStyle(value.value<QString>()); |
2574 | break; |
2575 | case LeftPen: |
2576 | newSubStyle = new BorderPenStyle<LeftPen>(value.value<QPen>()); |
2577 | break; |
2578 | case RightPen: |
2579 | newSubStyle = new BorderPenStyle<RightPen>(value.value<QPen>()); |
2580 | break; |
2581 | case TopPen: |
2582 | newSubStyle = new BorderPenStyle<TopPen>(value.value<QPen>()); |
2583 | break; |
2584 | case BottomPen: |
2585 | newSubStyle = new BorderPenStyle<BottomPen>(value.value<QPen>()); |
2586 | break; |
2587 | case FallDiagonalPen: |
2588 | newSubStyle = new BorderPenStyle<FallDiagonalPen>(value.value<QPen>()); |
2589 | break; |
2590 | case GoUpDiagonalPen: |
2591 | newSubStyle = new BorderPenStyle<GoUpDiagonalPen>(value.value<QPen>()); |
2592 | break; |
2593 | // layout |
2594 | case HorizontalAlignment: |
2595 | newSubStyle = new SubStyleOne<HorizontalAlignment, HAlign>((HAlign)value.value<int>()); |
2596 | break; |
2597 | case VerticalAlignment: |
2598 | newSubStyle = new SubStyleOne<VerticalAlignment, VAlign>((VAlign)value.value<int>()); |
2599 | break; |
2600 | case MultiRow: |
2601 | newSubStyle = new SubStyleOne<MultiRow, bool>(value.value<bool>()); |
2602 | break; |
2603 | case VerticalText: |
2604 | newSubStyle = new SubStyleOne<VerticalText, bool>(value.value<bool>()); |
2605 | break; |
2606 | case Angle: |
2607 | newSubStyle = new SubStyleOne<Angle, int>(value.value<int>()); |
2608 | break; |
2609 | case Indentation: |
2610 | newSubStyle = new SubStyleOne<Indentation, int>(value.value<int>()); |
2611 | break; |
2612 | case ShrinkToFit: |
2613 | newSubStyle = new SubStyleOne<ShrinkToFit,bool>(value.value<bool>()); |
2614 | break; |
2615 | // content format |
2616 | case Prefix: |
2617 | newSubStyle = new SubStyleOne<Prefix, QString>(value.value<QString>()); |
2618 | break; |
2619 | case Postfix: |
2620 | newSubStyle = new SubStyleOne<Postfix, QString>(value.value<QString>()); |
2621 | break; |
2622 | case Precision: |
2623 | newSubStyle = new SubStyleOne<Precision, int>(value.value<int>()); |
2624 | break; |
2625 | case ThousandsSep: |
2626 | newSubStyle = new SubStyleOne<ThousandsSep, bool>(value.value<bool>()); |
2627 | break; |
2628 | case FormatTypeKey: |
2629 | newSubStyle = new SubStyleOne<FormatTypeKey, Format::Type>((Format::Type)value.value<int>()); |
2630 | break; |
2631 | case FloatFormatKey: |
2632 | newSubStyle = new SubStyleOne<FloatFormatKey, FloatFormat>((FloatFormat)value.value<int>()); |
2633 | break; |
2634 | case FloatColorKey: |
2635 | newSubStyle = new SubStyleOne<FloatColorKey, FloatColor>((FloatColor)value.value<int>()); |
2636 | break; |
2637 | case CurrencyFormat: |
2638 | newSubStyle = new SubStyleOne<CurrencyFormat, Currency>(value.value<Currency>()); |
2639 | break; |
2640 | case CustomFormat: |
2641 | newSubStyle = new SubStyleOne<CustomFormat, QString>(value.value<QString>()); |
2642 | break; |
2643 | // background |
2644 | case BackgroundBrush: |
2645 | newSubStyle = new SubStyleOne<BackgroundBrush, QBrush>(value.value<QBrush>()); |
2646 | break; |
2647 | case BackgroundColor: |
2648 | newSubStyle = new SubStyleOne<BackgroundColor, QColor>(value.value<QColor>()); |
2649 | break; |
2650 | // font |
2651 | case FontColor: |
2652 | newSubStyle = new SubStyleOne<FontColor, QColor>(value.value<QColor>()); |
2653 | break; |
2654 | case FontFamily: |
2655 | newSubStyle = new SubStyleOne<FontFamily, QString>(value.value<QString>()); |
2656 | break; |
2657 | case FontSize: |
2658 | newSubStyle = new SubStyleOne<FontSize, int>(value.value<int>()); |
2659 | break; |
2660 | case FontBold: |
2661 | newSubStyle = new SubStyleOne<FontBold, bool>(value.value<bool>()); |
2662 | break; |
2663 | case FontItalic: |
2664 | newSubStyle = new SubStyleOne<FontItalic, bool>(value.value<bool>()); |
2665 | break; |
2666 | case FontStrike: |
2667 | newSubStyle = new SubStyleOne<FontStrike, bool>(value.value<bool>()); |
2668 | break; |
2669 | case FontUnderline: |
2670 | newSubStyle = new SubStyleOne<FontUnderline, bool>(value.value<bool>()); |
2671 | break; |
2672 | //misc |
2673 | case DontPrintText: |
2674 | newSubStyle = new SubStyleOne<DontPrintText, bool>(value.value<bool>()); |
2675 | break; |
2676 | case NotProtected: |
2677 | newSubStyle = new SubStyleOne<NotProtected, bool>(value.value<bool>()); |
2678 | break; |
2679 | case HideAll: |
2680 | newSubStyle = new SubStyleOne<HideAll, bool>(value.value<bool>()); |
2681 | break; |
2682 | case HideFormula: |
2683 | newSubStyle = new SubStyleOne<HideFormula, bool>(value.value<bool>()); |
2684 | break; |
2685 | } |
2686 | return newSubStyle; |
2687 | } |
2688 | |
2689 | void Style::insertSubStyle(Key key, const QVariant& value) |
2690 | { |
2691 | const SharedSubStyle subStyle = createSubStyle(key, value); |
2692 | Q_ASSERT(!!subStyle); |
2693 | insertSubStyle(subStyle); |
2694 | } |
2695 | |
2696 | void Style::insertSubStyle(const SharedSubStyle& subStyle) |
2697 | { |
2698 | if (!subStyle) |
2699 | return; |
2700 | releaseSubStyle(subStyle->type()); |
2701 | d->subStyles.insert(subStyle->type(), subStyle); |
2702 | } |
2703 | |
2704 | bool Style::releaseSubStyle(Key key) |
2705 | { |
2706 | if (!d->subStyles.contains(key)) |
2707 | return false; |
2708 | |
2709 | d->subStyles.remove(key); |
2710 | return true; |
2711 | } |
2712 | |
2713 | ///////////////////////////////////////////////////////////////////////////// |
2714 | // |
2715 | // CustomStyle::Private |
2716 | // |
2717 | ///////////////////////////////////////////////////////////////////////////// |
2718 | |
2719 | class CustomStyle::Private : public QSharedData |
2720 | { |
2721 | public: |
2722 | QString name; |
2723 | StyleType type; |
2724 | }; |
2725 | |
2726 | |
2727 | ///////////////////////////////////////////////////////////////////////////// |
2728 | // |
2729 | // CustomStyle |
2730 | // |
2731 | ///////////////////////////////////////////////////////////////////////////// |
2732 | |
2733 | CustomStyle::CustomStyle() |
2734 | : Style() |
2735 | , d(new Private) |
2736 | { |
2737 | d->name = "Default" ; |
2738 | d->type = BUILTIN; |
2739 | setDefault(); |
2740 | } |
2741 | |
2742 | CustomStyle::CustomStyle(QString const & name, CustomStyle * parent) |
2743 | : Style() |
2744 | , d(new Private) |
2745 | { |
2746 | d->name = name; |
2747 | d->type = CUSTOM; |
2748 | if (parent) |
2749 | setParentName(parent->name()); |
2750 | } |
2751 | |
2752 | CustomStyle::CustomStyle(const CustomStyle& style) |
2753 | : Style(style), d(style.d) |
2754 | { |
2755 | } |
2756 | |
2757 | CustomStyle::~CustomStyle() |
2758 | { |
2759 | } |
2760 | |
2761 | CustomStyle& CustomStyle::operator=(const CustomStyle& style) |
2762 | { |
2763 | Style::operator=(style); |
2764 | d = style.d; |
2765 | return *this; |
2766 | } |
2767 | |
2768 | Style::StyleType CustomStyle::type() const |
2769 | { |
2770 | return d->type; |
2771 | } |
2772 | |
2773 | void CustomStyle::setType(StyleType type) |
2774 | { |
2775 | Q_ASSERT(type != AUTO); |
2776 | d->type = type; |
2777 | } |
2778 | |
2779 | const QString& CustomStyle::name() const |
2780 | { |
2781 | return d->name; |
2782 | } |
2783 | |
2784 | void CustomStyle::setName(QString const & name) |
2785 | { |
2786 | d->name = name; |
2787 | } |
2788 | |
2789 | QString CustomStyle::saveOdf(KoGenStyle& style, KoGenStyles &mainStyles, |
2790 | const StyleManager* manager) const |
2791 | { |
2792 | Q_ASSERT(!name().isEmpty()); |
2793 | // default style does not need display name |
2794 | if (!isDefault()) |
2795 | style.addAttribute("style:display-name" , name()); |
2796 | |
2797 | // doing the real work |
2798 | QSet<Key> keysToStore; |
2799 | for (int i = 0; i < subStyles().count(); ++i) |
2800 | keysToStore.insert(subStyles()[i].data()->type()); |
2801 | saveOdfStyle(keysToStore, style, mainStyles, manager); |
2802 | |
2803 | if (isDefault()) { |
2804 | style.setDefaultStyle(true); |
2805 | // don't i18n'ize "Default" in this case |
2806 | return mainStyles.insert(style, "Default" , KoGenStyles::DontAddNumberToName); |
2807 | } |
2808 | |
2809 | // this is a custom style |
2810 | return mainStyles.insert(style, "custom-style" ); |
2811 | } |
2812 | |
2813 | void CustomStyle::loadOdf(KoOdfStylesReader& stylesReader, const KoXmlElement& style, |
2814 | const QString& name, Conditions& conditions, |
2815 | const StyleManager* styleManager, const ValueParser *parser) |
2816 | { |
2817 | setName(name); |
2818 | if (style.hasAttributeNS(KoXmlNS::style, "parent-style-name" )) |
2819 | setParentName(style.attributeNS(KoXmlNS::style, "parent-style-name" , QString())); |
2820 | |
2821 | setType(CUSTOM); |
2822 | |
2823 | Style::loadOdfStyle(stylesReader, style, conditions, styleManager, parser); |
2824 | } |
2825 | |
2826 | void CustomStyle::save(QDomDocument& doc, QDomElement& styles, const StyleManager* styleManager) |
2827 | { |
2828 | if (name().isEmpty()) |
2829 | return; |
2830 | |
2831 | QDomElement style(doc.createElement("style" )); |
2832 | style.setAttribute("type" , (int) type()); |
2833 | if (!parentName().isNull()) |
2834 | style.setAttribute("parent" , parentName()); |
2835 | style.setAttribute("name" , name()); |
2836 | |
2837 | QDomElement format(doc.createElement("format" )); |
2838 | saveXML(doc, format, styleManager); |
2839 | style.appendChild(format); |
2840 | |
2841 | styles.appendChild(style); |
2842 | } |
2843 | |
2844 | bool CustomStyle::loadXML(KoXmlElement const & style, QString const & name) |
2845 | { |
2846 | setName(name); |
2847 | |
2848 | if (style.hasAttribute("parent" )) |
2849 | setParentName(style.attribute("parent" )); |
2850 | |
2851 | if (!style.hasAttribute("type" )) |
2852 | return false; |
2853 | |
2854 | bool ok = true; |
2855 | setType((StyleType) style.attribute("type" ).toInt(&ok)); |
2856 | if (!ok) |
2857 | return false; |
2858 | |
2859 | KoXmlElement f(style.namedItem("format" ).toElement()); |
2860 | if (!f.isNull()) |
2861 | if (!Style::loadXML(f)) |
2862 | return false; |
2863 | |
2864 | return true; |
2865 | } |
2866 | |
2867 | int CustomStyle::usage() const |
2868 | { |
2869 | return d->ref; |
2870 | } |
2871 | |