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