src/gui/text/qtextlist.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    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 
       
    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 
       
   195     switch (style) {
       
   196         case QTextListFormat::ListDecimal:
       
   197             result = QString::number(item);
       
   198             break;
       
   199             // from the old richtext
       
   200         case QTextListFormat::ListLowerAlpha:
       
   201         case QTextListFormat::ListUpperAlpha:
       
   202             {
       
   203                 const char baseChar = style == QTextListFormat::ListUpperAlpha ? 'A' : 'a';
       
   204 
       
   205                 int c = item;
       
   206                 while (c > 0) {
       
   207                     c--;
       
   208                     result.prepend(QChar(baseChar + (c % 26)));
       
   209                     c /= 26;
       
   210                 }
       
   211             }
       
   212             break;
       
   213         case QTextListFormat::ListLowerRoman:
       
   214         case QTextListFormat::ListUpperRoman:
       
   215             {
       
   216                 if (item < 5000) {
       
   217                     QByteArray romanNumeral;
       
   218 
       
   219                     // works for up to 4999 items
       
   220                     static const char romanSymbolsLower[] = "iiivixxxlxcccdcmmmm";
       
   221                     static const char romanSymbolsUpper[] = "IIIVIXXXLXCCCDCMMMM";
       
   222                     QByteArray romanSymbols; // wrap to have "mid"
       
   223                     if (style == QTextListFormat::ListLowerRoman)
       
   224                         romanSymbols = QByteArray::fromRawData(romanSymbolsLower, sizeof(romanSymbolsLower));
       
   225                     else
       
   226                         romanSymbols = QByteArray::fromRawData(romanSymbolsUpper, sizeof(romanSymbolsUpper));
       
   227 
       
   228                     int c[] = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 };
       
   229                     int n = item;
       
   230                     for (int i = 12; i >= 0; n %= c[i], i--) {
       
   231                         int q = n / c[i];
       
   232                         if (q > 0) {
       
   233                             int startDigit = i + (i+3)/4;
       
   234                             int numDigits;
       
   235                             if (i % 4) { 
       
   236                                 // c[i] == 4|5|9|40|50|90|400|500|900
       
   237                                 if ((i-2) % 4) {
       
   238                                     // c[i] == 4|9|40|90|400|900 => with substraction (IV, IX, XL, XC, ...)
       
   239                                     numDigits = 2;
       
   240                                 }
       
   241                                 else {
       
   242                                     // c[i] == 5|50|500 (V, L, D)
       
   243                                     numDigits = 1;
       
   244                                 }
       
   245                             }
       
   246                             else {
       
   247                                 // c[i] == 1|10|100|1000 (I, II, III, X, XX, ...)
       
   248                                 numDigits = q;
       
   249                             }
       
   250 
       
   251                             romanNumeral.append(romanSymbols.mid(startDigit, numDigits));
       
   252                         }
       
   253                     }
       
   254                     result = QString::fromLatin1(romanNumeral);
       
   255                 }
       
   256                 else {
       
   257                     result = QLatin1String("?");
       
   258                 }
       
   259 
       
   260 	    }
       
   261 	    break;
       
   262         default:
       
   263             Q_ASSERT(false);
       
   264     }
       
   265     if (blockFormat.layoutDirection() == Qt::RightToLeft)
       
   266         return result.prepend(QLatin1Char('.'));
       
   267     return result + QLatin1Char('.');
       
   268 }
       
   269 
       
   270 /*!
       
   271     Removes the item at item position \a i from the list. When the last item in the
       
   272     list is removed, the list is automatically deleted by the QTextDocument that owns
       
   273     it.
       
   274 
       
   275     \sa add(), remove()
       
   276 */
       
   277 void QTextList::removeItem(int i)
       
   278 {
       
   279     Q_D(QTextList);
       
   280     if (i < 0 || i >= d->blocks.size())
       
   281         return;
       
   282 
       
   283     QTextBlock block = d->blocks.at(i);
       
   284     remove(block);
       
   285 }
       
   286 
       
   287 
       
   288 /*!
       
   289     Removes the given \a block from the list.
       
   290 
       
   291     \sa add(), removeItem()
       
   292 */
       
   293 void QTextList::remove(const QTextBlock &block)
       
   294 {
       
   295     QTextBlockFormat fmt = block.blockFormat();
       
   296     fmt.setIndent(fmt.indent() + format().indent());
       
   297     fmt.setObjectIndex(-1);
       
   298     block.docHandle()->setBlockFormat(block, block, fmt, QTextDocumentPrivate::SetFormat);
       
   299 }
       
   300 
       
   301 /*!
       
   302     Makes the given \a block part of the list.
       
   303 
       
   304     \sa remove(), removeItem()
       
   305 */
       
   306 void QTextList::add(const QTextBlock &block)
       
   307 {
       
   308     QTextBlockFormat fmt = block.blockFormat();
       
   309     fmt.setObjectIndex(objectIndex());
       
   310     block.docHandle()->setBlockFormat(block, block, fmt, QTextDocumentPrivate::SetFormat);
       
   311 }
       
   312 
       
   313 QT_END_NAMESPACE