source: trunk/src/gui/text/qtextobject.cpp@ 605

Last change on this file since 605 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 43.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qtextobject.h"
43#include "qtextobject_p.h"
44#include "qtextdocument.h"
45#include "qtextformat_p.h"
46#include "qtextdocument_p.h"
47#include "qtextcursor.h"
48#include "qtextlist.h"
49#include "qabstracttextdocumentlayout.h"
50#include "qtextengine_p.h"
51#include "qdebug.h"
52
53QT_BEGIN_NAMESPACE
54
55// ### DOC: We ought to explain the CONCEPT of objectIndexes if
56// relevant to the public API
57/*!
58 \class QTextObject
59 \reentrant
60
61 \brief The QTextObject class is a base class for different kinds
62 of objects that can group parts of a QTextDocument together.
63
64 \ingroup richtext-processing
65
66 The common grouping text objects are lists (QTextList), frames
67 (QTextFrame), and tables (QTextTable). A text object has an
68 associated format() and document().
69
70 There are essentially two kinds of text objects: those that are used
71 with blocks (block formats), and those that are used with characters
72 (character formats). The first kind are derived from QTextBlockGroup,
73 and the second kind from QTextFrame.
74
75 You rarely need to use this class directly. When creating custom text
76 objects, you will also need to reimplement QTextDocument::createObject()
77 which acts as a factory method for creating text objects.
78
79 \sa QTextDocument, {Text Object Example}
80*/
81
82/*!
83 \fn QTextObject::QTextObject(QTextDocument *document)
84
85 Creates a new QTextObject for the given \a document.
86
87 \warning This function should never be called directly, but only
88 from QTextDocument::createObject().
89*/
90QTextObject::QTextObject(QTextDocument *doc)
91 : QObject(*new QTextObjectPrivate(doc), doc)
92{
93}
94
95/*!
96 \fn QTextObject::QTextObject(QTextObjectPrivate &p, QTextDocument *document)
97
98 \internal
99*/
100QTextObject::QTextObject(QTextObjectPrivate &p, QTextDocument *doc)
101 : QObject(p, doc)
102{
103}
104
105/*!
106 Destroys the text object.
107
108 \warning Text objects are owned by the document, so you should
109 never destroy them yourself.
110*/
111QTextObject::~QTextObject()
112{
113}
114
115/*!
116 Returns the text object's format.
117
118 \sa setFormat() document()
119*/
120QTextFormat QTextObject::format() const
121{
122 Q_D(const QTextObject);
123 return d->pieceTable->formatCollection()->objectFormat(d->objectIndex);
124}
125
126/*!
127 Returns the index of the object's format in the document's internal
128 list of formats.
129
130 \sa QTextDocument::allFormats()
131*/
132int QTextObject::formatIndex() const
133{
134 Q_D(const QTextObject);
135 return d->pieceTable->formatCollection()->objectFormatIndex(d->objectIndex);
136}
137
138
139/*!
140 Sets the text object's \a format.
141
142 \sa format()
143*/
144void QTextObject::setFormat(const QTextFormat &format)
145{
146 Q_D(QTextObject);
147 int idx = d->pieceTable->formatCollection()->indexForFormat(format);
148 d->pieceTable->changeObjectFormat(this, idx);
149}
150
151/*!
152 Returns the object index of this object. This can be used together with
153 QTextFormat::setObjectIndex().
154*/
155int QTextObject::objectIndex() const
156{
157 Q_D(const QTextObject);
158 return d->objectIndex;
159}
160
161/*!
162 Returns the document this object belongs to.
163
164 \sa format()
165*/
166QTextDocument *QTextObject::document() const
167{
168 return static_cast<QTextDocument *>(parent());
169}
170
171/*!
172 \internal
173*/
174QTextDocumentPrivate *QTextObject::docHandle() const
175{
176 return static_cast<const QTextDocument *>(parent())->docHandle();
177}
178
179/*!
180 \class QTextBlockGroup
181 \reentrant
182
183 \brief The QTextBlockGroup class provides a container for text blocks within
184 a QTextDocument.
185
186 \ingroup richtext-processing
187
188 Block groups can be used to organize blocks of text within a document.
189 They maintain an up-to-date list of the text blocks that belong to
190 them, even when text blocks are being edited.
191
192 Each group has a parent document which is specified when the group is
193 constructed.
194
195 Text blocks can be inserted into a group with blockInserted(), and removed
196 with blockRemoved(). If a block's format is changed, blockFormatChanged()
197 is called.
198
199 The list of blocks in the group is returned by blockList(). Note that the
200 blocks in the list are not necessarily adjacent elements in the document;
201 for example, the top-level items in a multi-level list will be separated
202 by the items in lower levels of the list.
203
204 \sa QTextBlock QTextDocument
205*/
206
207void QTextBlockGroupPrivate::markBlocksDirty()
208{
209 for (int i = 0; i < blocks.count(); ++i) {
210 const QTextBlock &block = blocks.at(i);
211 pieceTable->documentChange(block.position(), block.length());
212 }
213}
214
215/*!
216 \fn QTextBlockGroup::QTextBlockGroup(QTextDocument *document)
217
218 Creates a new new block group for the given \a document.
219
220 \warning This function should only be called from
221 QTextDocument::createObject().
222*/
223QTextBlockGroup::QTextBlockGroup(QTextDocument *doc)
224 : QTextObject(*new QTextBlockGroupPrivate(doc), doc)
225{
226}
227
228/*!
229 \internal
230*/
231QTextBlockGroup::QTextBlockGroup(QTextBlockGroupPrivate &p, QTextDocument *doc)
232 : QTextObject(p, doc)
233{
234}
235
236/*!
237 Destroys this block group; the blocks are not deleted, they simply
238 don't belong to this block anymore.
239*/
240QTextBlockGroup::~QTextBlockGroup()
241{
242}
243
244// ### DOC: Shouldn't this be insertBlock()?
245/*!
246 Appends the given \a block to the end of the group.
247
248 \warning If you reimplement this function you must call the base
249 class implementation.
250*/
251void QTextBlockGroup::blockInserted(const QTextBlock &block)
252{
253 Q_D(QTextBlockGroup);
254 QTextBlockGroupPrivate::BlockList::Iterator it = qLowerBound(d->blocks.begin(), d->blocks.end(), block);
255 d->blocks.insert(it, block);
256 d->markBlocksDirty();
257}
258
259// ### DOC: Shouldn't this be removeBlock()?
260/*!
261 Removes the given \a block from the group; the block itself is not
262 deleted, it simply isn't a member of this group anymore.
263*/
264void QTextBlockGroup::blockRemoved(const QTextBlock &block)
265{
266 Q_D(QTextBlockGroup);
267 d->blocks.removeAll(block);
268 d->markBlocksDirty();
269 if (d->blocks.isEmpty()) {
270 document()->docHandle()->deleteObject(this);
271 return;
272 }
273}
274
275/*!
276 This function is called whenever the specified \a block of text is changed.
277 The text block is a member of this group.
278
279 The base class implementation does nothing.
280*/
281void QTextBlockGroup::blockFormatChanged(const QTextBlock &)
282{
283}
284
285/*!
286 Returns a (possibly empty) list of all the blocks that are part of
287 the block group.
288*/
289QList<QTextBlock> QTextBlockGroup::blockList() const
290{
291 Q_D(const QTextBlockGroup);
292 return d->blocks;
293}
294
295
296
297QTextFrameLayoutData::~QTextFrameLayoutData()
298{
299}
300
301
302/*!
303 \class QTextFrame
304 \reentrant
305
306 \brief The QTextFrame class represents a frame in a QTextDocument.
307
308 \ingroup richtext-processing
309
310 Text frames provide structure for the text in a document. They are used
311 as generic containers for other document elements.
312 Frames are usually created by using QTextCursor::insertFrame().
313
314 \omit
315 Each frame in a document consists of a frame start character,
316 QChar(0xFDD0), followed by the frame's contents, followed by a
317 frame end character, QChar(0xFDD1). The character formats of the
318 start and end character contain a reference to the frame object's
319 objectIndex.
320 \endomit
321
322 Frames can be used to create hierarchical structures in rich text documents.
323 Each document has a root frame (QTextDocument::rootFrame()), and each frame
324 beneath the root frame has a parent frame and a (possibly empty) list of
325 child frames. The parent frame can be found with parentFrame(), and the
326 childFrames() function provides a list of child frames.
327
328 Each frame contains at least one text block to enable text cursors to
329 insert new document elements within. As a result, the QTextFrame::iterator
330 class is used to traverse both the blocks and child frames within a given
331 frame. The first and last child elements in the frame can be found with
332 begin() and end().
333
334 A frame also has a format (specified using QTextFrameFormat) which can be set
335 with setFormat() and read with format().
336
337 Text cursors can be obtained that point to the first and last valid cursor
338 positions within a frame; use the firstCursorPosition() and
339 lastCursorPosition() functions for this. The frame's extent in the
340 document can be found with firstPosition() and lastPosition().
341
342 You can iterate over a frame's contents using the
343 QTextFrame::iterator class: this provides read-only access to its
344 internal list of text blocks and child frames.
345
346 \sa QTextCursor QTextDocument
347*/
348
349/*!
350 \typedef QTextFrame::Iterator
351
352 Qt-style synonym for QTextFrame::iterator.
353*/
354
355/*!
356 \fn QTextFrame *QTextFrame::iterator::parentFrame() const
357
358 Returns the parent frame of the current frame.
359
360 \sa currentFrame() QTextFrame::parentFrame()
361*/
362
363/*!
364 \fn bool QTextFrame::iterator::operator==(const iterator &other) const
365
366 Retuns true if the iterator is the same as the \a other iterator;
367 otherwise returns false.
368*/
369
370/*!
371 \fn bool QTextFrame::iterator::operator!=(const iterator &other) const
372
373 Retuns true if the iterator is different from the \a other iterator;
374 otherwise returns false.
375*/
376
377/*!
378 \fn QTextFrame::iterator QTextFrame::iterator::operator++(int)
379
380 The postfix ++ operator (\c{i++}) advances the iterator to the
381 next item in the text frame, and returns an iterator to the old item.
382*/
383
384/*!
385 \fn QTextFrame::iterator QTextFrame::iterator::operator--(int)
386
387 The postfix -- operator (\c{i--}) makes the preceding item in the
388 current frame, and returns an iterator to the old item.
389*/
390
391/*!
392 \fn void QTextFrame::setFrameFormat(const QTextFrameFormat &format)
393
394 Sets the frame's \a format.
395
396 \sa frameFormat()
397*/
398
399/*!
400 \fn QTextFrameFormat QTextFrame::frameFormat() const
401
402 Returns the frame's format.
403
404 \sa setFrameFormat()
405*/
406
407/*!
408 \fn QTextFrame::QTextFrame(QTextDocument *document)
409
410 Creates a new empty frame for the text \a document.
411*/
412QTextFrame::QTextFrame(QTextDocument *doc)
413 : QTextObject(*new QTextFramePrivate(doc), doc)
414{
415}
416
417// ### DOC: What does this do to child frames?
418/*!
419 Destroys the frame, and removes it from the document's layout.
420*/
421QTextFrame::~QTextFrame()
422{
423 Q_D(QTextFrame);
424 delete d->layoutData;
425}
426
427/*!
428 \internal
429*/
430QTextFrame::QTextFrame(QTextFramePrivate &p, QTextDocument *doc)
431 : QTextObject(p, doc)
432{
433}
434
435/*!
436 Returns a (possibly empty) list of the frame's child frames.
437
438 \sa parentFrame()
439*/
440QList<QTextFrame *> QTextFrame::childFrames() const
441{
442 Q_D(const QTextFrame);
443 return d->childFrames;
444}
445
446/*!
447 Returns the frame's parent frame. If the frame is the root frame of a
448 document, this will return 0.
449
450 \sa childFrames() QTextDocument::rootFrame()
451*/
452QTextFrame *QTextFrame::parentFrame() const
453{
454 Q_D(const QTextFrame);
455 return d->parentFrame;
456}
457
458
459/*!
460 Returns the first cursor position inside the frame.
461
462 \sa lastCursorPosition() firstPosition() lastPosition()
463*/
464QTextCursor QTextFrame::firstCursorPosition() const
465{
466 Q_D(const QTextFrame);
467 return QTextCursor(d->pieceTable, firstPosition());
468}
469
470/*!
471 Returns the last cursor position inside the frame.
472
473 \sa firstCursorPosition() firstPosition() lastPosition()
474*/
475QTextCursor QTextFrame::lastCursorPosition() const
476{
477 Q_D(const QTextFrame);
478 return QTextCursor(d->pieceTable, lastPosition());
479}
480
481/*!
482 Returns the first document position inside the frame.
483
484 \sa lastPosition() firstCursorPosition() lastCursorPosition()
485*/
486int QTextFrame::firstPosition() const
487{
488 Q_D(const QTextFrame);
489 if (!d->fragment_start)
490 return 0;
491 return d->pieceTable->fragmentMap().position(d->fragment_start) + 1;
492}
493
494/*!
495 Returns the last document position inside the frame.
496
497 \sa firstPosition() firstCursorPosition() lastCursorPosition()
498*/
499int QTextFrame::lastPosition() const
500{
501 Q_D(const QTextFrame);
502 if (!d->fragment_end)
503 return d->pieceTable->length() - 1;
504 return d->pieceTable->fragmentMap().position(d->fragment_end);
505}
506
507/*!
508 \internal
509*/
510QTextFrameLayoutData *QTextFrame::layoutData() const
511{
512 Q_D(const QTextFrame);
513 return d->layoutData;
514}
515
516/*!
517 \internal
518*/
519void QTextFrame::setLayoutData(QTextFrameLayoutData *data)
520{
521 Q_D(QTextFrame);
522 delete d->layoutData;
523 d->layoutData = data;
524}
525
526
527
528void QTextFramePrivate::fragmentAdded(const QChar &type, uint fragment)
529{
530 if (type == QTextBeginningOfFrame) {
531 Q_ASSERT(!fragment_start);
532 fragment_start = fragment;
533 } else if (type == QTextEndOfFrame) {
534 Q_ASSERT(!fragment_end);
535 fragment_end = fragment;
536 } else if (type == QChar::ObjectReplacementCharacter) {
537 Q_ASSERT(!fragment_start);
538 Q_ASSERT(!fragment_end);
539 fragment_start = fragment;
540 fragment_end = fragment;
541 } else {
542 Q_ASSERT(false);
543 }
544}
545
546void QTextFramePrivate::fragmentRemoved(const QChar &type, uint fragment)
547{
548 Q_UNUSED(fragment); // --release warning
549 if (type == QTextBeginningOfFrame) {
550 Q_ASSERT(fragment_start == fragment);
551 fragment_start = 0;
552 } else if (type == QTextEndOfFrame) {
553 Q_ASSERT(fragment_end == fragment);
554 fragment_end = 0;
555 } else if (type == QChar::ObjectReplacementCharacter) {
556 Q_ASSERT(fragment_start == fragment);
557 Q_ASSERT(fragment_end == fragment);
558 fragment_start = 0;
559 fragment_end = 0;
560 } else {
561 Q_ASSERT(false);
562 }
563 remove_me();
564}
565
566
567void QTextFramePrivate::remove_me()
568{
569 Q_Q(QTextFrame);
570 if (fragment_start == 0 && fragment_end == 0
571 && !parentFrame) {
572 q->document()->docHandle()->deleteObject(q);
573 return;
574 }
575
576 if (!parentFrame)
577 return;
578
579 int index = parentFrame->d_func()->childFrames.indexOf(q);
580
581 // iterator over all children and move them to the parent
582 for (int i = 0; i < childFrames.size(); ++i) {
583 QTextFrame *c = childFrames.at(i);
584 parentFrame->d_func()->childFrames.insert(index, c);
585 c->d_func()->parentFrame = parentFrame;
586 ++index;
587 }
588 Q_ASSERT(parentFrame->d_func()->childFrames.at(index) == q);
589 parentFrame->d_func()->childFrames.removeAt(index);
590
591 childFrames.clear();
592 parentFrame = 0;
593}
594
595/*!
596 \class QTextFrame::iterator
597 \reentrant
598
599 \brief The iterator class provides an iterator for reading
600 the contents of a QTextFrame.
601
602 \ingroup richtext-processing
603
604 A frame consists of an arbitrary sequence of \l{QTextBlock}s and
605 child \l{QTextFrame}s. This class provides a way to iterate over the
606 child objects of a frame, and read their contents. It does not provide
607 a way to modify the contents of the frame.
608
609*/
610
611/*!
612 \fn bool QTextFrame::iterator::atEnd() const
613
614 Returns true if the current item is the last item in the text frame.
615*/
616
617/*!
618 Returns an iterator pointing to the first document element inside the frame.
619
620 \sa end()
621*/
622QTextFrame::iterator QTextFrame::begin() const
623{
624 const QTextDocumentPrivate *priv = docHandle();
625 int b = priv->blockMap().findNode(firstPosition());
626 int e = priv->blockMap().findNode(lastPosition()+1);
627 return iterator(const_cast<QTextFrame *>(this), b, b, e);
628}
629
630/*!
631 Returns an iterator pointing to the last document element inside the frame.
632
633 \sa begin()
634*/
635QTextFrame::iterator QTextFrame::end() const
636{
637 const QTextDocumentPrivate *priv = docHandle();
638 int b = priv->blockMap().findNode(firstPosition());
639 int e = priv->blockMap().findNode(lastPosition()+1);
640 return iterator(const_cast<QTextFrame *>(this), e, b, e);
641}
642
643/*!
644 Constructs an invalid iterator.
645*/
646QTextFrame::iterator::iterator()
647{
648 f = 0;
649 b = 0;
650 e = 0;
651 cf = 0;
652 cb = 0;
653}
654
655/*!
656 \internal
657*/
658QTextFrame::iterator::iterator(QTextFrame *frame, int block, int begin, int end)
659{
660 f = frame;
661 b = begin;
662 e = end;
663 cf = 0;
664 cb = block;
665}
666
667/*!
668 Copy constructor. Constructs a copy of the \a other iterator.
669*/
670QTextFrame::iterator::iterator(const iterator &other)
671{
672 f = other.f;
673 b = other.b;
674 e = other.e;
675 cf = other.cf;
676 cb = other.cb;
677}
678
679/*!
680 Assigns \a other to this iterator and returns a reference to
681 this iterator.
682*/
683QTextFrame::iterator &QTextFrame::iterator::operator=(const iterator &other)
684{
685 f = other.f;
686 b = other.b;
687 e = other.e;
688 cf = other.cf;
689 cb = other.cb;
690 return *this;
691}
692
693/*!
694 Returns the current frame pointed to by the iterator, or 0 if the
695 iterator currently points to a block.
696
697 \sa currentBlock()
698*/
699QTextFrame *QTextFrame::iterator::currentFrame() const
700{
701 return cf;
702}
703
704/*!
705 Returns the current block the iterator points to. If the iterator
706 points to a child frame, the returned block is invalid.
707
708 \sa currentFrame()
709*/
710QTextBlock QTextFrame::iterator::currentBlock() const
711{
712 if (!f)
713 return QTextBlock();
714 return QTextBlock(f->docHandle(), cb);
715}
716
717/*!
718 Moves the iterator to the next frame or block.
719
720 \sa currentBlock() currentFrame()
721*/
722QTextFrame::iterator &QTextFrame::iterator::operator++()
723{
724 const QTextDocumentPrivate *priv = f->docHandle();
725 const QTextDocumentPrivate::BlockMap &map = priv->blockMap();
726 if (cf) {
727 int end = cf->lastPosition() + 1;
728 cb = map.findNode(end);
729 cf = 0;
730 } else if (cb) {
731 cb = map.next(cb);
732 if (cb == e)
733 return *this;
734
735 if (!f->d_func()->childFrames.isEmpty()) {
736 int pos = map.position(cb);
737 // check if we entered a frame
738 QTextDocumentPrivate::FragmentIterator frag = priv->find(pos-1);
739 if (priv->buffer().at(frag->stringPosition) != QChar::ParagraphSeparator) {
740 QTextFrame *nf = qobject_cast<QTextFrame *>(priv->objectForFormat(frag->format));
741 if (nf) {
742 if (priv->buffer().at(frag->stringPosition) == QTextBeginningOfFrame && nf != f) {
743 cf = nf;
744 cb = 0;
745 } else {
746 Q_ASSERT(priv->buffer().at(frag->stringPosition) != QTextEndOfFrame);
747 }
748 }
749 }
750 }
751 }
752 return *this;
753}
754
755/*!
756 Moves the iterator to the previous frame or block.
757
758 \sa currentBlock() currentFrame()
759*/
760QTextFrame::iterator &QTextFrame::iterator::operator--()
761{
762 const QTextDocumentPrivate *priv = f->docHandle();
763 const QTextDocumentPrivate::BlockMap &map = priv->blockMap();
764 if (cf) {
765 int start = cf->firstPosition() - 1;
766 cb = map.findNode(start);
767 cf = 0;
768 } else {
769 if (cb == b)
770 goto end;
771 if (cb != e) {
772 int pos = map.position(cb);
773 // check if we have to enter a frame
774 QTextDocumentPrivate::FragmentIterator frag = priv->find(pos-1);
775 if (priv->buffer().at(frag->stringPosition) != QChar::ParagraphSeparator) {
776 QTextFrame *pf = qobject_cast<QTextFrame *>(priv->objectForFormat(frag->format));
777 if (pf) {
778 if (priv->buffer().at(frag->stringPosition) == QTextBeginningOfFrame) {
779 Q_ASSERT(pf == f);
780 } else if (priv->buffer().at(frag->stringPosition) == QTextEndOfFrame) {
781 Q_ASSERT(pf != f);
782 cf = pf;
783 cb = 0;
784 goto end;
785 }
786 }
787 }
788 }
789 cb = map.previous(cb);
790 }
791 end:
792 return *this;
793}
794
795/*!
796 \class QTextBlockUserData
797 \reentrant
798
799 \brief The QTextBlockUserData class is used to associate custom data with blocks of text.
800 \since 4.1
801
802 \ingroup richtext-processing
803
804 QTextBlockUserData provides an abstract interface for container classes that are used
805 to associate application-specific user data with text blocks in a QTextDocument.
806
807 Generally, subclasses of this class provide functions to allow data to be stored
808 and retrieved, and instances are attached to blocks of text using
809 QTextBlock::setUserData(). This makes it possible to store additional data per text
810 block in a way that can be retrieved safely by the application.
811
812 Each subclass should provide a reimplementation of the destructor to ensure that any
813 private data is automatically cleaned up when user data objects are deleted.
814
815 \sa QTextBlock
816*/
817
818/*!
819 Destroys the user data.
820*/
821QTextBlockUserData::~QTextBlockUserData()
822{
823}
824
825/*!
826 \class QTextBlock
827 \reentrant
828
829 \brief The QTextBlock class provides a container for text fragments in a
830 QTextDocument.
831
832 \ingroup richtext-processing
833
834 A text block encapsulates a block or paragraph of text in a QTextDocument.
835 QTextBlock provides read-only access to the block/paragraph structure of
836 QTextDocuments. It is mainly of use if you want to implement your own
837 layouts for the visual representation of a QTextDocument, or if you want to
838 iterate over a document and write out the contents in your own custom
839 format.
840
841 Text blocks are created by their parent documents. If you need to create
842 a new text block, or modify the contents of a document while examining its
843 contents, use the cursor-based interface provided by QTextCursor instead.
844
845 Each text block is located at a specific position() in a document().
846 The contents of the block can be obtained by using the text() function.
847 The length() function determines the block's size within the document
848 (including formatting characters).
849 The visual properties of the block are determined by its text layout(),
850 its charFormat(), and its blockFormat().
851
852 The next() and previous() functions enable iteration over consecutive
853 valid blocks in a document under the condition that the document is not
854 modified by other means during the iteration process. Note that, although
855 blocks are returned in sequence, adjacent blocks may come from different
856 places in the document structure. The validity of a block can be determined
857 by calling isValid().
858
859 QTextBlock provides comparison operators to make it easier to work with
860 blocks: \l operator==() compares two block for equality, \l operator!=()
861 compares two blocks for inequality, and \l operator<() determines whether
862 a block precedes another in the same document.
863
864 \img qtextblock-sequence.png
865
866 \sa QTextBlockFormat QTextCharFormat QTextFragment
867 */
868
869/*!
870 \fn QTextBlock::QTextBlock(QTextDocumentPrivate *priv, int b)
871
872 \internal
873*/
874
875/*!
876 \fn QTextBlock::QTextBlock()
877
878 \internal
879*/
880
881/*!
882 \fn QTextBlock::QTextBlock(const QTextBlock &other)
883
884 Copies the \a other text block's attributes to this text block.
885*/
886
887/*!
888 \fn bool QTextBlock::isValid() const
889
890 Returns true if this text block is valid; otherwise returns false.
891*/
892
893/*!
894 \fn QTextBlock &QTextBlock::operator=(const QTextBlock &other)
895
896 Assigns the \a other text block to this text block.
897*/
898
899/*!
900 \fn bool QTextBlock::operator==(const QTextBlock &other) const
901
902 Returns true if this text block is the same as the \a other text
903 block.
904*/
905
906/*!
907 \fn bool QTextBlock::operator!=(const QTextBlock &other) const
908
909 Returns true if this text block is different from the \a other
910 text block.
911*/
912
913/*!
914 \fn bool QTextBlock::operator<(const QTextBlock &other) const
915
916 Returns true if this text block occurs before the \a other text
917 block in the document.
918*/
919
920/*!
921 \class QTextBlock::iterator
922 \reentrant
923
924 \brief The QTextBlock::iterator class provides an iterator for reading
925 the contents of a QTextBlock.
926
927 \ingroup richtext-processing
928
929 A block consists of a sequence of text fragments. This class provides
930 a way to iterate over these, and read their contents. It does not provide
931 a way to modify the internal structure or contents of the block.
932
933 An iterator can be constructed and used to access the fragments within
934 a text block in the following way:
935
936 \snippet doc/src/snippets/textblock-fragments/xmlwriter.cpp 4
937 \snippet doc/src/snippets/textblock-fragments/xmlwriter.cpp 7
938
939 \sa QTextFragment
940*/
941
942/*!
943 \typedef QTextBlock::Iterator
944
945 Qt-style synonym for QTextBlock::iterator.
946*/
947
948/*!
949 \fn QTextBlock::iterator::iterator()
950
951 Constructs an iterator for this text block.
952*/
953
954/*!
955 \fn QTextBlock::iterator::iterator(const iterator &other)
956
957 Copy constructor. Constructs a copy of the \a other iterator.
958*/
959
960/*!
961 \fn bool QTextBlock::iterator::atEnd() const
962
963 Returns true if the current item is the last item in the text block.
964*/
965
966/*!
967 \fn bool QTextBlock::iterator::operator==(const iterator &other) const
968
969 Retuns true if this iterator is the same as the \a other iterator;
970 otherwise returns false.
971*/
972
973/*!
974 \fn bool QTextBlock::iterator::operator!=(const iterator &other) const
975
976 Retuns true if this iterator is different from the \a other iterator;
977 otherwise returns false.
978*/
979
980/*!
981 \fn QTextBlock::iterator QTextBlock::iterator::operator++(int)
982
983 The postfix ++ operator (\c{i++}) advances the iterator to the
984 next item in the text block and returns an iterator to the old current
985 item.
986*/
987
988/*!
989 \fn QTextBlock::iterator QTextBlock::iterator::operator--(int)
990
991 The postfix -- operator (\c{i--}) makes the preceding item current and
992 returns an iterator to the old current item.
993*/
994
995/*!
996 \fn QTextDocumentPrivate *QTextBlock::docHandle() const
997
998 \internal
999*/
1000
1001/*!
1002 \fn int QTextBlock::fragmentIndex() const
1003
1004 \internal
1005*/
1006
1007/*!
1008 Returns the index of the block's first character within the document.
1009 */
1010int QTextBlock::position() const
1011{
1012 if (!p || !n)
1013 return 0;
1014
1015 return p->blockMap().position(n);
1016}
1017
1018/*!
1019 Returns the length of the block in characters.
1020
1021 \note The length returned includes all formatting characters,
1022 for example, newline.
1023
1024 \sa text() charFormat() blockFormat()
1025 */
1026int QTextBlock::length() const
1027{
1028 if (!p || !n)
1029 return 0;
1030
1031 return p->blockMap().size(n);
1032}
1033
1034/*!
1035 Returns true if the given \a position is located within the text
1036 block; otherwise returns false.
1037 */
1038bool QTextBlock::contains(int position) const
1039{
1040 if (!p || !n)
1041 return false;
1042
1043 int pos = p->blockMap().position(n);
1044 int len = p->blockMap().size(n);
1045 return position >= pos && position < pos + len;
1046}
1047
1048/*!
1049 Returns the QTextLayout that is used to lay out and display the
1050 block's contents.
1051
1052 Note that the returned QTextLayout object can only be modified from the
1053 documentChanged implementation of a QAbstractTextDocumentLayout subclass.
1054 Any changes applied from the outside cause undefined behavior.
1055
1056 \sa clearLayout()
1057 */
1058QTextLayout *QTextBlock::layout() const
1059{
1060 if (!p || !n)
1061 return 0;
1062
1063 const QTextBlockData *b = p->blockMap().fragment(n);
1064 if (!b->layout)
1065 b->layout = new QTextLayout(*this);
1066 return b->layout;
1067}
1068
1069/*!
1070 \since 4.4
1071 Clears the QTextLayout that is used to lay out and display the
1072 block's contents.
1073
1074 \sa layout()
1075 */
1076void QTextBlock::clearLayout()
1077{
1078 if (!p || !n)
1079 return;
1080
1081 const QTextBlockData *b = p->blockMap().fragment(n);
1082 if (b->layout)
1083 b->layout->clearLayout();
1084}
1085
1086/*!
1087 Returns the QTextBlockFormat that describes block-specific properties.
1088
1089 \sa charFormat()
1090 */
1091QTextBlockFormat QTextBlock::blockFormat() const
1092{
1093 if (!p || !n)
1094 return QTextFormat().toBlockFormat();
1095
1096 return p->formatCollection()->blockFormat(p->blockMap().fragment(n)->format);
1097}
1098
1099/*!
1100 Returns an index into the document's internal list of block formats
1101 for the text block's format.
1102
1103 \sa QTextDocument::allFormats()
1104*/
1105int QTextBlock::blockFormatIndex() const
1106{
1107 if (!p || !n)
1108 return -1;
1109
1110 return p->blockMap().fragment(n)->format;
1111}
1112
1113/*!
1114 Returns the QTextCharFormat that describes the block's character
1115 format. The block's character format is used when inserting text into
1116 an empty block.
1117
1118 \sa blockFormat()
1119 */
1120QTextCharFormat QTextBlock::charFormat() const
1121{
1122 if (!p || !n)
1123 return QTextFormat().toCharFormat();
1124
1125 return p->formatCollection()->charFormat(charFormatIndex());
1126}
1127
1128/*!
1129 Returns an index into the document's internal list of character formats
1130 for the text block's character format.
1131
1132 \sa QTextDocument::allFormats()
1133*/
1134int QTextBlock::charFormatIndex() const
1135{
1136 if (!p || !n)
1137 return -1;
1138
1139 return p->blockCharFormatIndex(n);
1140}
1141
1142/*!
1143 Returns the block's contents as plain text.
1144
1145 \sa length() charFormat() blockFormat()
1146 */
1147QString QTextBlock::text() const
1148{
1149 if (!p || !n)
1150 return QString();
1151
1152 const QString buffer = p->buffer();
1153 QString text;
1154 text.reserve(length());
1155
1156 const int pos = position();
1157 QTextDocumentPrivate::FragmentIterator it = p->find(pos);
1158 QTextDocumentPrivate::FragmentIterator end = p->find(pos + length() - 1); // -1 to omit the block separator char
1159 for (; it != end; ++it) {
1160 const QTextFragmentData * const frag = it.value();
1161 text += QString::fromRawData(buffer.constData() + frag->stringPosition, frag->size_array[0]);
1162 }
1163
1164 return text;
1165}
1166
1167
1168/*!
1169 Returns the text document this text block belongs to, or 0 if the
1170 text block does not belong to any document.
1171*/
1172const QTextDocument *QTextBlock::document() const
1173{
1174 return p ? p->document() : 0;
1175}
1176
1177/*!
1178 If the block represents a list item, returns the list that the item belongs
1179 to; otherwise returns 0.
1180*/
1181QTextList *QTextBlock::textList() const
1182{
1183 if (!isValid())
1184 return 0;
1185
1186 const QTextBlockFormat fmt = blockFormat();
1187 QTextObject *obj = p->document()->objectForFormat(fmt);
1188 return qobject_cast<QTextList *>(obj);
1189}
1190
1191/*!
1192 \since 4.1
1193
1194 Returns a pointer to a QTextBlockUserData object if previously set with
1195 setUserData() or a null pointer.
1196*/
1197QTextBlockUserData *QTextBlock::userData() const
1198{
1199 if (!p || !n)
1200 return 0;
1201
1202 const QTextBlockData *b = p->blockMap().fragment(n);
1203 return b->userData;
1204}
1205
1206/*!
1207 \since 4.1
1208
1209 Attaches the given \a data object to the text block.
1210
1211 QTextBlockUserData can be used to store custom settings. The
1212 ownership is passed to the underlying text document, i.e. the
1213 provided QTextBlockUserData object will be deleted if the
1214 corresponding text block gets deleted. The user data object is
1215 not stored in the undo history, so it will not be available after
1216 undoing the deletion of a text block.
1217
1218 For example, if you write a programming editor in an IDE, you may
1219 want to let your user set breakpoints visually in your code for an
1220 integrated debugger. In a programming editor a line of text
1221 usually corresponds to one QTextBlock. The QTextBlockUserData
1222 interface allows the developer to store data for each QTextBlock,
1223 like for example in which lines of the source code the user has a
1224 breakpoint set. Of course this could also be stored externally,
1225 but by storing it inside the QTextDocument, it will for example be
1226 automatically deleted when the user deletes the associated
1227 line. It's really just a way to store custom information in the
1228 QTextDocument without using custom properties in QTextFormat which
1229 would affect the undo/redo stack.
1230*/
1231void QTextBlock::setUserData(QTextBlockUserData *data)
1232{
1233 if (!p || !n)
1234 return;
1235
1236 const QTextBlockData *b = p->blockMap().fragment(n);
1237 if (data != b->userData)
1238 delete b->userData;
1239 b->userData = data;
1240}
1241
1242/*!
1243 \since 4.1
1244
1245 Returns the integer value previously set with setUserState() or -1.
1246*/
1247int QTextBlock::userState() const
1248{
1249 if (!p || !n)
1250 return -1;
1251
1252 const QTextBlockData *b = p->blockMap().fragment(n);
1253 return b->userState;
1254}
1255
1256/*!
1257 \since 4.1
1258
1259 Stores the specified \a state integer value in the text block. This may be
1260 useful for example in a syntax highlighter to store a text parsing state.
1261*/
1262void QTextBlock::setUserState(int state)
1263{
1264 if (!p || !n)
1265 return;
1266
1267 const QTextBlockData *b = p->blockMap().fragment(n);
1268 b->userState = state;
1269}
1270
1271/*!
1272 \since 4.4
1273
1274 Returns the blocks revision.
1275
1276 \sa setRevision(), QTextDocument::revision()
1277*/
1278int QTextBlock::revision() const
1279{
1280 if (!p || !n)
1281 return -1;
1282
1283 const QTextBlockData *b = p->blockMap().fragment(n);
1284 return b->revision;
1285}
1286
1287/*!
1288 \since 4.4
1289
1290 Sets a blocks revision to \a rev.
1291
1292 \sa revision(), QTextDocument::revision()
1293*/
1294void QTextBlock::setRevision(int rev)
1295{
1296 if (!p || !n)
1297 return;
1298
1299 const QTextBlockData *b = p->blockMap().fragment(n);
1300 b->revision = rev;
1301}
1302
1303/*!
1304 \since 4.4
1305
1306 Returns true if the block is visible; otherwise returns false.
1307
1308 \sa setVisible()
1309*/
1310bool QTextBlock::isVisible() const
1311{
1312 if (!p || !n)
1313 return true;
1314
1315 const QTextBlockData *b = p->blockMap().fragment(n);
1316 return !b->hidden;
1317}
1318
1319/*!
1320 \since 4.4
1321
1322 Sets the block's visibility to \a visible.
1323
1324 \sa isVisible()
1325*/
1326void QTextBlock::setVisible(bool visible)
1327{
1328 if (!p || !n)
1329 return;
1330
1331 const QTextBlockData *b = p->blockMap().fragment(n);
1332 b->hidden = !visible;
1333}
1334
1335
1336/*!
1337\since 4.4
1338
1339 Returns the number of this block, or -1 if the block is invalid.
1340
1341 \sa QTextCursor::blockNumber()
1342
1343*/
1344int QTextBlock::blockNumber() const
1345{
1346 if (!p || !n)
1347 return -1;
1348 return p->blockMap().position(n, 1);
1349}
1350
1351/*!
1352\since 4.5
1353
1354 Returns the first line number of this block, or -1 if the block is invalid.
1355 Unless the layout supports it, the line number is identical to the block number.
1356
1357 \sa QTextBlock::blockNumber()
1358
1359*/
1360int QTextBlock::firstLineNumber() const
1361{
1362 if (!p || !n)
1363 return -1;
1364 return p->blockMap().position(n, 2);
1365}
1366
1367
1368/*!
1369\since 4.5
1370
1371Sets the line count to \a count.