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