| /**************************************************************************** |
| ** |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** This file is part of the QtGui module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** GNU Lesser General Public License Usage |
| ** This file may be used under the terms of the GNU Lesser General Public |
| ** License version 2.1 as published by the Free Software Foundation and |
| ** appearing in the file LICENSE.LGPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU Lesser |
| ** General Public License version 2.1 requirements will be met: |
| ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| ** |
| ** In addition, as a special exception, Nokia gives you certain additional |
| ** rights. These rights are described in the Nokia Qt LGPL Exception |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU General |
| ** Public License version 3.0 as published by the Free Software Foundation |
| ** and appearing in the file LICENSE.GPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU General |
| ** Public License version 3.0 requirements will be met: |
| ** http://www.gnu.org/copyleft/gpl.html. |
| ** |
| ** Other Usage |
| ** Alternatively, this file may be used in accordance with the terms and |
| ** conditions contained in a signed written agreement between you and Nokia. |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| |
| #include "qtextlist.h" |
| #include "qtextobject_p.h" |
| #include "qtextcursor.h" |
| #include "qtextdocument_p.h" |
| #include <qdebug.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| class QTextListPrivate : public QTextBlockGroupPrivate |
| { |
| public: |
| QTextListPrivate(QTextDocument *doc) |
| : QTextBlockGroupPrivate(doc) |
| { |
| } |
| }; |
| |
| /*! |
| \class QTextList |
| \reentrant |
| |
| \brief The QTextList class provides a decorated list of items in a QTextDocument. |
| |
| \ingroup richtext-processing |
| |
| A list contains a sequence of text blocks, each of which is marked with a |
| bullet point or other symbol. Multiple levels of lists can be used, and |
| the automatic numbering feature provides support for ordered numeric and |
| alphabetical lists. |
| |
| Lists are created by using a text cursor to insert an empty list at the |
| current position or by moving existing text into a new list. |
| The \l{QTextCursor::insertList()} function inserts an empty block into the |
| document at the cursor position, and makes it the first item in a list. |
| |
| \snippet doc/src/snippets/textdocument-lists/mainwindow.cpp 0 |
| |
| The \l{QTextCursor::createList()} function takes the contents of the |
| cursor's current block and turns it into the first item of a new list. |
| |
| The cursor's current list is found with \l{QTextCursor::currentList()}. |
| |
| The number of items in a list is given by count(). Each item can be |
| obtained by its index in the list with the item() function. Similarly, |
| the index of a given item can be found with itemNumber(). The text of |
| each item can be found with the itemText() function. |
| |
| Note that the items in the list may not be adjacent elements in the |
| document. For example, the top-level items in a multi-level list will |
| be separated by the items in lower levels of the list. |
| |
| List items can be deleted by index with the removeItem() function. |
| remove() deletes the specified item in the list. |
| |
| The list's format is set with setFormat() and read with format(). |
| The format describes the decoration of the list itself, and not the |
| individual items. |
| |
| \sa QTextBlock, QTextListFormat, QTextCursor |
| */ |
| |
| /*! |
| \fn bool QTextList::isEmpty() const |
| \obsolete |
| |
| Returns true if the list has no items; otherwise returns false. |
| |
| \bold{Note:} Empty lists are automatically deleted by the QTextDocument that owns |
| them. |
| |
| \sa count() |
| */ |
| |
| /*! \internal |
| */ |
| QTextList::QTextList(QTextDocument *doc) |
| : QTextBlockGroup(*new QTextListPrivate(doc), doc) |
| { |
| } |
| |
| /*! |
| \internal |
| */ |
| QTextList::~QTextList() |
| { |
| } |
| |
| /*! |
| Returns the number of items in the list. |
| */ |
| int QTextList::count() const |
| { |
| Q_D(const QTextList); |
| return d->blocks.count(); |
| } |
| |
| /*! |
| Returns the \a{i}-th text block in the list. |
| |
| \sa count() itemText() |
| */ |
| QTextBlock QTextList::item(int i) const |
| { |
| Q_D(const QTextList); |
| if (i < 0 || i >= d->blocks.size()) |
| return QTextBlock(); |
| return d->blocks.at(i); |
| } |
| |
| /*! |
| \fn void QTextList::setFormat(const QTextListFormat &format) |
| |
| Sets the list's format to \a format. |
| */ |
| |
| /*! |
| \fn QTextListFormat QTextList::format() const |
| |
| Returns the list's format. |
| */ |
| |
| /*! |
| \fn int QTextList::itemNumber(const QTextBlock &block) const |
| |
| Returns the index of the list item that corresponds to the given \a block. |
| Returns -1 if the block was not present in the list. |
| */ |
| int QTextList::itemNumber(const QTextBlock &blockIt) const |
| { |
| Q_D(const QTextList); |
| return d->blocks.indexOf(blockIt); |
| } |
| |
| /*! |
| \fn QString QTextList::itemText(const QTextBlock &block) const |
| |
| Returns the text of the list item that corresponds to the given \a block. |
| */ |
| QString QTextList::itemText(const QTextBlock &blockIt) const |
| { |
| Q_D(const QTextList); |
| int item = d->blocks.indexOf(blockIt) + 1; |
| if (item <= 0) |
| return QString(); |
| |
| QTextBlock block = d->blocks.at(item-1); |
| QTextBlockFormat blockFormat = block.blockFormat(); |
| |
| QString result; |
| |
| const int style = format().style(); |
| |
| switch (style) { |
| case QTextListFormat::ListDecimal: |
| result = QString::number(item); |
| break; |
| // from the old richtext |
| case QTextListFormat::ListLowerAlpha: |
| case QTextListFormat::ListUpperAlpha: |
| { |
| const char baseChar = style == QTextListFormat::ListUpperAlpha ? 'A' : 'a'; |
| |
| int c = item; |
| while (c > 0) { |
| c--; |
| result.prepend(QChar(baseChar + (c % 26))); |
| c /= 26; |
| } |
| } |
| break; |
| case QTextListFormat::ListLowerRoman: |
| case QTextListFormat::ListUpperRoman: |
| { |
| if (item < 5000) { |
| QByteArray romanNumeral; |
| |
| // works for up to 4999 items |
| static const char romanSymbolsLower[] = "iiivixxxlxcccdcmmmm"; |
| static const char romanSymbolsUpper[] = "IIIVIXXXLXCCCDCMMMM"; |
| QByteArray romanSymbols; // wrap to have "mid" |
| if (style == QTextListFormat::ListLowerRoman) |
| romanSymbols = QByteArray::fromRawData(romanSymbolsLower, sizeof(romanSymbolsLower)); |
| else |
| romanSymbols = QByteArray::fromRawData(romanSymbolsUpper, sizeof(romanSymbolsUpper)); |
| |
| int c[] = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 }; |
| int n = item; |
| for (int i = 12; i >= 0; n %= c[i], i--) { |
| int q = n / c[i]; |
| if (q > 0) { |
| int startDigit = i + (i+3)/4; |
| int numDigits; |
| if (i % 4) { |
| // c[i] == 4|5|9|40|50|90|400|500|900 |
| if ((i-2) % 4) { |
| // c[i] == 4|9|40|90|400|900 => with subtraction (IV, IX, XL, XC, ...) |
| numDigits = 2; |
| } |
| else { |
| // c[i] == 5|50|500 (V, L, D) |
| numDigits = 1; |
| } |
| } |
| else { |
| // c[i] == 1|10|100|1000 (I, II, III, X, XX, ...) |
| numDigits = q; |
| } |
| |
| romanNumeral.append(romanSymbols.mid(startDigit, numDigits)); |
| } |
| } |
| result = QString::fromLatin1(romanNumeral); |
| } |
| else { |
| result = QLatin1String("?"); |
| } |
| |
| } |
| break; |
| default: |
| Q_ASSERT(false); |
| } |
| if (blockIt.textDirection() == Qt::RightToLeft) |
| return result.prepend(QLatin1Char('.')); |
| return result + QLatin1Char('.'); |
| } |
| |
| /*! |
| Removes the item at item position \a i from the list. When the last item in the |
| list is removed, the list is automatically deleted by the QTextDocument that owns |
| it. |
| |
| \sa add(), remove() |
| */ |
| void QTextList::removeItem(int i) |
| { |
| Q_D(QTextList); |
| if (i < 0 || i >= d->blocks.size()) |
| return; |
| |
| QTextBlock block = d->blocks.at(i); |
| remove(block); |
| } |
| |
| |
| /*! |
| Removes the given \a block from the list. |
| |
| \sa add(), removeItem() |
| */ |
| void QTextList::remove(const QTextBlock &block) |
| { |
| QTextBlockFormat fmt = block.blockFormat(); |
| fmt.setIndent(fmt.indent() + format().indent()); |
| fmt.setObjectIndex(-1); |
| block.docHandle()->setBlockFormat(block, block, fmt, QTextDocumentPrivate::SetFormat); |
| } |
| |
| /*! |
| Makes the given \a block part of the list. |
| |
| \sa remove(), removeItem() |
| */ |
| void QTextList::add(const QTextBlock &block) |
| { |
| QTextBlockFormat fmt = block.blockFormat(); |
| fmt.setObjectIndex(objectIndex()); |
| block.docHandle()->setBlockFormat(block, block, fmt, QTextDocumentPrivate::SetFormat); |
| } |
| |
| QT_END_NAMESPACE |