| /**************************************************************************** |
| ** |
| ** 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 "qtextobject.h" |
| #include "qtextobject_p.h" |
| #include "qtextdocument.h" |
| #include "qtextformat_p.h" |
| #include "qtextdocument_p.h" |
| #include "qtextcursor.h" |
| #include "qtextlist.h" |
| #include "qabstracttextdocumentlayout.h" |
| #include "qtextengine_p.h" |
| #include "qdebug.h" |
| |
| QT_BEGIN_NAMESPACE |
| |
| // ### DOC: We ought to explain the CONCEPT of objectIndexes if |
| // relevant to the public API |
| /*! |
| \class QTextObject |
| \reentrant |
| |
| \brief The QTextObject class is a base class for different kinds |
| of objects that can group parts of a QTextDocument together. |
| |
| \ingroup richtext-processing |
| |
| The common grouping text objects are lists (QTextList), frames |
| (QTextFrame), and tables (QTextTable). A text object has an |
| associated format() and document(). |
| |
| There are essentially two kinds of text objects: those that are used |
| with blocks (block formats), and those that are used with characters |
| (character formats). The first kind are derived from QTextBlockGroup, |
| and the second kind from QTextFrame. |
| |
| You rarely need to use this class directly. When creating custom text |
| objects, you will also need to reimplement QTextDocument::createObject() |
| which acts as a factory method for creating text objects. |
| |
| \sa QTextDocument, {Text Object Example} |
| */ |
| |
| /*! |
| \fn QTextObject::QTextObject(QTextDocument *document) |
| |
| Creates a new QTextObject for the given \a document. |
| |
| \warning This function should never be called directly, but only |
| from QTextDocument::createObject(). |
| */ |
| QTextObject::QTextObject(QTextDocument *doc) |
| : QObject(*new QTextObjectPrivate(doc), doc) |
| { |
| } |
| |
| /*! |
| \fn QTextObject::QTextObject(QTextObjectPrivate &p, QTextDocument *document) |
| |
| \internal |
| */ |
| QTextObject::QTextObject(QTextObjectPrivate &p, QTextDocument *doc) |
| : QObject(p, doc) |
| { |
| } |
| |
| /*! |
| Destroys the text object. |
| |
| \warning Text objects are owned by the document, so you should |
| never destroy them yourself. |
| */ |
| QTextObject::~QTextObject() |
| { |
| } |
| |
| /*! |
| Returns the text object's format. |
| |
| \sa setFormat() document() |
| */ |
| QTextFormat QTextObject::format() const |
| { |
| Q_D(const QTextObject); |
| return d->pieceTable->formatCollection()->objectFormat(d->objectIndex); |
| } |
| |
| /*! |
| Returns the index of the object's format in the document's internal |
| list of formats. |
| |
| \sa QTextDocument::allFormats() |
| */ |
| int QTextObject::formatIndex() const |
| { |
| Q_D(const QTextObject); |
| return d->pieceTable->formatCollection()->objectFormatIndex(d->objectIndex); |
| } |
| |
| |
| /*! |
| Sets the text object's \a format. |
| |
| \sa format() |
| */ |
| void QTextObject::setFormat(const QTextFormat &format) |
| { |
| Q_D(QTextObject); |
| int idx = d->pieceTable->formatCollection()->indexForFormat(format); |
| d->pieceTable->changeObjectFormat(this, idx); |
| } |
| |
| /*! |
| Returns the object index of this object. This can be used together with |
| QTextFormat::setObjectIndex(). |
| */ |
| int QTextObject::objectIndex() const |
| { |
| Q_D(const QTextObject); |
| return d->objectIndex; |
| } |
| |
| /*! |
| Returns the document this object belongs to. |
| |
| \sa format() |
| */ |
| QTextDocument *QTextObject::document() const |
| { |
| return static_cast<QTextDocument *>(parent()); |
| } |
| |
| /*! |
| \internal |
| */ |
| QTextDocumentPrivate *QTextObject::docHandle() const |
| { |
| return static_cast<const QTextDocument *>(parent())->docHandle(); |
| } |
| |
| /*! |
| \class QTextBlockGroup |
| \reentrant |
| |
| \brief The QTextBlockGroup class provides a container for text blocks within |
| a QTextDocument. |
| |
| \ingroup richtext-processing |
| |
| Block groups can be used to organize blocks of text within a document. |
| They maintain an up-to-date list of the text blocks that belong to |
| them, even when text blocks are being edited. |
| |
| Each group has a parent document which is specified when the group is |
| constructed. |
| |
| Text blocks can be inserted into a group with blockInserted(), and removed |
| with blockRemoved(). If a block's format is changed, blockFormatChanged() |
| is called. |
| |
| The list of blocks in the group is returned by blockList(). Note that the |
| blocks in the list are not necessarily 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. |
| |
| \sa QTextBlock QTextDocument |
| */ |
| |
| void QTextBlockGroupPrivate::markBlocksDirty() |
| { |
| for (int i = 0; i < blocks.count(); ++i) { |
| const QTextBlock &block = blocks.at(i); |
| pieceTable->documentChange(block.position(), block.length()); |
| } |
| } |
| |
| /*! |
| \fn QTextBlockGroup::QTextBlockGroup(QTextDocument *document) |
| |
| Creates a new new block group for the given \a document. |
| |
| \warning This function should only be called from |
| QTextDocument::createObject(). |
| */ |
| QTextBlockGroup::QTextBlockGroup(QTextDocument *doc) |
| : QTextObject(*new QTextBlockGroupPrivate(doc), doc) |
| { |
| } |
| |
| /*! |
| \internal |
| */ |
| QTextBlockGroup::QTextBlockGroup(QTextBlockGroupPrivate &p, QTextDocument *doc) |
| : QTextObject(p, doc) |
| { |
| } |
| |
| /*! |
| Destroys this block group; the blocks are not deleted, they simply |
| don't belong to this block anymore. |
| */ |
| QTextBlockGroup::~QTextBlockGroup() |
| { |
| } |
| |
| // ### DOC: Shouldn't this be insertBlock()? |
| /*! |
| Appends the given \a block to the end of the group. |
| |
| \warning If you reimplement this function you must call the base |
| class implementation. |
| */ |
| void QTextBlockGroup::blockInserted(const QTextBlock &block) |
| { |
| Q_D(QTextBlockGroup); |
| QTextBlockGroupPrivate::BlockList::Iterator it = qLowerBound(d->blocks.begin(), d->blocks.end(), block); |
| d->blocks.insert(it, block); |
| d->markBlocksDirty(); |
| } |
| |
| // ### DOC: Shouldn't this be removeBlock()? |
| /*! |
| Removes the given \a block from the group; the block itself is not |
| deleted, it simply isn't a member of this group anymore. |
| */ |
| void QTextBlockGroup::blockRemoved(const QTextBlock &block) |
| { |
| Q_D(QTextBlockGroup); |
| d->blocks.removeAll(block); |
| d->markBlocksDirty(); |
| if (d->blocks.isEmpty()) { |
| document()->docHandle()->deleteObject(this); |
| return; |
| } |
| } |
| |
| /*! |
| This function is called whenever the specified \a block of text is changed. |
| The text block is a member of this group. |
| |
| The base class implementation does nothing. |
| */ |
| void QTextBlockGroup::blockFormatChanged(const QTextBlock &) |
| { |
| } |
| |
| /*! |
| Returns a (possibly empty) list of all the blocks that are part of |
| the block group. |
| */ |
| QList<QTextBlock> QTextBlockGroup::blockList() const |
| { |
| Q_D(const QTextBlockGroup); |
| return d->blocks; |
| } |
| |
| |
| |
| QTextFrameLayoutData::~QTextFrameLayoutData() |
| { |
| } |
| |
| |
| /*! |
| \class QTextFrame |
| \reentrant |
| |
| \brief The QTextFrame class represents a frame in a QTextDocument. |
| |
| \ingroup richtext-processing |
| |
| Text frames provide structure for the text in a document. They are used |
| as generic containers for other document elements. |
| Frames are usually created by using QTextCursor::insertFrame(). |
| |
| \omit |
| Each frame in a document consists of a frame start character, |
| QChar(0xFDD0), followed by the frame's contents, followed by a |
| frame end character, QChar(0xFDD1). The character formats of the |
| start and end character contain a reference to the frame object's |
| objectIndex. |
| \endomit |
| |
| Frames can be used to create hierarchical structures in rich text documents. |
| Each document has a root frame (QTextDocument::rootFrame()), and each frame |
| beneath the root frame has a parent frame and a (possibly empty) list of |
| child frames. The parent frame can be found with parentFrame(), and the |
| childFrames() function provides a list of child frames. |
| |
| Each frame contains at least one text block to enable text cursors to |
| insert new document elements within. As a result, the QTextFrame::iterator |
| class is used to traverse both the blocks and child frames within a given |
| frame. The first and last child elements in the frame can be found with |
| begin() and end(). |
| |
| A frame also has a format (specified using QTextFrameFormat) which can be set |
| with setFormat() and read with format(). |
| |
| Text cursors can be obtained that point to the first and last valid cursor |
| positions within a frame; use the firstCursorPosition() and |
| lastCursorPosition() functions for this. The frame's extent in the |
| document can be found with firstPosition() and lastPosition(). |
| |
| You can iterate over a frame's contents using the |
| QTextFrame::iterator class: this provides read-only access to its |
| internal list of text blocks and child frames. |
| |
| \sa QTextCursor QTextDocument |
| */ |
| |
| /*! |
| \typedef QTextFrame::Iterator |
| |
| Qt-style synonym for QTextFrame::iterator. |
| */ |
| |
| /*! |
| \fn QTextFrame *QTextFrame::iterator::parentFrame() const |
| |
| Returns the parent frame of the current frame. |
| |
| \sa currentFrame() QTextFrame::parentFrame() |
| */ |
| |
| /*! |
| \fn bool QTextFrame::iterator::operator==(const iterator &other) const |
| |
| Retuns true if the iterator is the same as the \a other iterator; |
| otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QTextFrame::iterator::operator!=(const iterator &other) const |
| |
| Retuns true if the iterator is different from the \a other iterator; |
| otherwise returns false. |
| */ |
| |
| /*! |
| \fn QTextFrame::iterator QTextFrame::iterator::operator++(int) |
| |
| The postfix ++ operator (\c{i++}) advances the iterator to the |
| next item in the text frame, and returns an iterator to the old item. |
| */ |
| |
| /*! |
| \fn QTextFrame::iterator QTextFrame::iterator::operator--(int) |
| |
| The postfix -- operator (\c{i--}) makes the preceding item in the |
| current frame, and returns an iterator to the old item. |
| */ |
| |
| /*! |
| \fn void QTextFrame::setFrameFormat(const QTextFrameFormat &format) |
| |
| Sets the frame's \a format. |
| |
| \sa frameFormat() |
| */ |
| |
| /*! |
| \fn QTextFrameFormat QTextFrame::frameFormat() const |
| |
| Returns the frame's format. |
| |
| \sa setFrameFormat() |
| */ |
| |
| /*! |
| \fn QTextFrame::QTextFrame(QTextDocument *document) |
| |
| Creates a new empty frame for the text \a document. |
| */ |
| QTextFrame::QTextFrame(QTextDocument *doc) |
| : QTextObject(*new QTextFramePrivate(doc), doc) |
| { |
| } |
| |
| // ### DOC: What does this do to child frames? |
| /*! |
| Destroys the frame, and removes it from the document's layout. |
| */ |
| QTextFrame::~QTextFrame() |
| { |
| Q_D(QTextFrame); |
| delete d->layoutData; |
| } |
| |
| /*! |
| \internal |
| */ |
| QTextFrame::QTextFrame(QTextFramePrivate &p, QTextDocument *doc) |
| : QTextObject(p, doc) |
| { |
| } |
| |
| /*! |
| Returns a (possibly empty) list of the frame's child frames. |
| |
| \sa parentFrame() |
| */ |
| QList<QTextFrame *> QTextFrame::childFrames() const |
| { |
| Q_D(const QTextFrame); |
| return d->childFrames; |
| } |
| |
| /*! |
| Returns the frame's parent frame. If the frame is the root frame of a |
| document, this will return 0. |
| |
| \sa childFrames() QTextDocument::rootFrame() |
| */ |
| QTextFrame *QTextFrame::parentFrame() const |
| { |
| Q_D(const QTextFrame); |
| return d->parentFrame; |
| } |
| |
| |
| /*! |
| Returns the first cursor position inside the frame. |
| |
| \sa lastCursorPosition() firstPosition() lastPosition() |
| */ |
| QTextCursor QTextFrame::firstCursorPosition() const |
| { |
| Q_D(const QTextFrame); |
| return QTextCursor(d->pieceTable, firstPosition()); |
| } |
| |
| /*! |
| Returns the last cursor position inside the frame. |
| |
| \sa firstCursorPosition() firstPosition() lastPosition() |
| */ |
| QTextCursor QTextFrame::lastCursorPosition() const |
| { |
| Q_D(const QTextFrame); |
| return QTextCursor(d->pieceTable, lastPosition()); |
| } |
| |
| /*! |
| Returns the first document position inside the frame. |
| |
| \sa lastPosition() firstCursorPosition() lastCursorPosition() |
| */ |
| int QTextFrame::firstPosition() const |
| { |
| Q_D(const QTextFrame); |
| if (!d->fragment_start) |
| return 0; |
| return d->pieceTable->fragmentMap().position(d->fragment_start) + 1; |
| } |
| |
| /*! |
| Returns the last document position inside the frame. |
| |
| \sa firstPosition() firstCursorPosition() lastCursorPosition() |
| */ |
| int QTextFrame::lastPosition() const |
| { |
| Q_D(const QTextFrame); |
| if (!d->fragment_end) |
| return d->pieceTable->length() - 1; |
| return d->pieceTable->fragmentMap().position(d->fragment_end); |
| } |
| |
| /*! |
| \internal |
| */ |
| QTextFrameLayoutData *QTextFrame::layoutData() const |
| { |
| Q_D(const QTextFrame); |
| return d->layoutData; |
| } |
| |
| /*! |
| \internal |
| */ |
| void QTextFrame::setLayoutData(QTextFrameLayoutData *data) |
| { |
| Q_D(QTextFrame); |
| delete d->layoutData; |
| d->layoutData = data; |
| } |
| |
| |
| |
| void QTextFramePrivate::fragmentAdded(const QChar &type, uint fragment) |
| { |
| if (type == QTextBeginningOfFrame) { |
| Q_ASSERT(!fragment_start); |
| fragment_start = fragment; |
| } else if (type == QTextEndOfFrame) { |
| Q_ASSERT(!fragment_end); |
| fragment_end = fragment; |
| } else if (type == QChar::ObjectReplacementCharacter) { |
| Q_ASSERT(!fragment_start); |
| Q_ASSERT(!fragment_end); |
| fragment_start = fragment; |
| fragment_end = fragment; |
| } else { |
| Q_ASSERT(false); |
| } |
| } |
| |
| void QTextFramePrivate::fragmentRemoved(const QChar &type, uint fragment) |
| { |
| Q_UNUSED(fragment); // --release warning |
| if (type == QTextBeginningOfFrame) { |
| Q_ASSERT(fragment_start == fragment); |
| fragment_start = 0; |
| } else if (type == QTextEndOfFrame) { |
| Q_ASSERT(fragment_end == fragment); |
| fragment_end = 0; |
| } else if (type == QChar::ObjectReplacementCharacter) { |
| Q_ASSERT(fragment_start == fragment); |
| Q_ASSERT(fragment_end == fragment); |
| fragment_start = 0; |
| fragment_end = 0; |
| } else { |
| Q_ASSERT(false); |
| } |
| remove_me(); |
| } |
| |
| |
| void QTextFramePrivate::remove_me() |
| { |
| Q_Q(QTextFrame); |
| if (fragment_start == 0 && fragment_end == 0 |
| && !parentFrame) { |
| q->document()->docHandle()->deleteObject(q); |
| return; |
| } |
| |
| if (!parentFrame) |
| return; |
| |
| int index = parentFrame->d_func()->childFrames.indexOf(q); |
| |
| // iterator over all children and move them to the parent |
| for (int i = 0; i < childFrames.size(); ++i) { |
| QTextFrame *c = childFrames.at(i); |
| parentFrame->d_func()->childFrames.insert(index, c); |
| c->d_func()->parentFrame = parentFrame; |
| ++index; |
| } |
| Q_ASSERT(parentFrame->d_func()->childFrames.at(index) == q); |
| parentFrame->d_func()->childFrames.removeAt(index); |
| |
| childFrames.clear(); |
| parentFrame = 0; |
| } |
| |
| /*! |
| \class QTextFrame::iterator |
| \reentrant |
| |
| \brief The iterator class provides an iterator for reading |
| the contents of a QTextFrame. |
| |
| \ingroup richtext-processing |
| |
| A frame consists of an arbitrary sequence of \l{QTextBlock}s and |
| child \l{QTextFrame}s. This class provides a way to iterate over the |
| child objects of a frame, and read their contents. It does not provide |
| a way to modify the contents of the frame. |
| |
| */ |
| |
| /*! |
| \fn bool QTextFrame::iterator::atEnd() const |
| |
| Returns true if the current item is the last item in the text frame. |
| */ |
| |
| /*! |
| Returns an iterator pointing to the first document element inside the frame. |
| Please see the document \l{STL-style-Iterators} for more information. |
| |
| \sa end() |
| */ |
| QTextFrame::iterator QTextFrame::begin() const |
| { |
| const QTextDocumentPrivate *priv = docHandle(); |
| int b = priv->blockMap().findNode(firstPosition()); |
| int e = priv->blockMap().findNode(lastPosition()+1); |
| return iterator(const_cast<QTextFrame *>(this), b, b, e); |
| } |
| |
| /*! |
| Returns an iterator pointing to the position past the last document element inside the frame. |
| Please see the document \l{STL-Style Iterators} for more information. |
| \sa begin() |
| */ |
| QTextFrame::iterator QTextFrame::end() const |
| { |
| const QTextDocumentPrivate *priv = docHandle(); |
| int b = priv->blockMap().findNode(firstPosition()); |
| int e = priv->blockMap().findNode(lastPosition()+1); |
| return iterator(const_cast<QTextFrame *>(this), e, b, e); |
| } |
| |
| /*! |
| Constructs an invalid iterator. |
| */ |
| QTextFrame::iterator::iterator() |
| { |
| f = 0; |
| b = 0; |
| e = 0; |
| cf = 0; |
| cb = 0; |
| } |
| |
| /*! |
| \internal |
| */ |
| QTextFrame::iterator::iterator(QTextFrame *frame, int block, int begin, int end) |
| { |
| f = frame; |
| b = begin; |
| e = end; |
| cf = 0; |
| cb = block; |
| } |
| |
| /*! |
| Copy constructor. Constructs a copy of the \a other iterator. |
| */ |
| QTextFrame::iterator::iterator(const iterator &other) |
| { |
| f = other.f; |
| b = other.b; |
| e = other.e; |
| cf = other.cf; |
| cb = other.cb; |
| } |
| |
| /*! |
| Assigns \a other to this iterator and returns a reference to |
| this iterator. |
| */ |
| QTextFrame::iterator &QTextFrame::iterator::operator=(const iterator &other) |
| { |
| f = other.f; |
| b = other.b; |
| e = other.e; |
| cf = other.cf; |
| cb = other.cb; |
| return *this; |
| } |
| |
| /*! |
| Returns the current frame pointed to by the iterator, or 0 if the |
| iterator currently points to a block. |
| |
| \sa currentBlock() |
| */ |
| QTextFrame *QTextFrame::iterator::currentFrame() const |
| { |
| return cf; |
| } |
| |
| /*! |
| Returns the current block the iterator points to. If the iterator |
| points to a child frame, the returned block is invalid. |
| |
| \sa currentFrame() |
| */ |
| QTextBlock QTextFrame::iterator::currentBlock() const |
| { |
| if (!f) |
| return QTextBlock(); |
| return QTextBlock(f->docHandle(), cb); |
| } |
| |
| /*! |
| Moves the iterator to the next frame or block. |
| |
| \sa currentBlock() currentFrame() |
| */ |
| QTextFrame::iterator &QTextFrame::iterator::operator++() |
| { |
| const QTextDocumentPrivate *priv = f->docHandle(); |
| const QTextDocumentPrivate::BlockMap &map = priv->blockMap(); |
| if (cf) { |
| int end = cf->lastPosition() + 1; |
| cb = map.findNode(end); |
| cf = 0; |
| } else if (cb) { |
| cb = map.next(cb); |
| if (cb == e) |
| return *this; |
| |
| if (!f->d_func()->childFrames.isEmpty()) { |
| int pos = map.position(cb); |
| // check if we entered a frame |
| QTextDocumentPrivate::FragmentIterator frag = priv->find(pos-1); |
| if (priv->buffer().at(frag->stringPosition) != QChar::ParagraphSeparator) { |
| QTextFrame *nf = qobject_cast<QTextFrame *>(priv->objectForFormat(frag->format)); |
| if (nf) { |
| if (priv->buffer().at(frag->stringPosition) == QTextBeginningOfFrame && nf != f) { |
| cf = nf; |
| cb = 0; |
| } else { |
| Q_ASSERT(priv->buffer().at(frag->stringPosition) != QTextEndOfFrame); |
| } |
| } |
| } |
| } |
| } |
| return *this; |
| } |
| |
| /*! |
| Moves the iterator to the previous frame or block. |
| |
| \sa currentBlock() currentFrame() |
| */ |
| QTextFrame::iterator &QTextFrame::iterator::operator--() |
| { |
| const QTextDocumentPrivate *priv = f->docHandle(); |
| const QTextDocumentPrivate::BlockMap &map = priv->blockMap(); |
| if (cf) { |
| int start = cf->firstPosition() - 1; |
| cb = map.findNode(start); |
| cf = 0; |
| } else { |
| if (cb == b) |
| goto end; |
| if (cb != e) { |
| int pos = map.position(cb); |
| // check if we have to enter a frame |
| QTextDocumentPrivate::FragmentIterator frag = priv->find(pos-1); |
| if (priv->buffer().at(frag->stringPosition) != QChar::ParagraphSeparator) { |
| QTextFrame *pf = qobject_cast<QTextFrame *>(priv->objectForFormat(frag->format)); |
| if (pf) { |
| if (priv->buffer().at(frag->stringPosition) == QTextBeginningOfFrame) { |
| Q_ASSERT(pf == f); |
| } else if (priv->buffer().at(frag->stringPosition) == QTextEndOfFrame) { |
| Q_ASSERT(pf != f); |
| cf = pf; |
| cb = 0; |
| goto end; |
| } |
| } |
| } |
| } |
| cb = map.previous(cb); |
| } |
| end: |
| return *this; |
| } |
| |
| /*! |
| \class QTextBlockUserData |
| \reentrant |
| |
| \brief The QTextBlockUserData class is used to associate custom data with blocks of text. |
| \since 4.1 |
| |
| \ingroup richtext-processing |
| |
| QTextBlockUserData provides an abstract interface for container classes that are used |
| to associate application-specific user data with text blocks in a QTextDocument. |
| |
| Generally, subclasses of this class provide functions to allow data to be stored |
| and retrieved, and instances are attached to blocks of text using |
| QTextBlock::setUserData(). This makes it possible to store additional data per text |
| block in a way that can be retrieved safely by the application. |
| |
| Each subclass should provide a reimplementation of the destructor to ensure that any |
| private data is automatically cleaned up when user data objects are deleted. |
| |
| \sa QTextBlock |
| */ |
| |
| /*! |
| Destroys the user data. |
| */ |
| QTextBlockUserData::~QTextBlockUserData() |
| { |
| } |
| |
| /*! |
| \class QTextBlock |
| \reentrant |
| |
| \brief The QTextBlock class provides a container for text fragments in a |
| QTextDocument. |
| |
| \ingroup richtext-processing |
| |
| A text block encapsulates a block or paragraph of text in a QTextDocument. |
| QTextBlock provides read-only access to the block/paragraph structure of |
| QTextDocuments. It is mainly of use if you want to implement your own |
| layouts for the visual representation of a QTextDocument, or if you want to |
| iterate over a document and write out the contents in your own custom |
| format. |
| |
| Text blocks are created by their parent documents. If you need to create |
| a new text block, or modify the contents of a document while examining its |
| contents, use the cursor-based interface provided by QTextCursor instead. |
| |
| Each text block is located at a specific position() in a document(). |
| The contents of the block can be obtained by using the text() function. |
| The length() function determines the block's size within the document |
| (including formatting characters). |
| The visual properties of the block are determined by its text layout(), |
| its charFormat(), and its blockFormat(). |
| |
| The next() and previous() functions enable iteration over consecutive |
| valid blocks in a document under the condition that the document is not |
| modified by other means during the iteration process. Note that, although |
| blocks are returned in sequence, adjacent blocks may come from different |
| places in the document structure. The validity of a block can be determined |
| by calling isValid(). |
| |
| QTextBlock provides comparison operators to make it easier to work with |
| blocks: \l operator==() compares two block for equality, \l operator!=() |
| compares two blocks for inequality, and \l operator<() determines whether |
| a block precedes another in the same document. |
| |
| \img qtextblock-sequence.png |
| |
| \sa QTextBlockFormat QTextCharFormat QTextFragment |
| */ |
| |
| /*! |
| \fn QTextBlock::QTextBlock(QTextDocumentPrivate *priv, int b) |
| |
| \internal |
| */ |
| |
| /*! |
| \fn QTextBlock::QTextBlock() |
| |
| \internal |
| */ |
| |
| /*! |
| \fn QTextBlock::QTextBlock(const QTextBlock &other) |
| |
| Copies the \a other text block's attributes to this text block. |
| */ |
| |
| /*! |
| \fn bool QTextBlock::isValid() const |
| |
| Returns true if this text block is valid; otherwise returns false. |
| */ |
| |
| /*! |
| \fn QTextBlock &QTextBlock::operator=(const QTextBlock &other) |
| |
| Assigns the \a other text block to this text block. |
| */ |
| |
| /*! |
| \fn bool QTextBlock::operator==(const QTextBlock &other) const |
| |
| Returns true if this text block is the same as the \a other text |
| block. |
| */ |
| |
| /*! |
| \fn bool QTextBlock::operator!=(const QTextBlock &other) const |
| |
| Returns true if this text block is different from the \a other |
| text block. |
| */ |
| |
| /*! |
| \fn bool QTextBlock::operator<(const QTextBlock &other) const |
| |
| Returns true if this text block occurs before the \a other text |
| block in the document. |
| */ |
| |
| /*! |
| \class QTextBlock::iterator |
| \reentrant |
| |
| \brief The QTextBlock::iterator class provides an iterator for reading |
| the contents of a QTextBlock. |
| |
| \ingroup richtext-processing |
| |
| A block consists of a sequence of text fragments. This class provides |
| a way to iterate over these, and read their contents. It does not provide |
| a way to modify the internal structure or contents of the block. |
| |
| An iterator can be constructed and used to access the fragments within |
| a text block in the following way: |
| |
| \snippet doc/src/snippets/textblock-fragments/xmlwriter.cpp 4 |
| \snippet doc/src/snippets/textblock-fragments/xmlwriter.cpp 7 |
| |
| \sa QTextFragment |
| */ |
| |
| /*! |
| \typedef QTextBlock::Iterator |
| |
| Qt-style synonym for QTextBlock::iterator. |
| */ |
| |
| /*! |
| \fn QTextBlock::iterator::iterator() |
| |
| Constructs an iterator for this text block. |
| */ |
| |
| /*! |
| \fn QTextBlock::iterator::iterator(const iterator &other) |
| |
| Copy constructor. Constructs a copy of the \a other iterator. |
| */ |
| |
| /*! |
| \fn bool QTextBlock::iterator::atEnd() const |
| |
| Returns true if the current item is the last item in the text block. |
| */ |
| |
| /*! |
| \fn bool QTextBlock::iterator::operator==(const iterator &other) const |
| |
| Retuns true if this iterator is the same as the \a other iterator; |
| otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QTextBlock::iterator::operator!=(const iterator &other) const |
| |
| Retuns true if this iterator is different from the \a other iterator; |
| otherwise returns false. |
| */ |
| |
| /*! |
| \fn QTextBlock::iterator QTextBlock::iterator::operator++(int) |
| |
| The postfix ++ operator (\c{i++}) advances the iterator to the |
| next item in the text block and returns an iterator to the old current |
| item. |
| */ |
| |
| /*! |
| \fn QTextBlock::iterator QTextBlock::iterator::operator--(int) |
| |
| The postfix -- operator (\c{i--}) makes the preceding item current and |
| returns an iterator to the old current item. |
| */ |
| |
| /*! |
| \fn QTextDocumentPrivate *QTextBlock::docHandle() const |
| |
| \internal |
| */ |
| |
| /*! |
| \fn int QTextBlock::fragmentIndex() const |
| |
| \internal |
| */ |
| |
| /*! |
| Returns the index of the block's first character within the document. |
| */ |
| int QTextBlock::position() const |
| { |
| if (!p || !n) |
| return 0; |
| |
| return p->blockMap().position(n); |
| } |
| |
| /*! |
| Returns the length of the block in characters. |
| |
| \note The length returned includes all formatting characters, |
| for example, newline. |
| |
| \sa text() charFormat() blockFormat() |
| */ |
| int QTextBlock::length() const |
| { |
| if (!p || !n) |
| return 0; |
| |
| return p->blockMap().size(n); |
| } |
| |
| /*! |
| Returns true if the given \a position is located within the text |
| block; otherwise returns false. |
| */ |
| bool QTextBlock::contains(int position) const |
| { |
| if (!p || !n) |
| return false; |
| |
| int pos = p->blockMap().position(n); |
| int len = p->blockMap().size(n); |
| return position >= pos && position < pos + len; |
| } |
| |
| /*! |
| Returns the QTextLayout that is used to lay out and display the |
| block's contents. |
| |
| Note that the returned QTextLayout object can only be modified from the |
| documentChanged implementation of a QAbstractTextDocumentLayout subclass. |
| Any changes applied from the outside cause undefined behavior. |
| |
| \sa clearLayout() |
| */ |
| QTextLayout *QTextBlock::layout() const |
| { |
| if (!p || !n) |
| return 0; |
| |
| const QTextBlockData *b = p->blockMap().fragment(n); |
| if (!b->layout) |
| b->layout = new QTextLayout(*this); |
| return b->layout; |
| } |
| |
| /*! |
| \since 4.4 |
| Clears the QTextLayout that is used to lay out and display the |
| block's contents. |
| |
| \sa layout() |
| */ |
| void QTextBlock::clearLayout() |
| { |
| if (!p || !n) |
| return; |
| |
| const QTextBlockData *b = p->blockMap().fragment(n); |
| if (b->layout) |
| b->layout->clearLayout(); |
| } |
| |
| /*! |
| Returns the QTextBlockFormat that describes block-specific properties. |
| |
| \sa charFormat() |
| */ |
| QTextBlockFormat QTextBlock::blockFormat() const |
| { |
| if (!p || !n) |
| return QTextFormat().toBlockFormat(); |
| |
| return p->formatCollection()->blockFormat(p->blockMap().fragment(n)->format); |
| } |
| |
| /*! |
| Returns an index into the document's internal list of block formats |
| for the text block's format. |
| |
| \sa QTextDocument::allFormats() |
| */ |
| int QTextBlock::blockFormatIndex() const |
| { |
| if (!p || !n) |
| return -1; |
| |
| return p->blockMap().fragment(n)->format; |
| } |
| |
| /*! |
| Returns the QTextCharFormat that describes the block's character |
| format. The block's character format is used when inserting text into |
| an empty block. |
| |
| \sa blockFormat() |
| */ |
| QTextCharFormat QTextBlock::charFormat() const |
| { |
| if (!p || !n) |
| return QTextFormat().toCharFormat(); |
| |
| return p->formatCollection()->charFormat(charFormatIndex()); |
| } |
| |
| /*! |
| Returns an index into the document's internal list of character formats |
| for the text block's character format. |
| |
| \sa QTextDocument::allFormats() |
| */ |
| int QTextBlock::charFormatIndex() const |
| { |
| if (!p || !n) |
| return -1; |
| |
| return p->blockCharFormatIndex(n); |
| } |
| |
| /*! |
| \since 4.7 |
| |
| Returns the resolved text direction. |
| |
| If the block has no explicit direction set, it will resolve the |
| direction from the blocks content. Returns either Qt::LeftToRight |
| or Qt::RightToLeft. |
| |
| \sa QTextFormat::layoutDirection(), QString::isRightToLeft(), Qt::LayoutDirection |
| */ |
| Qt::LayoutDirection QTextBlock::textDirection() const |
| { |
| Qt::LayoutDirection dir = blockFormat().layoutDirection(); |
| if (dir != Qt::LayoutDirectionAuto) |
| return dir; |
| |
| dir = p->defaultTextOption.textDirection(); |
| if (dir != Qt::LayoutDirectionAuto) |
| return dir; |
| |
| const QString buffer = p->buffer(); |
| |
| const int pos = position(); |
| QTextDocumentPrivate::FragmentIterator it = p->find(pos); |
| QTextDocumentPrivate::FragmentIterator end = p->find(pos + length() - 1); // -1 to omit the block separator char |
| for (; it != end; ++it) { |
| const QTextFragmentData * const frag = it.value(); |
| const QChar *p = buffer.constData() + frag->stringPosition; |
| const QChar * const end = p + frag->size_array[0]; |
| while (p < end) { |
| switch(QChar::direction(p->unicode())) |
| { |
| case QChar::DirL: |
| return Qt::LeftToRight; |
| case QChar::DirR: |
| case QChar::DirAL: |
| return Qt::RightToLeft; |
| default: |
| break; |
| } |
| ++p; |
| } |
| } |
| return Qt::LeftToRight; |
| } |
| |
| /*! |
| Returns the block's contents as plain text. |
| |
| \sa length() charFormat() blockFormat() |
| */ |
| QString QTextBlock::text() const |
| { |
| if (!p || !n) |
| return QString(); |
| |
| const QString buffer = p->buffer(); |
| QString text; |
| text.reserve(length()); |
| |
| const int pos = position(); |
| QTextDocumentPrivate::FragmentIterator it = p->find(pos); |
| QTextDocumentPrivate::FragmentIterator end = p->find(pos + length() - 1); // -1 to omit the block separator char |
| for (; it != end; ++it) { |
| const QTextFragmentData * const frag = it.value(); |
| text += QString::fromRawData(buffer.constData() + frag->stringPosition, frag->size_array[0]); |
| } |
| |
| return text; |
| } |
| |
| |
| /*! |
| Returns the text document this text block belongs to, or 0 if the |
| text block does not belong to any document. |
| */ |
| const QTextDocument *QTextBlock::document() const |
| { |
| return p ? p->document() : 0; |
| } |
| |
| /*! |
| If the block represents a list item, returns the list that the item belongs |
| to; otherwise returns 0. |
| */ |
| QTextList *QTextBlock::textList() const |
| { |
| if (!isValid()) |
| return 0; |
| |
| const QTextBlockFormat fmt = blockFormat(); |
| QTextObject *obj = p->document()->objectForFormat(fmt); |
| return qobject_cast<QTextList *>(obj); |
| } |
| |
| /*! |
| \since 4.1 |
| |
| Returns a pointer to a QTextBlockUserData object if previously set with |
| setUserData() or a null pointer. |
| */ |
| QTextBlockUserData *QTextBlock::userData() const |
| { |
| if (!p || !n) |
| return 0; |
| |
| const QTextBlockData *b = p->blockMap().fragment(n); |
| return b->userData; |
| } |
| |
| /*! |
| \since 4.1 |
| |
| Attaches the given \a data object to the text block. |
| |
| QTextBlockUserData can be used to store custom settings. The |
| ownership is passed to the underlying text document, i.e. the |
| provided QTextBlockUserData object will be deleted if the |
| corresponding text block gets deleted. The user data object is |
| not stored in the undo history, so it will not be available after |
| undoing the deletion of a text block. |
| |
| For example, if you write a programming editor in an IDE, you may |
| want to let your user set breakpoints visually in your code for an |
| integrated debugger. In a programming editor a line of text |
| usually corresponds to one QTextBlock. The QTextBlockUserData |
| interface allows the developer to store data for each QTextBlock, |
| like for example in which lines of the source code the user has a |
| breakpoint set. Of course this could also be stored externally, |
| but by storing it inside the QTextDocument, it will for example be |
| automatically deleted when the user deletes the associated |
| line. It's really just a way to store custom information in the |
| QTextDocument without using custom properties in QTextFormat which |
| would affect the undo/redo stack. |
| */ |
| void QTextBlock::setUserData(QTextBlockUserData *data) |
| { |
| if (!p || !n) |
| return; |
| |
| const QTextBlockData *b = p->blockMap().fragment(n); |
| if (data != b->userData) |
| delete b->userData; |
| b->userData = data; |
| } |
| |
| /*! |
| \since 4.1 |
| |
| Returns the integer value previously set with setUserState() or -1. |
| */ |
| int QTextBlock::userState() const |
| { |
| if (!p || !n) |
| return -1; |
| |
| const QTextBlockData *b = p->blockMap().fragment(n); |
| return b->userState; |
| } |
| |
| /*! |
| \since 4.1 |
| |
| Stores the specified \a state integer value in the text block. This may be |
| useful for example in a syntax highlighter to store a text parsing state. |
| */ |
| void QTextBlock::setUserState(int state) |
| { |
| if (!p || !n) |
| return; |
| |
| const QTextBlockData *b = p->blockMap().fragment(n); |
| b->userState = state; |
| } |
| |
| /*! |
| \since 4.4 |
| |
| Returns the blocks revision. |
| |
| \sa setRevision(), QTextDocument::revision() |
| */ |
| int QTextBlock::revision() const |
| { |
| if (!p || !n) |
| return -1; |
| |
| const QTextBlockData *b = p->blockMap().fragment(n); |
| return b->revision; |
| } |
| |
| /*! |
| \since 4.4 |
| |
| Sets a blocks revision to \a rev. |
| |
| \sa revision(), QTextDocument::revision() |
| */ |
| void QTextBlock::setRevision(int rev) |
| { |
| if (!p || !n) |
| return; |
| |
| const QTextBlockData *b = p->blockMap().fragment(n); |
| b->revision = rev; |
| } |
| |
| /*! |
| \since 4.4 |
| |
| Returns true if the block is visible; otherwise returns false. |
| |
| \sa setVisible() |
| */ |
| bool QTextBlock::isVisible() const |
| { |
| if (!p || !n) |
| return true; |
| |
| const QTextBlockData *b = p->blockMap().fragment(n); |
| return !b->hidden; |
| } |
| |
| /*! |
| \since 4.4 |
| |
| Sets the block's visibility to \a visible. |
| |
| \sa isVisible() |
| */ |
| void QTextBlock::setVisible(bool visible) |
| { |
| if (!p || !n) |
| return; |
| |
| const QTextBlockData *b = p->blockMap().fragment(n); |
| b->hidden = !visible; |
| } |
| |
| |
| /*! |
| \since 4.4 |
| |
| Returns the number of this block, or -1 if the block is invalid. |
| |
| \sa QTextCursor::blockNumber() |
| |
| */ |
| int QTextBlock::blockNumber() const |
| { |
| if (!p || !n) |
| return -1; |
| return p->blockMap().position(n, 1); |
| } |
| |
| /*! |
| \since 4.5 |
| |
| Returns the first line number of this block, or -1 if the block is invalid. |
| Unless the layout supports it, the line number is identical to the block number. |
| |
| \sa QTextBlock::blockNumber() |
| |
| */ |
| int QTextBlock::firstLineNumber() const |
| { |
| if (!p || !n) |
| return -1; |
| return p->blockMap().position(n, 2); |
| } |
| |
| |
| /*! |
| \since 4.5 |
| |
| Sets the line count to \a count. |
| |
| \sa lineCount() |
| */ |
| void QTextBlock::setLineCount(int count) |
| { |
| if (!p || !n) |
| return; |
| p->blockMap().setSize(n, count, 2); |
| } |
| /*! |
| \since 4.5 |
| |
| Returns the line count. Not all document layouts support this feature. |
| |
| \sa setLineCount() |
| */ |
| int QTextBlock::lineCount() const |
| { |
| if (!p || !n) |
| return -1; |
| return p->blockMap().size(n, 2); |
| } |
| |
| |
| /*! |
| Returns a text block iterator pointing to the beginning of the |
| text block. |
| |
| \sa end() |
| */ |
| QTextBlock::iterator QTextBlock::begin() const |
| { |
| if (!p || !n) |
| return iterator(); |
| |
| int pos = position(); |
| int len = length() - 1; // exclude the fragment that holds the paragraph separator |
| int b = p->fragmentMap().findNode(pos); |
| int e = p->fragmentMap().findNode(pos+len); |
| return iterator(p, b, e, b); |
| } |
| |
| /*! |
| Returns a text block iterator pointing to the end of the text |
| block. |
| |
| \sa begin() next() previous() |
| */ |
| QTextBlock::iterator QTextBlock::end() const |
| { |
| if (!p || !n) |
| return iterator(); |
| |
| int pos = position(); |
| int len = length() - 1; // exclude the fragment that holds the paragraph separator |
| int b = p->fragmentMap().findNode(pos); |
| int e = p->fragmentMap().findNode(pos+len); |
| return iterator(p, b, e, e); |
| } |
| |
| |
| /*! |
| Returns the text block in the document after this block, or an empty |
| text block if this is the last one. |
| |
| Note that the next block may be in a different frame or table to this block. |
| |
| \sa previous() begin() end() |
| */ |
| QTextBlock QTextBlock::next() const |
| { |
| if (!isValid() || !p->blockMap().isValid(n)) |
| return QTextBlock(); |
| |
| return QTextBlock(p, p->blockMap().next(n)); |
| } |
| |
| /*! |
| Returns the text block in the document before this block, or an empty text |
| block if this is the first one. |
| |
| Note that the next block may be in a different frame or table to this block. |
| |
| \sa next() begin() end() |
| */ |
| QTextBlock QTextBlock::previous() const |
| { |
| if (!p) |
| return QTextBlock(); |
| |
| return QTextBlock(p, p->blockMap().previous(n)); |
| } |
| |
| |
| /*! |
| Returns the text fragment the iterator currently points to. |
| */ |
| QTextFragment QTextBlock::iterator::fragment() const |
| { |
| int ne = n; |
| int formatIndex = p->fragmentMap().fragment(n)->format; |
| do { |
| ne = p->fragmentMap().next(ne); |
| } while (ne != e && p->fragmentMap().fragment(ne)->format == formatIndex); |
| return QTextFragment(p, n, ne); |
| } |
| |
| /*! |
| The prefix ++ operator (\c{++i}) advances the iterator to the |
| next item in the hash and returns an iterator to the new current |
| item. |
| */ |
| |
| QTextBlock::iterator &QTextBlock::iterator::operator++() |
| { |
| int ne = n; |
| int formatIndex = p->fragmentMap().fragment(n)->format; |
| do { |
| ne = p->fragmentMap().next(ne); |
| } while (ne != e && p->fragmentMap().fragment(ne)->format == formatIndex); |
| n = ne; |
| return *this; |
| } |
| |
| /*! |
| The prefix -- operator (\c{--i}) makes the preceding item |
| current and returns an iterator pointing to the new current item. |
| */ |
| |
| QTextBlock::iterator &QTextBlock::iterator::operator--() |
| { |
| n = p->fragmentMap().previous(n); |
| |
| if (n == b) |
| return *this; |
| |
| int formatIndex = p->fragmentMap().fragment(n)->format; |
| int last = n; |
| |
| while (n != b && p->fragmentMap().fragment(n)->format != formatIndex) { |
| last = n; |
| n = p->fragmentMap().previous(n); |
| } |
| |
| n = last; |
| return *this; |
| } |
| |
| |
| /*! |
| \class QTextFragment |
| \reentrant |
| |
| \brief The QTextFragment class holds a piece of text in a |
| QTextDocument with a single QTextCharFormat. |
| |
| \ingroup richtext-processing |
| |
| A text fragment describes a piece of text that is stored with a single |
| character format. Text in which the character format changes can be |
| represented by sequences of text fragments with different formats. |
| |
| If the user edits the text in a fragment and introduces a different |
| character format, the fragment's text will be split at each point where |
| the format changes, and new fragments will be created. |
| For example, changing the style of some text in the middle of a |
| sentence will cause the fragment to be broken into three separate fragments: |
| the first and third with the same format as before, and the second with |
| the new style. The first fragment will contain the text from the beginning |
| of the sentence, the second will contain the text from the middle, and the |
| third takes the text from the end of the sentence. |
| |
| \img qtextfragment-split.png |
| |
| A fragment's text and character format can be obtained with the text() |
| and charFormat() functions. The length() function gives the length of |
| the text in the fragment. position() gives the position in the document |
| of the start of the fragment. To determine whether the fragment contains |
| a particular position within the document, use the contains() function. |
| |
| \sa QTextDocument, {Rich Text Document Structure} |
| */ |
| |
| /*! |
| \fn QTextFragment::QTextFragment(const QTextDocumentPrivate *priv, int f, int fe) |
| \internal |
| */ |
| |
| /*! |
| \fn QTextFragment::QTextFragment() |
| |
| Creates a new empty text fragment. |
| */ |
| |
| /*! |
| \fn QTextFragment::QTextFragment(const QTextFragment &other) |
| |
| Copies the content (text and format) of the \a other text fragment |
| to this text fragment. |
| */ |
| |
| /*! |
| \fn QTextFragment &QTextFragment::operator=(const QTextFragment |
| &other) |
| |
| Assigns the content (text and format) of the \a other text fragment |
| to this text fragment. |
| */ |
| |
| /*! |
| \fn bool QTextFragment::isValid() const |
| |
| Returns true if this is a valid text fragment (i.e. has a valid |
| position in a document); otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QTextFragment::operator==(const QTextFragment &other) const |
| |
| Returns true if this text fragment is the same (at the same |
| position) as the \a other text fragment; otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QTextFragment::operator!=(const QTextFragment &other) const |
| |
| Returns true if this text fragment is different (at a different |
| position) from the \a other text fragment; otherwise returns |
| false. |
| */ |
| |
| /*! |
| \fn bool QTextFragment::operator<(const QTextFragment &other) const |
| |
| Returns true if this text fragment appears earlier in the document |
| than the \a other text fragment; otherwise returns false. |
| */ |
| |
| |
| /*! |
| Returns the position of this text fragment in the document. |
| */ |
| int QTextFragment::position() const |
| { |
| if (!p || !n) |
| return 0; // ### -1 instead? |
| |
| return p->fragmentMap().position(n); |
| } |
| |
| /*! |
| Returns the number of characters in the text fragment. |
| |
| \sa text() |
| */ |
| int QTextFragment::length() const |
| { |
| if (!p || !n) |
| return 0; |
| |
| int len = 0; |
| int f = n; |
| while (f != ne) { |
| len += p->fragmentMap().size(f); |
| f = p->fragmentMap().next(f); |
| } |
| return len; |
| } |
| |
| /*! |
| Returns true if the text fragment contains the text at the given |
| \a position in the document; otherwise returns false. |
| */ |
| bool QTextFragment::contains(int position) const |
| { |
| if (!p || !n) |
| return false; |
| int pos = this->position(); |
| return position >= pos && position < pos + length(); |
| } |
| |
| /*! |
| Returns the text fragment's character format. |
| |
| \sa text() |
| */ |
| QTextCharFormat QTextFragment::charFormat() const |
| { |
| if (!p || !n) |
| return QTextCharFormat(); |
| const QTextFragmentData *data = p->fragmentMap().fragment(n); |
| return p->formatCollection()->charFormat(data->format); |
| } |
| |
| /*! |
| Returns an index into the document's internal list of character formats |
| for the text fragment's character format. |
| |
| \sa QTextDocument::allFormats() |
| */ |
| int QTextFragment::charFormatIndex() const |
| { |
| if (!p || !n) |
| return -1; |
| const QTextFragmentData *data = p->fragmentMap().fragment(n); |
| return data->format; |
| } |
| |
| /*! |
| Returns the text fragment's as plain text. |
| |
| \sa length(), charFormat() |
| */ |
| QString QTextFragment::text() const |
| { |
| if (!p || !n) |
| return QString(); |
| |
| QString result; |
| QString buffer = p->buffer(); |
| int f = n; |
| while (f != ne) { |
| const QTextFragmentData * const frag = p->fragmentMap().fragment(f); |
| result += QString(buffer.constData() + frag->stringPosition, frag->size_array[0]); |
| f = p->fragmentMap().next(f); |
| } |
| return result; |
| } |
| |
| QT_END_NAMESPACE |