1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
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
53 QT_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 */
QTextObject(QTextDocument * doc)90 QTextObject::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 */
QTextObject(QTextObjectPrivate & p,QTextDocument * doc)100 QTextObject::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 */
~QTextObject()111 QTextObject::~QTextObject()
112 {
113 }
114
115 /*!
116 Returns the text object's format.
117
118 \sa setFormat() document()
119 */
format() const120 QTextFormat 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 */
formatIndex() const132 int 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 */
setFormat(const QTextFormat & format)144 void 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 */
objectIndex() const155 int 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 */
document() const166 QTextDocument *QTextObject::document() const
167 {
168 return static_cast<QTextDocument *>(parent());
169 }
170
171 /*!
172 \internal
173 */
docHandle() const174 QTextDocumentPrivate *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
markBlocksDirty()207 void 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 */
QTextBlockGroup(QTextDocument * doc)223 QTextBlockGroup::QTextBlockGroup(QTextDocument *doc)
224 : QTextObject(*new QTextBlockGroupPrivate(doc), doc)
225 {
226 }
227
228 /*!
229 \internal
230 */
QTextBlockGroup(QTextBlockGroupPrivate & p,QTextDocument * doc)231 QTextBlockGroup::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 */
~QTextBlockGroup()240 QTextBlockGroup::~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 */
blockInserted(const QTextBlock & block)251 void 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 */
blockRemoved(const QTextBlock & block)264 void 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 */
blockFormatChanged(const QTextBlock &)281 void 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 */
blockList() const289 QList<QTextBlock> QTextBlockGroup::blockList() const
290 {
291 Q_D(const QTextBlockGroup);
292 return d->blocks;
293 }
294
295
296
~QTextFrameLayoutData()297 QTextFrameLayoutData::~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 */
QTextFrame(QTextDocument * doc)412 QTextFrame::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 */
~QTextFrame()421 QTextFrame::~QTextFrame()
422 {
423 Q_D(QTextFrame);
424 delete d->layoutData;
425 }
426
427 /*!
428 \internal
429 */
QTextFrame(QTextFramePrivate & p,QTextDocument * doc)430 QTextFrame::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 */
childFrames() const440 QList<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 */
parentFrame() const452 QTextFrame *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 */
firstCursorPosition() const464 QTextCursor 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 */
lastCursorPosition() const475 QTextCursor 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 */
firstPosition() const486 int 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 */
lastPosition() const499 int 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 */
layoutData() const510 QTextFrameLayoutData *QTextFrame::layoutData() const
511 {
512 Q_D(const QTextFrame);
513 return d->layoutData;
514 }
515
516 /*!
517 \internal
518 */
setLayoutData(QTextFrameLayoutData * data)519 void QTextFrame::setLayoutData(QTextFrameLayoutData *data)
520 {
521 Q_D(QTextFrame);
522 delete d->layoutData;
523 d->layoutData = data;
524 }
525
526
527
fragmentAdded(const QChar & type,uint fragment)528 void 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
fragmentRemoved(const QChar & type,uint fragment)546 void 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
remove_me()567 void 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 Please see the document \l{STL-style-Iterators} for more information.
620
621 \sa end()
622 */
begin() const623 QTextFrame::iterator QTextFrame::begin() const
624 {
625 const QTextDocumentPrivate *priv = docHandle();
626 int b = priv->blockMap().findNode(firstPosition());
627 int e = priv->blockMap().findNode(lastPosition()+1);
628 return iterator(const_cast<QTextFrame *>(this), b, b, e);
629 }
630
631 /*!
632 Returns an iterator pointing to the position past the last document element inside the frame.
633 Please see the document \l{STL-Style Iterators} for more information.
634 \sa begin()
635 */
end() const636 QTextFrame::iterator QTextFrame::end() const
637 {
638 const QTextDocumentPrivate *priv = docHandle();
639 int b = priv->blockMap().findNode(firstPosition());
640 int e = priv->blockMap().findNode(lastPosition()+1);
641 return iterator(const_cast<QTextFrame *>(this), e, b, e);
642 }
643
644 /*!
645 Constructs an invalid iterator.
646 */
iterator()647 QTextFrame::iterator::iterator()
648 {
649 f = 0;
650 b = 0;
651 e = 0;
652 cf = 0;
653 cb = 0;
654 }
655
656 /*!
657 \internal
658 */
iterator(QTextFrame * frame,int block,int begin,int end)659 QTextFrame::iterator::iterator(QTextFrame *frame, int block, int begin, int end)
660 {
661 f = frame;
662 b = begin;
663 e = end;
664 cf = 0;
665 cb = block;
666 }
667
668 /*!
669 Copy constructor. Constructs a copy of the \a other iterator.
670 */
iterator(const iterator & other)671 QTextFrame::iterator::iterator(const iterator &other)
672 {
673 f = other.f;
674 b = other.b;
675 e = other.e;
676 cf = other.cf;
677 cb = other.cb;
678 }
679
680 /*!
681 Assigns \a other to this iterator and returns a reference to
682 this iterator.
683 */
operator =(const iterator & other)684 QTextFrame::iterator &QTextFrame::iterator::operator=(const iterator &other)
685 {
686 f = other.f;
687 b = other.b;
688 e = other.e;
689 cf = other.cf;
690 cb = other.cb;
691 return *this;
692 }
693
694 /*!
695 Returns the current frame pointed to by the iterator, or 0 if the
696 iterator currently points to a block.
697
698 \sa currentBlock()
699 */
currentFrame() const700 QTextFrame *QTextFrame::iterator::currentFrame() const
701 {
702 return cf;
703 }
704
705 /*!
706 Returns the current block the iterator points to. If the iterator
707 points to a child frame, the returned block is invalid.
708
709 \sa currentFrame()
710 */
currentBlock() const711 QTextBlock QTextFrame::iterator::currentBlock() const
712 {
713 if (!f)
714 return QTextBlock();
715 return QTextBlock(f->docHandle(), cb);
716 }
717
718 /*!
719 Moves the iterator to the next frame or block.
720
721 \sa currentBlock() currentFrame()
722 */
operator ++()723 QTextFrame::iterator &QTextFrame::iterator::operator++()
724 {
725 const QTextDocumentPrivate *priv = f->docHandle();
726 const QTextDocumentPrivate::BlockMap &map = priv->blockMap();
727 if (cf) {
728 int end = cf->lastPosition() + 1;
729 cb = map.findNode(end);
730 cf = 0;
731 } else if (cb) {
732 cb = map.next(cb);
733 if (cb == e)
734 return *this;
735
736 if (!f->d_func()->childFrames.isEmpty()) {
737 int pos = map.position(cb);
738 // check if we entered a frame
739 QTextDocumentPrivate::FragmentIterator frag = priv->find(pos-1);
740 if (priv->buffer().at(frag->stringPosition) != QChar::ParagraphSeparator) {
741 QTextFrame *nf = qobject_cast<QTextFrame *>(priv->objectForFormat(frag->format));
742 if (nf) {
743 if (priv->buffer().at(frag->stringPosition) == QTextBeginningOfFrame && nf != f) {
744 cf = nf;
745 cb = 0;
746 } else {
747 Q_ASSERT(priv->buffer().at(frag->stringPosition) != QTextEndOfFrame);
748 }
749 }
750 }
751 }
752 }
753 return *this;
754 }
755
756 /*!
757 Moves the iterator to the previous frame or block.
758
759 \sa currentBlock() currentFrame()
760 */
operator --()761 QTextFrame::iterator &QTextFrame::iterator::operator--()
762 {
763 const QTextDocumentPrivate *priv = f->docHandle();
764 const QTextDocumentPrivate::BlockMap &map = priv->blockMap();
765 if (cf) {
766 int start = cf->firstPosition() - 1;
767 cb = map.findNode(start);
768 cf = 0;
769 } else {
770 if (cb == b)
771 goto end;
772 if (cb != e) {
773 int pos = map.position(cb);
774 // check if we have to enter a frame
775 QTextDocumentPrivate::FragmentIterator frag = priv->find(pos-1);
776 if (priv->buffer().at(frag->stringPosition) != QChar::ParagraphSeparator) {
777 QTextFrame *pf = qobject_cast<QTextFrame *>(priv->objectForFormat(frag->format));
778 if (pf) {
779 if (priv->buffer().at(frag->stringPosition) == QTextBeginningOfFrame) {
780 Q_ASSERT(pf == f);
781 } else if (priv->buffer().at(frag->stringPosition) == QTextEndOfFrame) {
782 Q_ASSERT(pf != f);
783 cf = pf;
784 cb = 0;
785 goto end;
786 }
787 }
788 }
789 }
790 cb = map.previous(cb);
791 }
792 end:
793 return *this;
794 }
795
796 /*!
797 \class QTextBlockUserData
798 \reentrant
799
800 \brief The QTextBlockUserData class is used to associate custom data with blocks of text.
801 \since 4.1
802
803 \ingroup richtext-processing
804
805 QTextBlockUserData provides an abstract interface for container classes that are used
806 to associate application-specific user data with text blocks in a QTextDocument.
807
808 Generally, subclasses of this class provide functions to allow data to be stored
809 and retrieved, and instances are attached to blocks of text using
810 QTextBlock::setUserData(). This makes it possible to store additional data per text
811 block in a way that can be retrieved safely by the application.
812
813 Each subclass should provide a reimplementation of the destructor to ensure that any
814 private data is automatically cleaned up when user data objects are deleted.
815
816 \sa QTextBlock
817 */
818
819 /*!
820 Destroys the user data.
821 */
~QTextBlockUserData()822 QTextBlockUserData::~QTextBlockUserData()
823 {
824 }
825
826 /*!
827 \class QTextBlock
828 \reentrant
829
830 \brief The QTextBlock class provides a container for text fragments in a
831 QTextDocument.
832
833 \ingroup richtext-processing
834
835 A text block encapsulates a block or paragraph of text in a QTextDocument.
836 QTextBlock provides read-only access to the block/paragraph structure of
837 QTextDocuments. It is mainly of use if you want to implement your own
838 layouts for the visual representation of a QTextDocument, or if you want to
839 iterate over a document and write out the contents in your own custom
840 format.
841
842 Text blocks are created by their parent documents. If you need to create
843 a new text block, or modify the contents of a document while examining its
844 contents, use the cursor-based interface provided by QTextCursor instead.
845
846 Each text block is located at a specific position() in a document().
847 The contents of the block can be obtained by using the text() function.
848 The length() function determines the block's size within the document
849 (including formatting characters).
850 The visual properties of the block are determined by its text layout(),
851 its charFormat(), and its blockFormat().
852
853 The next() and previous() functions enable iteration over consecutive
854 valid blocks in a document under the condition that the document is not
855 modified by other means during the iteration process. Note that, although
856 blocks are returned in sequence, adjacent blocks may come from different
857 places in the document structure. The validity of a block can be determined
858 by calling isValid().
859
860 QTextBlock provides comparison operators to make it easier to work with
861 blocks: \l operator==() compares two block for equality, \l operator!=()
862 compares two blocks for inequality, and \l operator<() determines whether
863 a block precedes another in the same document.
864
865 \img qtextblock-sequence.png
866
867 \sa QTextBlockFormat QTextCharFormat QTextFragment
868 */
869
870 /*!
871 \fn QTextBlock::QTextBlock(QTextDocumentPrivate *priv, int b)
872
873 \internal
874 */
875
876 /*!
877 \fn QTextBlock::QTextBlock()
878
879 \internal
880 */
881
882 /*!
883 \fn QTextBlock::QTextBlock(const QTextBlock &other)
884
885 Copies the \a other text block's attributes to this text block.
886 */
887
888 /*!
889 \fn bool QTextBlock::isValid() const
890
891 Returns true if this text block is valid; otherwise returns false.
892 */
893
894 /*!
895 \fn QTextBlock &QTextBlock::operator=(const QTextBlock &other)
896
897 Assigns the \a other text block to this text block.
898 */
899
900 /*!
901 \fn bool QTextBlock::operator==(const QTextBlock &other) const
902
903 Returns true if this text block is the same as the \a other text
904 block.
905 */
906
907 /*!
908 \fn bool QTextBlock::operator!=(const QTextBlock &other) const
909
910 Returns true if this text block is different from the \a other
911 text block.
912 */
913
914 /*!
915 \fn bool QTextBlock::operator<(const QTextBlock &other) const
916
917 Returns true if this text block occurs before the \a other text
918 block in the document.
919 */
920
921 /*!
922 \class QTextBlock::iterator
923 \reentrant
924
925 \brief The QTextBlock::iterator class provides an iterator for reading
926 the contents of a QTextBlock.
927
928 \ingroup richtext-processing
929
930 A block consists of a sequence of text fragments. This class provides
931 a way to iterate over these, and read their contents. It does not provide
932 a way to modify the internal structure or contents of the block.
933
934 An iterator can be constructed and used to access the fragments within
935 a text block in the following way:
936
937 \snippet doc/src/snippets/textblock-fragments/xmlwriter.cpp 4
938 \snippet doc/src/snippets/textblock-fragments/xmlwriter.cpp 7
939
940 \sa QTextFragment
941 */
942
943 /*!
944 \typedef QTextBlock::Iterator
945
946 Qt-style synonym for QTextBlock::iterator.
947 */
948
949 /*!
950 \fn QTextBlock::iterator::iterator()
951
952 Constructs an iterator for this text block.
953 */
954
955 /*!
956 \fn QTextBlock::iterator::iterator(const iterator &other)
957
958 Copy constructor. Constructs a copy of the \a other iterator.
959 */
960
961 /*!
962 \fn bool QTextBlock::iterator::atEnd() const
963
964 Returns true if the current item is the last item in the text block.
965 */
966
967 /*!
968 \fn bool QTextBlock::iterator::operator==(const iterator &other) const
969
970 Retuns true if this iterator is the same as the \a other iterator;
971 otherwise returns false.
972 */
973
974 /*!
975 \fn bool QTextBlock::iterator::operator!=(const iterator &other) const
976
977 Retuns true if this iterator is different from the \a other iterator;
978 otherwise returns false.
979 */
980
981 /*!
982 \fn QTextBlock::iterator QTextBlock::iterator::operator++(int)
983
984 The postfix ++ operator (\c{i++}) advances the iterator to the
985 next item in the text block and returns an iterator to the old current
986 item.
987 */
988
989 /*!
990 \fn QTextBlock::iterator QTextBlock::iterator::operator--(int)
991
992 The postfix -- operator (\c{i--}) makes the preceding item current and
993 returns an iterator to the old current item.
994 */
995
996 /*!
997 \fn QTextDocumentPrivate *QTextBlock::docHandle() const
998
999 \internal
1000 */
1001
1002 /*!
1003 \fn int QTextBlock::fragmentIndex() const
1004
1005 \internal
1006 */
1007
1008 /*!
1009 Returns the index of the block's first character within the document.
1010 */
position() const1011 int QTextBlock::position() const
1012 {
1013 if (!p || !n)
1014 return 0;
1015
1016 return p->blockMap().position(n);
1017 }
1018
1019 /*!
1020 Returns the length of the block in characters.
1021
1022 \note The length returned includes all formatting characters,
1023 for example, newline.
1024
1025 \sa text() charFormat() blockFormat()
1026 */
length() const1027 int QTextBlock::length() const
1028 {
1029 if (!p || !n)
1030 return 0;
1031
1032 return p->blockMap().size(n);
1033 }
1034
1035 /*!
1036 Returns true if the given \a position is located within the text
1037 block; otherwise returns false.
1038 */
contains(int position) const1039 bool QTextBlock::contains(int position) const
1040 {
1041 if (!p || !n)
1042 return false;
1043
1044 int pos = p->blockMap().position(n);
1045 int len = p->blockMap().size(n);
1046 return position >= pos && position < pos + len;
1047 }
1048
1049 /*!
1050 Returns the QTextLayout that is used to lay out and display the
1051 block's contents.
1052
1053 Note that the returned QTextLayout object can only be modified from the
1054 documentChanged implementation of a QAbstractTextDocumentLayout subclass.
1055 Any changes applied from the outside cause undefined behavior.
1056
1057 \sa clearLayout()
1058 */
layout() const1059 QTextLayout *QTextBlock::layout() const
1060 {
1061 if (!p || !n)
1062 return 0;
1063
1064 const QTextBlockData *b = p->blockMap().fragment(n);
1065 if (!b->layout)
1066 b->layout = new QTextLayout(*this);
1067 return b->layout;
1068 }
1069
1070 /*!
1071 \since 4.4
1072 Clears the QTextLayout that is used to lay out and display the
1073 block's contents.
1074
1075 \sa layout()
1076 */
clearLayout()1077 void QTextBlock::clearLayout()
1078 {
1079 if (!p || !n)
1080 return;
1081
1082 const QTextBlockData *b = p->blockMap().fragment(n);
1083 if (b->layout)
1084 b->layout->clearLayout();
1085 }
1086
1087 /*!
1088 Returns the QTextBlockFormat that describes block-specific properties.
1089
1090 \sa charFormat()
1091 */
blockFormat() const1092 QTextBlockFormat QTextBlock::blockFormat() const
1093 {
1094 if (!p || !n)
1095 return QTextFormat().toBlockFormat();
1096
1097 return p->formatCollection()->blockFormat(p->blockMap().fragment(n)->format);
1098 }
1099
1100 /*!
1101 Returns an index into the document's internal list of block formats
1102 for the text block's format.
1103
1104 \sa QTextDocument::allFormats()
1105 */
blockFormatIndex() const1106 int QTextBlock::blockFormatIndex() const
1107 {
1108 if (!p || !n)
1109 return -1;
1110
1111 return p->blockMap().fragment(n)->format;
1112 }
1113
1114 /*!
1115 Returns the QTextCharFormat that describes the block's character
1116 format. The block's character format is used when inserting text into
1117 an empty block.
1118
1119 \sa blockFormat()
1120 */
charFormat() const1121 QTextCharFormat QTextBlock::charFormat() const
1122 {
1123 if (!p || !n)
1124 return QTextFormat().toCharFormat();
1125
1126 return p->formatCollection()->charFormat(charFormatIndex());
1127 }
1128
1129 /*!
1130 Returns an index into the document's internal list of character formats
1131 for the text block's character format.
1132
1133 \sa QTextDocument::allFormats()
1134 */
charFormatIndex() const1135 int QTextBlock::charFormatIndex() const
1136 {
1137 if (!p || !n)
1138 return -1;
1139
1140 return p->blockCharFormatIndex(n);
1141 }
1142
1143 /*!
1144 \since 4.7
1145
1146 Returns the resolved text direction.
1147
1148 If the block has no explicit direction set, it will resolve the
1149 direction from the blocks content. Returns either Qt::LeftToRight
1150 or Qt::RightToLeft.
1151
1152 \sa QTextFormat::layoutDirection(), QString::isRightToLeft(), Qt::LayoutDirection
1153 */
textDirection() const1154 Qt::LayoutDirection QTextBlock::textDirection() const
1155 {
1156 Qt::LayoutDirection dir = blockFormat().layoutDirection();
1157 if (dir != Qt::LayoutDirectionAuto)
1158 return dir;
1159
1160 dir = p->defaultTextOption.textDirection();
1161 if (dir != Qt::LayoutDirectionAuto)
1162 return dir;
1163
1164 const QString buffer = p->buffer();
1165
1166 const int pos = position();
1167 QTextDocumentPrivate::FragmentIterator it = p->find(pos);
1168 QTextDocumentPrivate::FragmentIterator end = p->find(pos + length() - 1); // -1 to omit the block separator char
1169 for (; it != end; ++it) {
1170 const QTextFragmentData * const frag = it.value();
1171 const QChar *p = buffer.constData() + frag->stringPosition;
1172 const QChar * const end = p + frag->size_array[0];
1173 while (p < end) {
1174 switch(QChar::direction(p->unicode()))
1175 {
1176 case QChar::DirL:
1177 return Qt::LeftToRight;
1178 case QChar::DirR:
1179 case QChar::DirAL:
1180 return Qt::RightToLeft;
1181 default:
1182 break;
1183 }
1184 ++p;
1185 }
1186 }
1187 return Qt::LeftToRight;
1188 }
1189
1190 /*!
1191 Returns the block's contents as plain text.
1192
1193 \sa length() charFormat() blockFormat()
1194 */
text() const1195 QString QTextBlock::text() const
1196 {
1197 if (!p || !n)
1198 return QString();
1199
1200 const QString buffer = p->buffer();
1201 QString text;
1202 text.reserve(length());
1203
1204 const int pos = position();
1205 QTextDocumentPrivate::FragmentIterator it = p->find(pos);
1206 QTextDocumentPrivate::FragmentIterator end = p->find(pos + length() - 1); // -1 to omit the block separator char
1207 for (; it != end; ++it) {
1208 const QTextFragmentData * const frag = it.value();
1209 text += QString::fromRawData(buffer.constData() + frag->stringPosition, frag->size_array[0]);
1210 }
1211
1212 return text;
1213 }
1214
1215
1216 /*!
1217 Returns the text document this text block belongs to, or 0 if the
1218 text block does not belong to any document.
1219 */
document() const1220 const QTextDocument *QTextBlock::document() const
1221 {
1222 return p ? p->document() : 0;
1223 }
1224
1225 /*!
1226 If the block represents a list item, returns the list that the item belongs
1227 to; otherwise returns 0.
1228 */
textList() const1229 QTextList *QTextBlock::textList() const
1230 {
1231 if (!isValid())
1232 return 0;
1233
1234 const QTextBlockFormat fmt = blockFormat();
1235 QTextObject *obj = p->document()->objectForFormat(fmt);
1236 return qobject_cast<QTextList *>(obj);
1237 }
1238
1239 /*!
1240 \since 4.1
1241
1242 Returns a pointer to a QTextBlockUserData object if previously set with
1243 setUserData() or a null pointer.
1244 */
userData() const1245 QTextBlockUserData *QTextBlock::userData() const
1246 {
1247 if (!p || !n)
1248 return 0;
1249
1250 const QTextBlockData *b = p->blockMap().fragment(n);
1251 return b->userData;
1252 }
1253
1254 /*!
1255 \since 4.1
1256
1257 Attaches the given \a data object to the text block.
1258
1259 QTextBlockUserData can be used to store custom settings. The
1260 ownership is passed to the underlying text document, i.e. the
1261 provided QTextBlockUserData object will be deleted if the
1262 corresponding text block gets deleted. The user data object is
1263 not stored in the undo history, so it will not be available after
1264 undoing the deletion of a text block.
1265
1266 For example, if you write a programming editor in an IDE, you may
1267 want to let your user set breakpoints visually in your code for an
1268 integrated debugger. In a programming editor a line of text
1269 usually corresponds to one QTextBlock. The QTextBlockUserData
1270 interface allows the developer to store data for each QTextBlock,
1271 like for example in which lines of the source code the user has a
1272 breakpoint set. Of course this could also be stored externally,
1273 but by storing it inside the QTextDocument, it will for example be
1274 automatically deleted when the user deletes the associated
1275 line. It's really just a way to store custom information in the
1276 QTextDocument without using custom properties in QTextFormat which
1277 would affect the undo/redo stack.
1278 */
setUserData(QTextBlockUserData * data)1279 void QTextBlock::setUserData(QTextBlockUserData *data)
1280 {
1281 if (!p || !n)
1282 return;
1283
1284 const QTextBlockData *b = p->blockMap().fragment(n);
1285 if (data != b->userData)
1286 delete b->userData;
1287 b->userData = data;
1288 }
1289
1290 /*!
1291 \since 4.1
1292
1293 Returns the integer value previously set with setUserState() or -1.
1294 */
userState() const1295 int QTextBlock::userState() const
1296 {
1297 if (!p || !n)
1298 return -1;
1299
1300 const QTextBlockData *b = p->blockMap().fragment(n);
1301 return b->userState;
1302 }
1303
1304 /*!
1305 \since 4.1
1306
1307 Stores the specified \a state integer value in the text block. This may be
1308 useful for example in a syntax highlighter to store a text parsing state.
1309 */
setUserState(int state)1310 void QTextBlock::setUserState(int state)
1311 {
1312 if (!p || !n)
1313 return;
1314
1315 const QTextBlockData *b = p->blockMap().fragment(n);
1316 b->userState = state;
1317 }
1318
1319 /*!
1320 \since 4.4
1321
1322 Returns the blocks revision.
1323
1324 \sa setRevision(), QTextDocument::revision()
1325 */
revision() const1326 int QTextBlock::revision() const
1327 {
1328 if (!p || !n)
1329 return -1;
1330
1331 const QTextBlockData *b = p->blockMap().fragment(n);
1332 return b->revision;
1333 }
1334
1335 /*!
1336 \since 4.4
1337
1338 Sets a blocks revision to \a rev.
1339
1340 \sa revision(), QTextDocument::revision()
1341 */
setRevision(int rev)1342 void QTextBlock::setRevision(int rev)
1343 {
1344 if (!p || !n)
1345 return;
1346
1347 const QTextBlockData *b = p->blockMap().fragment(n);
1348 b->revision = rev;
1349 }
1350
1351 /*!
1352 \since 4.4
1353
1354 Returns true if the block is visible; otherwise returns false.
1355
1356 \sa setVisible()
1357 */
isVisible() const1358 bool QTextBlock::isVisible() const
1359 {
1360 if (!p || !n)
1361 return true;
1362
1363 const QTextBlockData *b = p->blockMap().fragment(n);
1364 return !b->hidden;
1365 }
1366
1367 /*!
1368 \since 4.4
1369
1370 Sets the block's visibility to \a visible.
1371
1372 \sa isVisible()
1373 */
setVisible(bool visible)1374 void QTextBlock::setVisible(bool visible)
1375 {
1376 if (!p || !n)
1377 return;
1378
1379 const QTextBlockData *b = p->blockMap().fragment(n);
1380 b->hidden = !visible;
1381 }
1382
1383
1384 /*!
1385 \since 4.4
1386
1387 Returns the number of this block, or -1 if the block is invalid.
1388
1389 \sa QTextCursor::blockNumber()
1390
1391 */
blockNumber() const1392 int QTextBlock::blockNumber() const
1393 {
1394 if (!p || !n)
1395 return -1;
1396 return p->blockMap().position(n, 1);
1397 }
1398
1399 /*!
1400 \since 4.5
1401
1402 Returns the first line number of this block, or -1 if the block is invalid.
1403 Unless the layout supports it, the line number is identical to the block number.
1404
1405 \sa QTextBlock::blockNumber()
1406
1407 */
firstLineNumber() const1408 int QTextBlock::firstLineNumber() const
1409 {
1410 if (!p || !n)
1411 return -1;
1412 return p->blockMap().position(n, 2);
1413 }
1414
1415
1416 /*!
1417 \since 4.5
1418
1419 Sets the line count to \a count.
1420
1421 \sa lineCount()
1422 */
setLineCount(int count)1423 void QTextBlock::setLineCount(int count)
1424 {
1425 if (!p || !n)
1426 return;
1427 p->blockMap().setSize(n, count, 2);
1428 }
1429 /*!
1430 \since 4.5
1431
1432 Returns the line count. Not all document layouts support this feature.
1433
1434 \sa setLineCount()
1435 */
lineCount() const1436 int QTextBlock::lineCount() const
1437 {
1438 if (!p || !n)
1439 return -1;
1440 return p->blockMap().size(n, 2);
1441 }
1442
1443
1444 /*!
1445 Returns a text block iterator pointing to the beginning of the
1446 text block.
1447
1448 \sa end()
1449 */
begin() const1450 QTextBlock::iterator QTextBlock::begin() const
1451 {
1452 if (!p || !n)
1453 return iterator();
1454
1455 int pos = position();
1456 int len = length() - 1; // exclude the fragment that holds the paragraph separator
1457 int b = p->fragmentMap().findNode(pos);
1458 int e = p->fragmentMap().findNode(pos+len);
1459 return iterator(p, b, e, b);
1460 }
1461
1462 /*!
1463 Returns a text block iterator pointing to the end of the text
1464 block.
1465
1466 \sa begin() next() previous()
1467 */
end() const1468 QTextBlock::iterator QTextBlock::end() const
1469 {
1470 if (!p || !n)
1471 return iterator();
1472
1473 int pos = position();
1474 int len = length() - 1; // exclude the fragment that holds the paragraph separator
1475 int b = p->fragmentMap().findNode(pos);
1476 int e = p->fragmentMap().findNode(pos+len);
1477 return iterator(p, b, e, e);
1478 }
1479
1480
1481 /*!
1482 Returns the text block in the document after this block, or an empty
1483 text block if this is the last one.
1484
1485 Note that the next block may be in a different frame or table to this block.
1486
1487 \sa previous() begin() end()
1488 */
next() const1489 QTextBlock QTextBlock::next() const
1490 {
1491 if (!isValid() || !p->blockMap().isValid(n))
1492 return QTextBlock();
1493
1494 return QTextBlock(p, p->blockMap().next(n));
1495 }
1496
1497 /*!
1498 Returns the text block in the document before this block, or an empty text
1499 block if this is the first one.
1500
1501 Note that the next block may be in a different frame or table to this block.
1502
1503 \sa next() begin() end()
1504 */
previous() const1505 QTextBlock QTextBlock::previous() const
1506 {
1507 if (!p)
1508 return QTextBlock();
1509
1510 return QTextBlock(p, p->blockMap().previous(n));
1511 }
1512
1513
1514 /*!
1515 Returns the text fragment the iterator currently points to.
1516 */
fragment() const1517 QTextFragment QTextBlock::iterator::fragment() const
1518 {
1519 int ne = n;
1520 int formatIndex = p->fragmentMap().fragment(n)->format;
1521 do {
1522 ne = p->fragmentMap().next(ne);
1523 } while (ne != e && p->fragmentMap().fragment(ne)->format == formatIndex);
1524 return QTextFragment(p, n, ne);
1525 }
1526
1527 /*!
1528 The prefix ++ operator (\c{++i}) advances the iterator to the
1529 next item in the hash and returns an iterator to the new current
1530 item.
1531 */
1532
operator ++()1533 QTextBlock::iterator &QTextBlock::iterator::operator++()
1534 {
1535 int ne = n;
1536 int formatIndex = p->fragmentMap().fragment(n)->format;
1537 do {
1538 ne = p->fragmentMap().next(ne);
1539 } while (ne != e && p->fragmentMap().fragment(ne)->format == formatIndex);
1540 n = ne;
1541 return *this;
1542 }
1543
1544 /*!
1545 The prefix -- operator (\c{--i}) makes the preceding item
1546 current and returns an iterator pointing to the new current item.
1547 */
1548
operator --()1549 QTextBlock::iterator &QTextBlock::iterator::operator--()
1550 {
1551 n = p->fragmentMap().previous(n);
1552
1553 if (n == b)
1554 return *this;
1555
1556 int formatIndex = p->fragmentMap().fragment(n)->format;
1557 int last = n;
1558
1559 while (n != b && p->fragmentMap().fragment(n)->format != formatIndex) {
1560 last = n;
1561 n = p->fragmentMap().previous(n);
1562 }
1563
1564 n = last;
1565 return *this;
1566 }
1567
1568
1569 /*!
1570 \class QTextFragment
1571 \reentrant
1572
1573 \brief The QTextFragment class holds a piece of text in a
1574 QTextDocument with a single QTextCharFormat.
1575
1576 \ingroup richtext-processing
1577
1578 A text fragment describes a piece of text that is stored with a single
1579 character format. Text in which the character format changes can be
1580 represented by sequences of text fragments with different formats.
1581
1582 If the user edits the text in a fragment and introduces a different
1583 character format, the fragment's text will be split at each point where
1584 the format changes, and new fragments will be created.
1585 For example, changing the style of some text in the middle of a
1586 sentence will cause the fragment to be broken into three separate fragments:
1587 the first and third with the same format as before, and the second with
1588 the new style. The first fragment will contain the text from the beginning
1589 of the sentence, the second will contain the text from the middle, and the
1590 third takes the text from the end of the sentence.
1591
1592 \img qtextfragment-split.png
1593
1594 A fragment's text and character format can be obtained with the text()
1595 and charFormat() functions. The length() function gives the length of
1596 the text in the fragment. position() gives the position in the document
1597 of the start of the fragment. To determine whether the fragment contains
1598 a particular position within the document, use the contains() function.
1599
1600 \sa QTextDocument, {Rich Text Document Structure}
1601 */
1602
1603 /*!
1604 \fn QTextFragment::QTextFragment(const QTextDocumentPrivate *priv, int f, int fe)
1605 \internal
1606 */
1607
1608 /*!
1609 \fn QTextFragment::QTextFragment()
1610
1611 Creates a new empty text fragment.
1612 */
1613
1614 /*!
1615 \fn QTextFragment::QTextFragment(const QTextFragment &other)
1616
1617 Copies the content (text and format) of the \a other text fragment
1618 to this text fragment.
1619 */
1620
1621 /*!
1622 \fn QTextFragment &QTextFragment::operator=(const QTextFragment
1623 &other)
1624
1625 Assigns the content (text and format) of the \a other text fragment
1626 to this text fragment.
1627 */
1628
1629 /*!
1630 \fn bool QTextFragment::isValid() const
1631
1632 Returns true if this is a valid text fragment (i.e. has a valid
1633 position in a document); otherwise returns false.
1634 */
1635
1636 /*!
1637 \fn bool QTextFragment::operator==(const QTextFragment &other) const
1638
1639 Returns true if this text fragment is the same (at the same
1640 position) as the \a other text fragment; otherwise returns false.
1641 */
1642
1643 /*!
1644 \fn bool QTextFragment::operator!=(const QTextFragment &other) const
1645
1646 Returns true if this text fragment is different (at a different
1647 position) from the \a other text fragment; otherwise returns
1648 false.
1649 */
1650
1651 /*!
1652 \fn bool QTextFragment::operator<(const QTextFragment &other) const
1653
1654 Returns true if this text fragment appears earlier in the document
1655 than the \a other text fragment; otherwise returns false.
1656 */
1657
1658 /*!
1659 Returns the glyphs of this text fragment. The positions of the glyphs are
1660 relative to the position of the QTextBlock's layout.
1661
1662 \sa QGlyphRun, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphRun()
1663 */
1664 #if !defined(QT_NO_RAWFONT)
glyphRuns() const1665 QList<QGlyphRun> QTextFragment::glyphRuns() const
1666 {
1667 if (!p || !n)
1668 return QList<QGlyphRun>();
1669
1670 int pos = position();
1671 int len = length();
1672 if (len == 0)
1673 return QList<QGlyphRun>();
1674
1675 int blockNode = p->blockMap().findNode(pos);
1676
1677 const QTextBlockData *blockData = p->blockMap().fragment(blockNode);
1678 QTextLayout *layout = blockData->layout;
1679
1680 QList<QGlyphRun> ret;
1681 for (int i=0; i<layout->lineCount(); ++i) {
1682 QTextLine textLine = layout->lineAt(i);
1683 ret += textLine.glyphs(pos, len);
1684 }
1685
1686 return ret;
1687 }
1688 #endif // QT_NO_RAWFONT
1689
1690 /*!
1691 Returns the position of this text fragment in the document.
1692 */
position() const1693 int QTextFragment::position() const
1694 {
1695 if (!p || !n)
1696 return 0; // ### -1 instead?
1697
1698 return p->fragmentMap().position(n);
1699 }
1700
1701 /*!
1702 Returns the number of characters in the text fragment.
1703
1704 \sa text()
1705 */
length() const1706 int QTextFragment::length() const
1707 {
1708 if (!p || !n)
1709 return 0;
1710
1711 int len = 0;
1712 int f = n;
1713 while (f != ne) {
1714 len += p->fragmentMap().size(f);
1715 f = p->fragmentMap().next(f);
1716 }
1717 return len;
1718 }
1719
1720 /*!
1721 Returns true if the text fragment contains the text at the given
1722 \a position in the document; otherwise returns false.
1723 */
contains(int position) const1724 bool QTextFragment::contains(int position) const
1725 {
1726 if (!p || !n)
1727 return false;
1728 int pos = this->position();
1729 return position >= pos && position < pos + length();
1730 }
1731
1732 /*!
1733 Returns the text fragment's character format.
1734
1735 \sa text()
1736 */
charFormat() const1737 QTextCharFormat QTextFragment::charFormat() const
1738 {
1739 if (!p || !n)
1740 return QTextCharFormat();
1741 const QTextFragmentData *data = p->fragmentMap().fragment(n);
1742 return p->formatCollection()->charFormat(data->format);
1743 }
1744
1745 /*!
1746 Returns an index into the document's internal list of character formats
1747 for the text fragment's character format.
1748
1749 \sa QTextDocument::allFormats()
1750 */
charFormatIndex() const1751 int QTextFragment::charFormatIndex() const
1752 {
1753 if (!p || !n)
1754 return -1;
1755 const QTextFragmentData *data = p->fragmentMap().fragment(n);
1756 return data->format;
1757 }
1758
1759 /*!
1760 Returns the text fragment's as plain text.
1761
1762 \sa length(), charFormat()
1763 */
text() const1764 QString QTextFragment::text() const
1765 {
1766 if (!p || !n)
1767 return QString();
1768
1769 QString result;
1770 QString buffer = p->buffer();
1771 int f = n;
1772 while (f != ne) {
1773 const QTextFragmentData * const frag = p->fragmentMap().fragment(f);
1774 result += QString(buffer.constData() + frag->stringPosition, frag->size_array[0]);
1775 f = p->fragmentMap().next(f);
1776 }
1777 return result;
1778 }
1779
1780 QT_END_NAMESPACE
1781