summaryrefslogtreecommitdiffstats
path: root/src/gui/text/qtextobject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text/qtextobject.cpp')
-rw-r--r--src/gui/text/qtextobject.cpp1785
1 files changed, 1785 insertions, 0 deletions
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
new file mode 100644
index 0000000000..5c1c8b9edc
--- /dev/null
+++ b/src/gui/text/qtextobject.cpp
@@ -0,0 +1,1785 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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.
+*/
+
+bool QTextBlock::isValid() const
+{
+ return p != 0 && p->blockMap().isValid(n);
+}
+
+/*!
+ \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())
+ 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 glyphs of this text fragment. The positions of the glyphs are
+ relative to the position of the QTextBlock's layout.
+
+ \sa QGlyphs, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphs()
+*/
+#if !defined(QT_NO_RAWFONT)
+QList<QGlyphs> QTextFragment::glyphs() const
+{
+ if (!p || !n)
+ return QList<QGlyphs>();
+
+ int pos = position();
+ int len = length();
+ if (len == 0)
+ return QList<QGlyphs>();
+
+ int blockNode = p->blockMap().findNode(pos);
+
+ const QTextBlockData *blockData = p->blockMap().fragment(blockNode);
+ QTextLayout *layout = blockData->layout;
+
+ QList<QGlyphs> ret;
+ for (int i=0; i<layout->lineCount(); ++i) {
+ QTextLine textLine = layout->lineAt(i);
+ ret += textLine.glyphs(pos, len);
+ }
+
+ return ret;
+}
+#endif // QT_NO_RAWFONT
+
+/*!
+ 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