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 | #ifndef CALLIGRA_SHEETS_STYLE |
23 | #define CALLIGRA_SHEETS_STYLE |
24 | |
25 | #include <QFont> |
26 | #include <QSharedDataPointer> |
27 | #include <QTextCharFormat> |
28 | |
29 | #include <KoXmlReader.h> |
30 | |
31 | #include "Currency.h" |
32 | #include "Format.h" |
33 | #include "Global.h" |
34 | |
35 | class KoGenStyle; |
36 | class KoGenStyles; |
37 | class KoOdfStylesReader; |
38 | class KoStyleStack; |
39 | |
40 | namespace Calligra |
41 | { |
42 | namespace Sheets |
43 | { |
44 | class Conditions; |
45 | class CustomStyle; |
46 | class SharedSubStyle; |
47 | class Style; |
48 | class StyleManager; |
49 | class StyleManipulator; |
50 | class SubStyle; |
51 | class ValueParser; |
52 | |
53 | // used for preloading OASIS auto styles |
54 | typedef QHash<QString, Style> Styles; |
55 | // needs to be ordered (QMap) for the style dialog |
56 | typedef QMap<QString, CustomStyle*> CustomStyles; |
57 | |
58 | CALLIGRA_SHEETS_ODF_EXPORT uint qHash(const Style& style); |
59 | |
60 | /** |
61 | * \ingroup Style |
62 | * A cell style. |
63 | */ |
64 | class CALLIGRA_SHEETS_ODF_EXPORT Style |
65 | { |
66 | public: |
67 | enum HAlign { |
68 | Left = 1, |
69 | Center = 2, |
70 | Right = 3, |
71 | Justified = 4, |
72 | HAlignUndefined = 0 |
73 | }; |
74 | |
75 | enum VAlign { |
76 | Top = 1, |
77 | Middle = 2, |
78 | Bottom = 3, |
79 | VDistributed = 4, |
80 | VJustified = 5, |
81 | VAlignUndefined = 0 |
82 | }; |
83 | |
84 | enum FloatFormat { |
85 | DefaultFloatFormat = 0, |
86 | AlwaysSigned = 1, |
87 | AlwaysUnsigned = 2, |
88 | OnlyNegSigned = DefaultFloatFormat |
89 | }; |
90 | |
91 | enum FloatColor { |
92 | DefaultFloatColor = 0, |
93 | NegRed = 1, |
94 | AllBlack = DefaultFloatColor, |
95 | NegBrackets = 3, |
96 | NegRedBrackets = 4 |
97 | }; |
98 | |
99 | /// The style type |
100 | enum StyleType { |
101 | BUILTIN, ///< built-in style (the default style) |
102 | CUSTOM, ///< custom style (defined in the StyleManager dialog) |
103 | AUTO, ///< automatically generated on cell format changes |
104 | TENTATIVE ///< @internal temporary state |
105 | }; |
106 | |
107 | enum Key { |
108 | // special cases |
109 | DefaultStyleKey, |
110 | /** |
111 | * The NamedStyleKey has two functions: |
112 | * \li In Style: On lookup the Style is composed (\see StyleStorage::composeStyle()). |
113 | * For named styles just the style's name is stored. On lookup, these styles |
114 | * are looked up in the StyleManager and their attributes, including all |
115 | * attributes of the parents, are filled in the composed style. Additionally, |
116 | * the name of the named style is stored in the NamedStyleKey attribute. |
117 | * This is especially useful while saving the styles. |
118 | * \li In CustomStyle: It simply refers to the parent style. |
119 | */ |
120 | NamedStyleKey, |
121 | // borders |
122 | LeftPen, |
123 | RightPen, |
124 | TopPen, |
125 | BottomPen, |
126 | FallDiagonalPen, |
127 | GoUpDiagonalPen, |
128 | // layout |
129 | HorizontalAlignment, |
130 | VerticalAlignment, |
131 | MultiRow, |
132 | VerticalText, |
133 | Angle, |
134 | ShrinkToFit, |
135 | Indentation, |
136 | // content format |
137 | Prefix, |
138 | Postfix, |
139 | Precision, |
140 | ThousandsSep, |
141 | FormatTypeKey, |
142 | FloatFormatKey, |
143 | FloatColorKey, |
144 | CurrencyFormat, |
145 | CustomFormat, |
146 | // background |
147 | BackgroundBrush, |
148 | BackgroundColor, |
149 | // font |
150 | FontColor, |
151 | FontFamily, |
152 | FontSize, |
153 | FontBold, |
154 | FontItalic, |
155 | FontStrike, |
156 | FontUnderline, |
157 | //misc |
158 | DontPrintText, |
159 | NotProtected, |
160 | HideAll, |
161 | HideFormula |
162 | }; |
163 | |
164 | Style(); |
165 | Style(const Style& style); |
166 | virtual ~Style(); |
167 | |
168 | virtual StyleType type() const; |
169 | |
170 | QString parentName() const; |
171 | void setParentName(const QString& name); |
172 | |
173 | |
174 | bool loadXML(KoXmlElement& format, Paste::Mode pm = Paste::Normal); |
175 | void saveXML(QDomDocument& doc, QDomElement& format, const StyleManager* styleManager) const; |
176 | void loadOdfStyle(KoOdfStylesReader& stylesReader, const KoXmlElement& element, |
177 | Conditions& conditions, const StyleManager* styleManager, |
178 | const ValueParser *parser); |
179 | void loadOdfDataStyle(KoOdfStylesReader& stylesReader, const QString& dataStyleName, |
180 | Conditions& conditions, const StyleManager* styleManager, |
181 | const ValueParser *parser); |
182 | |
183 | /** |
184 | * Saves an OASIS automatic style. |
185 | * Reimplemented by CustomStyle for OASIS user styles. |
186 | * \return the OASIS style's name |
187 | */ |
188 | virtual QString saveOdf(KoGenStyle& style, KoGenStyles& mainStyles, |
189 | const StyleManager* manager) const; |
190 | |
191 | |
192 | void clearAttribute(Key key); |
193 | bool hasAttribute(Key key) const; |
194 | void loadAttributes(const QList<SharedSubStyle>& subStyles); |
195 | |
196 | |
197 | uint bottomPenValue() const; |
198 | uint rightPenValue() const; |
199 | uint leftPenValue() const; |
200 | uint topPenValue() const; |
201 | |
202 | QColor fontColor() const; |
203 | QColor backgroundColor() const; |
204 | QPen rightBorderPen() const; |
205 | QPen bottomBorderPen() const; |
206 | QPen leftBorderPen() const; |
207 | QPen topBorderPen() const; |
208 | QPen fallDiagonalPen() const; |
209 | QPen goUpDiagonalPen() const; |
210 | QBrush backgroundBrush() const; |
211 | QString customFormat() const; |
212 | QString prefix() const; |
213 | QString postfix() const; |
214 | QString fontFamily() const; |
215 | |
216 | HAlign halign() const; |
217 | VAlign valign() const; |
218 | FloatFormat floatFormat() const; |
219 | FloatColor floatColor() const; |
220 | Format::Type formatType() const; |
221 | |
222 | Currency currency() const; |
223 | |
224 | QFont font() const; |
225 | bool bold() const; |
226 | bool italic() const; |
227 | bool underline() const; |
228 | bool strikeOut() const; |
229 | uint fontFlags() const; |
230 | int fontSize() const; |
231 | int precision() const; |
232 | bool thousandsSep() const; |
233 | int angle() const; |
234 | double indentation() const; |
235 | bool shrinkToFit() const; |
236 | bool verticalText() const; |
237 | bool wrapText() const; |
238 | bool printText() const; |
239 | bool hideAll() const; |
240 | bool hideFormula() const; |
241 | bool notProtected() const; |
242 | bool isDefault() const; |
243 | bool isEmpty() const; |
244 | |
245 | protected: |
246 | /** |
247 | * Helper function for saveOdf |
248 | * Does the real work by determining the used attributes. |
249 | */ |
250 | void saveOdfStyle(const QSet<Key>& subStyles, KoGenStyle &style, |
251 | KoGenStyles &mainStyles, const StyleManager* manager) const; |
252 | |
253 | void loadOdfDataStyle(KoOdfStylesReader& stylesReader, const KoXmlElement& element, |
254 | Conditions& conditions, const StyleManager* styleManager, |
255 | const ValueParser *parser); |
256 | void loadOdfParagraphProperties(KoOdfStylesReader& stylesReader, const KoStyleStack& element); |
257 | void loadOdfTableCellProperties(KoOdfStylesReader& stylesReader, const KoStyleStack& element); |
258 | void loadOdfTextProperties(KoOdfStylesReader& stylesReader, const KoStyleStack& element); |
259 | |
260 | public: |
261 | void setHAlign(HAlign align); |
262 | void setVAlign(VAlign align); |
263 | void setFont(QFont const & font); |
264 | void setFontFamily(QString const & fam); |
265 | void setFontBold(bool enable); |
266 | void setFontItalic(bool enable); |
267 | void setFontUnderline(bool enable); |
268 | void setFontStrikeOut(bool enable); |
269 | void setFontSize(int size); |
270 | void setFontColor(QColor const & color); |
271 | void setRightBorderPen(QPen const & pen); |
272 | void setBottomBorderPen(QPen const & pen); |
273 | void setLeftBorderPen(QPen const & pen); |
274 | void setTopBorderPen(QPen const & pen); |
275 | void setFallDiagonalPen(QPen const & pen); |
276 | void setGoUpDiagonalPen(QPen const & pen); |
277 | void setAngle(int angle); |
278 | void setIndentation(double indent); |
279 | void setBackgroundBrush(QBrush const & brush); |
280 | void setFloatFormat(FloatFormat format); |
281 | void setFloatColor(FloatColor color); |
282 | void setFormatType(Format::Type format); |
283 | void setCustomFormat(QString const & strFormat); |
284 | void setPrecision(int precision); |
285 | void setThousandsSep(bool thousandsSep); |
286 | void setPrefix(QString const & prefix); |
287 | void setPostfix(QString const & postfix); |
288 | void setCurrency(Currency const & currency); |
289 | void setWrapText(bool enable); |
290 | void setHideAll(bool enable); |
291 | void setHideFormula(bool enable); |
292 | void setNotProtected(bool enable); |
293 | void setDontPrintText(bool enable); |
294 | void setVerticalText(bool enable); |
295 | void setShrinkToFit(bool enable); |
296 | void setBackgroundColor(QColor const & color); |
297 | void setDefault(); |
298 | void clear(); |
299 | |
300 | |
301 | // static functions |
302 | // |
303 | static Format::Type dateType(const QString&); |
304 | static Format::Type timeType(const QString&); |
305 | static Format::Type fractionType(const QString&); |
306 | static Format::Type numberType(const QString&); |
307 | static Currency numberCurrency(const QString&); |
308 | |
309 | /** |
310 | * @return the name of the data style (number, currency, percentage, date, |
311 | * boolean, text) |
312 | */ |
313 | static QString saveOdfStyleNumeric(KoGenStyle &style, KoGenStyles &mainStyles, Format::Type _style, |
314 | const QString &_prefix, const QString &_postfix, int _precision, const QString& symbol, |
315 | bool thousandsSep); |
316 | static QString saveOdfStyleNumericDate(KoGenStyles &mainStyles, Format::Type _style, |
317 | const QString &_prefix, const QString &_suffix); |
318 | static QString saveOdfStyleNumericFraction(KoGenStyles &mainStyles, Format::Type _style, |
319 | const QString &_prefix, const QString &_suffix); |
320 | static QString saveOdfStyleNumericTime(KoGenStyles& mainStyles, Format::Type _style, |
321 | const QString &_prefix, const QString &_suffix); |
322 | static QString saveOdfStyleNumericCustom(KoGenStyles&mainStyles, Format::Type _style, |
323 | const QString &_prefix, const QString &_suffix); |
324 | static QString saveOdfStyleNumericScientific(KoGenStyles&mainStyles, Format::Type _style, |
325 | const QString &_prefix, const QString &_suffix, int _precision, bool thousandsSep); |
326 | static QString saveOdfStyleNumericPercentage(KoGenStyles&mainStyles, Format::Type _style, int _precision, |
327 | const QString &_prefix, const QString &_suffix); |
328 | static QString saveOdfStyleNumericMoney(KoGenStyles&mainStyles, Format::Type _style, |
329 | const QString& symbol, int _precision, |
330 | const QString &_prefix, const QString &_suffix); |
331 | static QString saveOdfStyleNumericText(KoGenStyles&mainStyles, Format::Type _style, int _precision, |
332 | const QString &_prefix, const QString &_suffix); |
333 | static QString saveOdfStyleNumericNumber(KoGenStyles&mainStyles, Format::Type _style, int _precision, |
334 | const QString &_prefix, const QString &_suffix, bool thousandsSep); |
335 | static QString saveOdfBackgroundStyle(KoGenStyles &mainStyles, const QBrush &brush); |
336 | |
337 | /** |
338 | * Returns the name of a color. This is the same as returned by QColor::name, but an internal cache |
339 | * is used to reduce the overhead when asking for the name of the same color. |
340 | */ |
341 | static QString colorName(const QColor& color); |
342 | |
343 | static bool compare(const SubStyle* one, const SubStyle* two); |
344 | |
345 | |
346 | /** Returns true if both styles have the same properties */ |
347 | bool operator== (const Style& style) const; |
348 | inline bool operator!=(const Style& other) const { |
349 | return !operator==(other); |
350 | } |
351 | friend CALLIGRA_SHEETS_ODF_EXPORT uint qHash(const Style& style); |
352 | void operator=(const Style& style); |
353 | Style operator-(const Style& style) const; |
354 | void merge(const Style& style); |
355 | |
356 | /** |
357 | * The keys, that are contained in this style, but not in \p other and |
358 | * the keys, that are contained in both but differ in value. |
359 | * \return a set of keys, in which this style and \p other differ. |
360 | */ |
361 | QSet<Key> difference(const Style& other) const; |
362 | |
363 | void dump() const; |
364 | |
365 | /** |
366 | * Return the properties of this style that can be represented as a QTextCharFormat |
367 | */ |
368 | QTextCharFormat asCharFormat() const; |
369 | protected: |
370 | QList<SharedSubStyle> subStyles() const; |
371 | |
372 | SharedSubStyle createSubStyle(Key key, const QVariant& value); |
373 | virtual void insertSubStyle(Key key, const QVariant& value); |
374 | void insertSubStyle(const SharedSubStyle& subStyle); |
375 | bool releaseSubStyle(Key key); |
376 | |
377 | private: |
378 | friend class StyleStorage; |
379 | friend class StyleStorageLoaderJob; |
380 | friend class BorderColorCommand; |
381 | |
382 | class Private; |
383 | QSharedDataPointer<Private> d; |
384 | }; |
385 | |
386 | |
387 | |
388 | /** |
389 | * \ingroup Style |
390 | * A named cell style. |
391 | */ |
392 | class CALLIGRA_SHEETS_ODF_EXPORT CustomStyle : public Style |
393 | { |
394 | public: |
395 | /** |
396 | * Constructor. |
397 | * Creates a custom style. |
398 | * \param name The name of this style. |
399 | * \param parent The style whose attributes are inherited - the parent style. |
400 | */ |
401 | explicit CustomStyle(const QString& name, CustomStyle* parent = 0); |
402 | CustomStyle(const CustomStyle& style); |
403 | virtual ~CustomStyle(); |
404 | CustomStyle& operator=(const CustomStyle& other); |
405 | |
406 | virtual StyleType type() const; |
407 | void setType(StyleType type); |
408 | |
409 | void setName(QString const & name); |
410 | QString const & name() const; |
411 | |
412 | bool loadXML(KoXmlElement const & style, QString const & name); |
413 | void save(QDomDocument & doc, QDomElement & styles, const StyleManager* styleManager); |
414 | |
415 | /** |
416 | * Loads the style properties from @p style . |
417 | * Determines also the parent's name. |
418 | * @param stylesReader map of all styles |
419 | * @param style the DOM element defining the style |
420 | * @param name the style's new name |
421 | */ |
422 | void loadOdf(KoOdfStylesReader& stylesReader, const KoXmlElement& style, |
423 | const QString& name, Conditions& conditions, |
424 | const StyleManager* styleManager, const ValueParser *parser); |
425 | |
426 | /** |
427 | * @reimp |
428 | * Stores an OASIS user style. |
429 | * @return the OASIS style's name |
430 | */ |
431 | virtual QString saveOdf(KoGenStyle& style, KoGenStyles &mainStyles, |
432 | const StyleManager* manager) const; |
433 | |
434 | |
435 | //bool operator==(const CustomStyle& other) const; |
436 | //inline bool operator!=(const CustomStyle& other) const { |
437 | // return !operator==(other); |
438 | //} |
439 | |
440 | /** |
441 | * @return the number of references to this style. |
442 | */ |
443 | int usage() const; |
444 | |
445 | private: |
446 | friend class StyleManager; |
447 | |
448 | /** |
449 | * Constructor. |
450 | * Constructs the default cell style. |
451 | */ |
452 | CustomStyle(); |
453 | |
454 | class Private; |
455 | QSharedDataPointer<Private> d; |
456 | }; |
457 | |
458 | |
459 | /** |
460 | * \ingroup Style |
461 | * A single style attribute. |
462 | */ |
463 | class CALLIGRA_SHEETS_ODF_TEST_EXPORT SubStyle : public QSharedData |
464 | { |
465 | public: |
466 | SubStyle() {} |
467 | virtual ~SubStyle() {} |
468 | virtual Style::Key type() const { |
469 | return Style::DefaultStyleKey; |
470 | } |
471 | virtual void dump() const { |
472 | kDebug() << debugData(); |
473 | } |
474 | virtual QString debugData(bool withName = true) const { |
475 | QString out; if (withName) out = name(Style::DefaultStyleKey); return out; |
476 | } |
477 | virtual uint koHash() const { return uint(type()); } |
478 | static QString name(Style::Key key); |
479 | }; |
480 | |
481 | // Provides a default SubStyle for the tree. |
482 | // Otherwise, we would have QSharedDataPointer<SubStyle>() as default, |
483 | // which has a null pointer and crashes. |
484 | // Also, this makes the code more readable: |
485 | // QSharedDataPointer<SubStyle> vs. SharedSubStyle |
486 | class SharedSubStyle |
487 | { |
488 | public: |
489 | inline SharedSubStyle() : d(s_defaultStyle.d){} |
490 | inline SharedSubStyle(SubStyle* subStyle) : d(subStyle) {} |
491 | inline const SubStyle *operator->() const { |
492 | return d.data(); |
493 | } |
494 | inline const SubStyle *data() const { |
495 | return d.data(); |
496 | } |
497 | inline bool operator<(const SharedSubStyle& o) const { |
498 | return d.data() < o.d.data(); |
499 | } |
500 | inline bool operator==(const SharedSubStyle& o) const { |
501 | return d.data() == o.d.data(); |
502 | } |
503 | inline bool operator!() const { |
504 | return !d; |
505 | } |
506 | |
507 | private: |
508 | QSharedDataPointer<SubStyle> d; |
509 | static SharedSubStyle s_defaultStyle; |
510 | }; |
511 | |
512 | class NamedStyle : public SubStyle |
513 | { |
514 | public: |
515 | NamedStyle(const QString& n) : SubStyle(), name(n) {} |
516 | virtual Style::Key type() const { |
517 | return Style::NamedStyleKey; |
518 | } |
519 | virtual void dump() const { |
520 | kDebug() << debugData(); |
521 | } |
522 | virtual QString debugData(bool withName = true) const { |
523 | QString out; if (withName) out = SubStyle::name(Style::NamedStyleKey) + ' '; out += name; return out; |
524 | } |
525 | virtual uint koHash() const { return uint(type()) ^ qHash(name); } |
526 | QString name; |
527 | }; |
528 | |
529 | |
530 | static inline uint qHash(const QColor& color) |
531 | { return uint(color.rgb()); } |
532 | |
533 | static inline uint qHash(const QPen& pen) |
534 | { return qHash(pen.color()) ^ 37 * uint(pen.style()); } |
535 | |
536 | static inline uint qHash(const QBrush& brush) |
537 | { return qHash(brush.color()) ^ 91 * uint(brush.style()); } |
538 | |
539 | template<Style::Key key, class Value1> |
540 | class SubStyleOne : public SubStyle |
541 | { |
542 | public: |
543 | SubStyleOne(const Value1& v = Value1()) : SubStyle(), value1(v) {} |
544 | virtual Style::Key type() const { |
545 | return key; |
546 | } |
547 | virtual void dump() const { |
548 | kDebug(36006) << debugData(); |
549 | } |
550 | virtual QString debugData(bool withName = true) const { |
551 | QString out; if (withName) out = name(key) + ' '; QDebug qdbg(&out); qdbg << value1; return out; |
552 | } |
553 | virtual uint koHash() const { return uint(type()) ^ qHash(value1); } |
554 | Value1 value1; |
555 | }; |
556 | |
557 | } // namespace Sheets |
558 | } // namespace Calligra |
559 | |
560 | Q_DECLARE_TYPEINFO(Calligra::Sheets::Style, Q_MOVABLE_TYPE); |
561 | Q_DECLARE_TYPEINFO(Calligra::Sheets::CustomStyle, Q_MOVABLE_TYPE); |
562 | Q_DECLARE_TYPEINFO(Calligra::Sheets::SharedSubStyle, Q_MOVABLE_TYPE); |
563 | |
564 | #endif // CALLIGRA_SHEETS_STYLE |
565 | |