Get started with patching up the Qt GUI docs
[profile/ivi/qtbase.git] / src / gui / text / qtextlist.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include "qtextlist.h"
44 #include "qtextobject_p.h"
45 #include "qtextcursor.h"
46 #include "qtextdocument_p.h"
47 #include <qdebug.h>
48
49 QT_BEGIN_NAMESPACE
50
51 class QTextListPrivate : public QTextBlockGroupPrivate
52 {
53 public:
54     QTextListPrivate(QTextDocument *doc)
55         : QTextBlockGroupPrivate(doc)
56     {
57     }
58 };
59
60 /*!
61     \class QTextList
62     \reentrant
63
64     \brief The QTextList class provides a decorated list of items in a QTextDocument.
65     \inmodule QtGui
66
67     \ingroup richtext-processing
68
69     A list contains a sequence of text blocks, each of which is marked with a
70     bullet point or other symbol. Multiple levels of lists can be used, and
71     the automatic numbering feature provides support for ordered numeric and
72     alphabetical lists.
73
74     Lists are created by using a text cursor to insert an empty list at the
75     current position or by moving existing text into a new list.
76     The \l{QTextCursor::insertList()} function inserts an empty block into the
77     document at the cursor position, and makes it the first item in a list.
78
79     \snippet textdocument-lists/mainwindow.cpp 0
80
81     The \l{QTextCursor::createList()} function takes the contents of the
82     cursor's current block and turns it into the first item of a new list.
83
84     The cursor's current list is found with \l{QTextCursor::currentList()}.
85
86     The number of items in a list is given by count(). Each item can be
87     obtained by its index in the list with the item() function. Similarly,
88     the index of a given item can be found with itemNumber(). The text of
89     each item can be found with the itemText() function.
90
91     Note that the items in the list may not be adjacent elements in the
92     document. For example, the top-level items in a multi-level list will
93     be separated by the items in lower levels of the list.
94
95     List items can be deleted by index with the removeItem() function.
96     remove() deletes the specified item in the list.
97
98     The list's format is set with setFormat() and read with format().
99     The format describes the decoration of the list itself, and not the
100     individual items.
101
102     \sa QTextBlock, QTextListFormat, QTextCursor
103 */
104
105 /*!
106     \fn bool QTextList::isEmpty() const
107     \obsolete
108
109     Returns true if the list has no items; otherwise returns false.
110
111     \b{Note:} Empty lists are automatically deleted by the QTextDocument that owns
112     them.
113
114     \sa count()
115 */
116
117 /*! \internal
118  */
119 QTextList::QTextList(QTextDocument *doc)
120     : QTextBlockGroup(*new QTextListPrivate(doc), doc)
121 {
122 }
123
124 /*!
125   \internal
126 */
127 QTextList::~QTextList()
128 {
129 }
130
131 /*!
132     Returns the number of items in the list.
133 */
134 int QTextList::count() const
135 {
136     Q_D(const QTextList);
137     return d->blocks.count();
138 }
139
140 /*!
141     Returns the \a{i}-th text block in the list.
142
143     \sa count(), itemText()
144 */
145 QTextBlock QTextList::item(int i) const
146 {
147     Q_D(const QTextList);
148     if (i < 0 || i >= d->blocks.size())
149         return QTextBlock();
150     return d->blocks.at(i);
151 }
152
153 /*!
154     \fn void QTextList::setFormat(const QTextListFormat &format)
155
156     Sets the list's format to \a format.
157 */
158
159 /*!
160     \fn QTextListFormat QTextList::format() const
161
162     Returns the list's format.
163 */
164
165 /*!
166     \fn int QTextList::itemNumber(const QTextBlock &block) const
167
168     Returns the index of the list item that corresponds to the given \a block.
169     Returns -1 if the block was not present in the list.
170 */
171 int QTextList::itemNumber(const QTextBlock &blockIt) const
172 {
173     Q_D(const QTextList);
174     return d->blocks.indexOf(blockIt);
175 }
176
177 /*!
178     \fn QString QTextList::itemText(const QTextBlock &block) const
179
180     Returns the text of the list item that corresponds to the given \a block.
181 */
182 QString QTextList::itemText(const QTextBlock &blockIt) const
183 {
184     Q_D(const QTextList);
185     int item = d->blocks.indexOf(blockIt) + 1;
186     if (item <= 0)
187         return QString();
188
189     QTextBlock block = d->blocks.at(item-1);
190     QTextBlockFormat blockFormat = block.blockFormat();
191
192     QString result;
193
194     const int style = format().style();
195     QString numberPrefix;
196     QString numberSuffix = QLatin1String(".");
197
198     if (format().hasProperty(QTextFormat::ListNumberPrefix))
199         numberPrefix = format().numberPrefix();
200     if (format().hasProperty(QTextFormat::ListNumberSuffix))
201         numberSuffix = format().numberSuffix();
202
203     switch (style) {
204         case QTextListFormat::ListDecimal:
205             result = QString::number(item);
206             break;
207             // from the old richtext
208         case QTextListFormat::ListLowerAlpha:
209         case QTextListFormat::ListUpperAlpha:
210             {
211                 const char baseChar = style == QTextListFormat::ListUpperAlpha ? 'A' : 'a';
212
213                 int c = item;
214                 while (c > 0) {
215                     c--;
216                     result.prepend(QChar(baseChar + (c % 26)));
217                     c /= 26;
218                 }
219             }
220             break;
221         case QTextListFormat::ListLowerRoman:
222         case QTextListFormat::ListUpperRoman:
223             {
224                 if (item < 5000) {
225                     QByteArray romanNumeral;
226
227                     // works for up to 4999 items
228                     static const char romanSymbolsLower[] = "iiivixxxlxcccdcmmmm";
229                     static const char romanSymbolsUpper[] = "IIIVIXXXLXCCCDCMMMM";
230                     QByteArray romanSymbols; // wrap to have "mid"
231                     if (style == QTextListFormat::ListLowerRoman)
232                         romanSymbols = QByteArray::fromRawData(romanSymbolsLower, sizeof(romanSymbolsLower));
233                     else
234                         romanSymbols = QByteArray::fromRawData(romanSymbolsUpper, sizeof(romanSymbolsUpper));
235
236                     int c[] = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 };
237                     int n = item;
238                     for (int i = 12; i >= 0; n %= c[i], i--) {
239                         int q = n / c[i];
240                         if (q > 0) {
241                             int startDigit = i + (i+3)/4;
242                             int numDigits;
243                             if (i % 4) {
244                                 // c[i] == 4|5|9|40|50|90|400|500|900
245                                 if ((i-2) % 4) {
246                                     // c[i] == 4|9|40|90|400|900 => with subtraction (IV, IX, XL, XC, ...)
247                                     numDigits = 2;
248                                 }
249                                 else {
250                                     // c[i] == 5|50|500 (V, L, D)
251                                     numDigits = 1;
252                                 }
253                             }
254                             else {
255                                 // c[i] == 1|10|100|1000 (I, II, III, X, XX, ...)
256                                 numDigits = q;
257                             }
258
259                             romanNumeral.append(romanSymbols.mid(startDigit, numDigits));
260                         }
261                     }
262                     result = QString::fromLatin1(romanNumeral);
263                 }
264                 else {
265                     result = QLatin1String("?");
266                 }
267
268             }
269             break;
270         default:
271             Q_ASSERT(false);
272     }
273     if (blockIt.textDirection() == Qt::RightToLeft)
274         return numberSuffix + result + numberPrefix;
275     else
276         return numberPrefix + result + numberSuffix;
277 }
278
279 /*!
280     Removes the item at item position \a i from the list. When the last item in the
281     list is removed, the list is automatically deleted by the QTextDocument that owns
282     it.
283
284     \sa add(), remove()
285 */
286 void QTextList::removeItem(int i)
287 {
288     Q_D(QTextList);
289     if (i < 0 || i >= d->blocks.size())
290         return;
291
292     QTextBlock block = d->blocks.at(i);
293     remove(block);
294 }
295
296
297 /*!
298     Removes the given \a block from the list.
299
300     \sa add(), removeItem()
301 */
302 void QTextList::remove(const QTextBlock &block)
303 {
304     QTextBlockFormat fmt = block.blockFormat();
305     fmt.setIndent(fmt.indent() + format().indent());
306     fmt.setObjectIndex(-1);
307     block.docHandle()->setBlockFormat(block, block, fmt, QTextDocumentPrivate::SetFormat);
308 }
309
310 /*!
311     Makes the given \a block part of the list.
312
313     \sa remove(), removeItem()
314 */
315 void QTextList::add(const QTextBlock &block)
316 {
317     QTextBlockFormat fmt = block.blockFormat();
318     fmt.setObjectIndex(objectIndex());
319     block.docHandle()->setBlockFormat(block, block, fmt, QTextDocumentPrivate::SetFormat);
320 }
321
322 QT_END_NAMESPACE