1 /* This file is part of the KDE project
2  * Copyright (C) 2006-2010 Thomas Zander <zander@kde.org>
3  * Copyright (C) 2008 Girish Ramakrishnan <girish@forwardbias.in>
4  * Copyright (C) 2010 Nandita Suri <suri.nandita@gmail.com>
5  * Copyright (C) 2011 Lukáš Tvrdý <lukas.tvrdy@ixonos.com>
6  * Copyright (C) 2011-2012 Gopalakrishna Bhat A <gopalakbhat@gmail.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 #ifndef KOLISTSTYLE_H
24 #define KOLISTSTYLE_H
25 
26 #include "kritatext_export.h"
27 
28 #include <QTextFormat>
29 #include <QTextListFormat>
30 
31 #include <KoXmlReader.h>
32 
33 class KoListLevelProperties;
34 class KoShapeLoadingContext;
35 class KoShapeSavingContext;
36 class KoGenStyle;
37 
38 class QTextBlock;
39 
40 /**
41  * This class groups all styling-options for lists.
42  * See KoParagraphStyle::setListStyle()
43  * The list-style represents several list-levels, where each level is represented by the
44  * KoListLevelProperties class. The top most list level is 1.
45  *
46  * list level1
47  *   list level2
48  *   list level2
49  *     list level3
50  * list level1
51  *
52  * A list-style as such represents cross paragraph relations. The most obvious evidence of this
53  * is with a numbered list where a counter is automatically increased from one paragraph to the next.
54  *
55  * If the list is interrupted by a praragraph with another list-style the counting will start from
56  * fresh when the list resumes. However you can set the list to continue if you like.
57  *
58  * Following from the above you can use the same paragraph style for several paragraphs and the
59  * the counter will increase. If you want a paragraph to be on a sub level you do however need to
60  * create a new paragraph-style when another listLevel set.
61  */
62 class  KRITATEXT_EXPORT KoListStyle : public QObject
63 {
64     Q_OBJECT
65     Q_ENUMS(Style Property)
66 public:
67     // ListIdType will be 32-bit in 32 bit machines and 64 bit in 64 bit machines
68     typedef quintptr ListIdType;
69 
70     /// This list is used to specify what kind of list-style to use
71     /// If you add a style to that list you also need to check if you need to update
72     /// KoListStyle::isNumberingStyle(int)
73     enum Style {
74         /// Draw a square
75         SquareItem = QTextListFormat::ListSquare,
76         /// Draw a disc (filled circle)  (aka bullet)
77         DiscItem = QTextListFormat::ListDisc,
78         /// Draw a disc (non-filled disk)
79         CircleItem = QTextListFormat::ListCircle,
80         /// use arabic numbering (1, 2, 3, ...)
81         DecimalItem = QTextListFormat::ListDecimal,
82         /// use alpha numbering (a, b, c, ... aa, ab, ...)
83         AlphaLowerItem = QTextListFormat::ListLowerAlpha,
84         /// use alpha numbering (A, B, C, ... AA, AB, ...)
85         UpperAlphaItem = QTextListFormat::ListUpperAlpha,
86         /// List style with no numbering
87         None = 1,
88         /// use lower roman counting.  (i, ii, iii, iv, ...)
89         RomanLowerItem,
90         /// use upper roman counting.  (I, II, III, IV, ...)
91         UpperRomanItem,
92         /// bullet, a small circle Unicode char U+2022
93         Bullet,
94         /// black circle, a large circle Unicode char U+25CF
95         BlackCircle,
96         /// draw a box
97         BoxItem,
98         /// rhombus, like a SquareItem but rotated by 45 degree
99         RhombusItem,
100         /// a check mark
101         HeavyCheckMarkItem,
102         /// a ballot x
103         BallotXItem,
104         /// heavy wide-headed rightwards arrow
105         RightArrowItem,
106         /// three-d top-lighted rightwards arrowhead
107         RightArrowHeadItem,
108         /// use an unicode char for the bullet
109         CustomCharItem,
110         Bengali,    ///< Bengali characters for normal 10-base counting
111         Gujarati,   ///< Gujarati characters for normal 10-base counting
112         Gurumukhi,  ///< Gurumukhi characters for normal 10-base counting
113         Kannada,    ///< Kannada characters for normal 10-base counting
114         Malayalam,  ///< Malayalam characters for normal 10-base counting
115         Oriya,      ///< Oriya characters for normal 10-base counting
116         Tamil,      ///< Tamil characters for normal 10-base counting
117         Telugu,     ///< Telugu characters for normal 10-base counting
118         Tibetan,    ///< Tibetan characters for normal 10-base counting
119         Thai,       ///< Thai characters for normal 10-base counting
120         Abjad,      ///< Abjad sequence.
121         AbjadMinor, ///< A lesser known version of the Abjad sequence.
122         ArabicAlphabet, ///< Arabic alphabet.
123         /// an image for the bullet
124         ImageItem
125 
126         // TODO look at css 3 for things like hebrew counters
127     };
128 
129     /// further properties
130     enum Property {
131         ListItemPrefix = QTextFormat::UserProperty + 1000, ///< The text to be printed before the listItem
132         ListItemSuffix, ///< The text to be printed after the listItem
133         StartValue,     ///< First value to use
134         Level,          ///< list nesting level, is 1 or higher, or zero when implied
135         DisplayLevel,   ///< show this many levels. Is always lower than the (implied) level.
136         CharacterStyleId,///< CharacterStyle used for markup of the counter
137         CharacterProperties, ///< This stores the character properties of the list style
138         BulletCharacter,///< an int with the unicode value of the character (for CustomCharItem)
139         RelativeBulletSize,     ///< size in percent relative to the height of the text
140         Alignment,      ///< Alignment of the counter
141         MinimumWidth,   ///< The minimum width, in pt, of the listItem including the prefix/suffix.
142         ListId,         ///< A group of lists together are called 1 (user intended) list in ODF. Store the listId here
143         IsOutline,      ///< If true then this list is an outline list (for header paragraphs)
144         LetterSynchronization, ///< If letters are used for numbering, when true increment all at the same time. (aa, bb)
145         StyleId,        ///< The id stored in the listFormat to link the list to this style.
146         Indent,         ///< The space (margin) to include for all paragraphs
147         MinimumDistance, ///< The minimum distance, in pt, between the counter and the text
148         Width,          ///< The width, in pt, of  a picture bullet.
149         Height,         ///< The height, in pt, of a picture bullet.
150         BulletImage,    ///< Bullet image stored as a key for lookup in the imageCollection
151         Margin,         ///< Stores the margin of the list
152         TextIndent,     ///< Stores the text indent of list item
153         AlignmentMode,   ///< Is true if list-level-position-and-space-mode=label-alignment
154         LabelFollowedBy,  ///< Label followed by one of the enums ListLabelFollowedBy
155         TabStopPosition   ///< Specifies the additional tab stops
156     };
157 
158     enum ListLabelFollowedBy
159     {
160         ListTab,  ///< Label is followed by a list tab
161         Space,    ///< Label followed by a Space
162         Nothing      ///< Nothing is present between label and the text
163     };
164 
165     /**
166      * Constructor
167      * Create a new list style which uses numbered (KoListStyle::ListDecimal) listitems.
168      */
169     explicit KoListStyle(QObject *parent = 0);
170 
171     /// Destructor
172     ~KoListStyle() override;
173 
174     /// creates a clone of this style with the specified parent
175     KoListStyle *clone(QObject *parent = 0);
176 
177     /// each style has a unique ID (non persistent) given out by the styleManager
178     int styleId() const;
179 
180     /// each style has a unique ID (non persistent) given out by the styleManager
181     void setStyleId(int id);
182 
183     /**
184      * Return the properties for the specified list level.
185      * A list style can contain properties for more than one level, when a paragraph is added to this list
186      * it will be added at a certain level and it will then be using the properties of that level.
187      * The gain from using one list style for multiple levels is in allowing a way to format the list label.
188      * A list item which is of level '4' will be able to have a display level of up to 4, which means that not
189      * only is the counter of the current level displayed, the counters of the higher levels can be displayed as
190      * well.
191      * Adding level properties for lower levels will have the effect that the counter of that level will be displayed
192      * in the specified format instead of being inherited from the list style at the higher level.
193      */
194     KoListLevelProperties levelProperties(int level) const;
195 
196     /**
197      * Set the properties for a level.
198      * @param properties the new properties for the level, including the level number.
199      * @see level()
200      */
201     void setLevelProperties(const KoListLevelProperties &properties);
202 
203     /**
204      * @return if there are the properties for a level set.
205      * @param level the level for which to check
206      * @see level()
207      */
208     bool hasLevelProperties(int level) const;
209 
210     /**
211      * Remove any properties that were set for a level.
212      * @param level the level for which to remove
213      * @see level()
214      */
215     void removeLevelProperties(int level);
216 
217     /// return a QTextListFormat that contains formatting information for the level.
218     QTextListFormat listFormat(int level) const;
219 
220     /// return the configured list levels that hasLevelProperties would return true to.
221     QList<int> listLevels() const;
222 
223     /// return the name of the style.
224     QString name() const;
225 
226     /// set a user-visible name on the style.
227     void setName(const QString &name);
228 
229     /**
230      * Apply this style to a block by adding the block to the proper list.
231      */
232     void applyStyle(const QTextBlock &block, int level = 0);
233 
234     bool operator==(const KoListStyle &other) const;
235     bool operator!=(const KoListStyle &other) const;
236 
237     /**
238      * Load the style from the \a KoStyleStack style stack using the
239      * OpenDocument format.
240      */
241     void loadOdf(KoShapeLoadingContext& context, const KoXmlElement& style = KoXmlElement());
242 
243     /**
244      * Save the style to a KoGenStyle object using the OpenDocument format
245      */
246     void saveOdf(KoGenStyle &style, KoShapeSavingContext &context) const;
247 
248     /// copy all the properties from the other style to this style, effectively duplicating it.
249     void copyProperties(KoListStyle *other);
250 
251     /**
252      * Check if list has numbering in one of it's list levels
253      */
254     bool isNumberingStyle() const;
255 
256     /**
257      * Returns true if this list style is a outline style
258      */
259     bool isOulineStyle() const;
260 
261     /// returns true if style is a numbering style
262     static bool isNumberingStyle(int style);
263 
264     static int bulletCharacter(int style);
265 Q_SIGNALS:
266     void nameChanged(const QString &newName);
267     void styleChanged(int level);
268 
269 private:
270     friend class ChangeListCommand;
271     friend class ChangeListLevelCommand;
272 
273     void refreshLevelProperties(const KoListLevelProperties &properties);
274 
275     class Private;
276     Private * const d;
277 };
278 
279 Q_DECLARE_METATYPE(KoListStyle *)
280 
281 #endif
282