|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtGui module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
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 */ |
|
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 */ |
|
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 */ |
|
111 QTextObject::~QTextObject() |
|
112 { |
|
113 } |
|
114 |
|
115 /*! |
|
116 Returns the text object's format. |
|
117 |
|
118 \sa setFormat() document() |
|
119 */ |
|
120 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 */ |
|
132 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 */ |
|
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 */ |
|
155 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 */ |
|
166 QTextDocument *QTextObject::document() const |
|
167 { |
|
168 return static_cast<QTextDocument *>(parent()); |
|
169 } |
|
170 |
|
171 /*! |
|
172 \internal |
|
173 */ |
|
174 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 |
|
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 */ |
|
223 QTextBlockGroup::QTextBlockGroup(QTextDocument *doc) |
|
224 : QTextObject(*new QTextBlockGroupPrivate(doc), doc) |
|
225 { |
|
226 } |
|
227 |
|
228 /*! |
|
229 \internal |
|
230 */ |
|
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 */ |
|
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 */ |
|
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 */ |
|
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 */ |
|
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 */ |
|
289 QList<QTextBlock> QTextBlockGroup::blockList() const |
|
290 { |
|
291 Q_D(const QTextBlockGroup); |
|
292 return d->blocks; |
|
293 } |
|
294 |
|
295 |
|
296 |
|
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 */ |
|
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 */ |
|
421 QTextFrame::~QTextFrame() |
|
422 { |
|
423 Q_D(QTextFrame); |
|
424 delete d->layoutData; |
|
425 } |
|
426 |
|
427 /*! |
|
428 \internal |
|
429 */ |
|
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 */ |
|
440 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 */ |
|
452 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 */ |
|
464 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 */ |
|
475 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 */ |
|
486 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 */ |
|
499 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 */ |
|
510 QTextFrameLayoutData *QTextFrame::layoutData() const |
|
511 { |
|
512 Q_D(const QTextFrame); |
|
513 return d->layoutData; |
|
514 } |
|
515 |
|
516 /*! |
|
517 \internal |
|
518 */ |
|
519 void QTextFrame::setLayoutData(QTextFrameLayoutData *data) |
|
520 { |
|
521 Q_D(QTextFrame); |
|
522 delete d->layoutData; |
|
523 d->layoutData = data; |
|
524 } |
|
525 |
|
526 |
|
527 |
|
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 |
|
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 |
|
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 |
|
620 \sa end() |
|
621 */ |
|
622 QTextFrame::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 */ |
|
635 QTextFrame::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 */ |
|
646 QTextFrame::iterator::iterator() |
|
647 { |
|
648 f = 0; |
|
649 b = 0; |
|
650 e = 0; |
|
651 cf = 0; |
|
652 cb = 0; |
|
653 } |
|
654 |
|
655 /*! |
|
656 \internal |
|
657 */ |
|
658 QTextFrame::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 */ |
|
670 QTextFrame::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 */ |
|
683 QTextFrame::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 */ |
|
699 QTextFrame *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 */ |
|
710 QTextBlock 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 */ |
|
722 QTextFrame::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 */ |
|
760 QTextFrame::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 */ |
|
821 QTextBlockUserData::~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 */ |
|
1010 int 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 */ |
|
1026 int 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 */ |
|
1038 bool 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 */ |
|
1058 QTextLayout *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 */ |
|
1076 void 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 */ |
|
1091 QTextBlockFormat 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 */ |
|
1105 int 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 */ |
|
1120 QTextCharFormat 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 */ |
|
1134 int 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 */ |
|
1147 QString 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 */ |
|
1172 const 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 */ |
|
1181 QTextList *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 */ |
|
1197 QTextBlockUserData *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 */ |
|
1231 void 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 */ |
|
1247 int 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 */ |
|
1262 void 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 */ |
|
1278 int 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 */ |
|
1294 void 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 */ |
|
1310 bool 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 */ |
|
1326 void 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 */ |
|
1344 int 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 */ |
|
1360 int 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 |
|
1371 Sets the line count to \a count. |
|
1372 |
|
1373 \sa lineCount() |
|
1374 */ |
|
1375 void QTextBlock::setLineCount(int count) |
|
1376 { |
|
1377 if (!p || !n) |
|
1378 return; |
|
1379 p->blockMap().setSize(n, count, 2); |
|
1380 } |
|
1381 /*! |
|
1382 \since 4.5 |
|
1383 |
|
1384 Returns the line count. Not all document layouts support this feature. |
|
1385 |
|
1386 \sa setLineCount() |
|
1387 */ |
|
1388 int QTextBlock::lineCount() const |
|
1389 { |
|
1390 if (!p || !n) |
|
1391 return -1; |
|
1392 return p->blockMap().size(n, 2); |
|
1393 } |
|
1394 |
|
1395 |
|
1396 /*! |
|
1397 Returns a text block iterator pointing to the beginning of the |
|
1398 text block. |
|
1399 |
|
1400 \sa end() |
|
1401 */ |
|
1402 QTextBlock::iterator QTextBlock::begin() const |
|
1403 { |
|
1404 if (!p || !n) |
|
1405 return iterator(); |
|
1406 |
|
1407 int pos = position(); |
|
1408 int len = length() - 1; // exclude the fragment that holds the paragraph separator |
|
1409 int b = p->fragmentMap().findNode(pos); |
|
1410 int e = p->fragmentMap().findNode(pos+len); |
|
1411 return iterator(p, b, e, b); |
|
1412 } |
|
1413 |
|
1414 /*! |
|
1415 Returns a text block iterator pointing to the end of the text |
|
1416 block. |
|
1417 |
|
1418 \sa begin() next() previous() |
|
1419 */ |
|
1420 QTextBlock::iterator QTextBlock::end() const |
|
1421 { |
|
1422 if (!p || !n) |
|
1423 return iterator(); |
|
1424 |
|
1425 int pos = position(); |
|
1426 int len = length() - 1; // exclude the fragment that holds the paragraph separator |
|
1427 int b = p->fragmentMap().findNode(pos); |
|
1428 int e = p->fragmentMap().findNode(pos+len); |
|
1429 return iterator(p, b, e, e); |
|
1430 } |
|
1431 |
|
1432 |
|
1433 /*! |
|
1434 Returns the text block in the document after this block, or an empty |
|
1435 text block if this is the last one. |
|
1436 |
|
1437 Note that the next block may be in a different frame or table to this block. |
|
1438 |
|
1439 \sa previous() begin() end() |
|
1440 */ |
|
1441 QTextBlock QTextBlock::next() const |
|
1442 { |
|
1443 if (!p) |
|
1444 return QTextBlock(); |
|
1445 |
|
1446 return QTextBlock(p, p->blockMap().next(n)); |
|
1447 } |
|
1448 |
|
1449 /*! |
|
1450 Returns the text block in the document before this block, or an empty text |
|
1451 block if this is the first one. |
|
1452 |
|
1453 Note that the next block may be in a different frame or table to this block. |
|
1454 |
|
1455 \sa next() begin() end() |
|
1456 */ |
|
1457 QTextBlock QTextBlock::previous() const |
|
1458 { |
|
1459 if (!p) |
|
1460 return QTextBlock(); |
|
1461 |
|
1462 return QTextBlock(p, p->blockMap().previous(n)); |
|
1463 } |
|
1464 |
|
1465 |
|
1466 /*! |
|
1467 Returns the text fragment the iterator currently points to. |
|
1468 */ |
|
1469 QTextFragment QTextBlock::iterator::fragment() const |
|
1470 { |
|
1471 int ne = n; |
|
1472 int formatIndex = p->fragmentMap().fragment(n)->format; |
|
1473 do { |
|
1474 ne = p->fragmentMap().next(ne); |
|
1475 } while (ne != e && p->fragmentMap().fragment(ne)->format == formatIndex); |
|
1476 return QTextFragment(p, n, ne); |
|
1477 } |
|
1478 |
|
1479 /*! |
|
1480 The prefix ++ operator (\c{++i}) advances the iterator to the |
|
1481 next item in the hash and returns an iterator to the new current |
|
1482 item. |
|
1483 */ |
|
1484 |
|
1485 QTextBlock::iterator &QTextBlock::iterator::operator++() |
|
1486 { |
|
1487 int ne = n; |
|
1488 int formatIndex = p->fragmentMap().fragment(n)->format; |
|
1489 do { |
|
1490 ne = p->fragmentMap().next(ne); |
|
1491 } while (ne != e && p->fragmentMap().fragment(ne)->format == formatIndex); |
|
1492 n = ne; |
|
1493 return *this; |
|
1494 } |
|
1495 |
|
1496 /*! |
|
1497 The prefix -- operator (\c{--i}) makes the preceding item |
|
1498 current and returns an iterator pointing to the new current item. |
|
1499 */ |
|
1500 |
|
1501 QTextBlock::iterator &QTextBlock::iterator::operator--() |
|
1502 { |
|
1503 n = p->fragmentMap().previous(n); |
|
1504 |
|
1505 if (n == b) |
|
1506 return *this; |
|
1507 |
|
1508 int formatIndex = p->fragmentMap().fragment(n)->format; |
|
1509 int last = n; |
|
1510 |
|
1511 while (n != b && p->fragmentMap().fragment(n)->format != formatIndex) { |
|
1512 last = n; |
|
1513 n = p->fragmentMap().previous(n); |
|
1514 } |
|
1515 |
|
1516 n = last; |
|
1517 return *this; |
|
1518 } |
|
1519 |
|
1520 |
|
1521 /*! |
|
1522 \class QTextFragment |
|
1523 \reentrant |
|
1524 |
|
1525 \brief The QTextFragment class holds a piece of text in a |
|
1526 QTextDocument with a single QTextCharFormat. |
|
1527 |
|
1528 \ingroup richtext-processing |
|
1529 |
|
1530 A text fragment describes a piece of text that is stored with a single |
|
1531 character format. Text in which the character format changes can be |
|
1532 represented by sequences of text fragments with different formats. |
|
1533 |
|
1534 If the user edits the text in a fragment and introduces a different |
|
1535 character format, the fragment's text will be split at each point where |
|
1536 the format changes, and new fragments will be created. |
|
1537 For example, changing the style of some text in the middle of a |
|
1538 sentence will cause the fragment to be broken into three separate fragments: |
|
1539 the first and third with the same format as before, and the second with |
|
1540 the new style. The first fragment will contain the text from the beginning |
|
1541 of the sentence, the second will contain the text from the middle, and the |
|
1542 third takes the text from the end of the sentence. |
|
1543 |
|
1544 \img qtextfragment-split.png |
|
1545 |
|
1546 A fragment's text and character format can be obtained with the text() |
|
1547 and charFormat() functions. The length() function gives the length of |
|
1548 the text in the fragment. position() gives the position in the document |
|
1549 of the start of the fragment. To determine whether the fragment contains |
|
1550 a particular position within the document, use the contains() function. |
|
1551 |
|
1552 \sa QTextDocument, {Rich Text Document Structure} |
|
1553 */ |
|
1554 |
|
1555 /*! |
|
1556 \fn QTextFragment::QTextFragment(const QTextDocumentPrivate *priv, int f, int fe) |
|
1557 \internal |
|
1558 */ |
|
1559 |
|
1560 /*! |
|
1561 \fn QTextFragment::QTextFragment() |
|
1562 |
|
1563 Creates a new empty text fragment. |
|
1564 */ |
|
1565 |
|
1566 /*! |
|
1567 \fn QTextFragment::QTextFragment(const QTextFragment &other) |
|
1568 |
|
1569 Copies the content (text and format) of the \a other text fragment |
|
1570 to this text fragment. |
|
1571 */ |
|
1572 |
|
1573 /*! |
|
1574 \fn QTextFragment &QTextFragment::operator=(const QTextFragment |
|
1575 &other) |
|
1576 |
|
1577 Assigns the content (text and format) of the \a other text fragment |
|
1578 to this text fragment. |
|
1579 */ |
|
1580 |
|
1581 /*! |
|
1582 \fn bool QTextFragment::isValid() const |
|
1583 |
|
1584 Returns true if this is a valid text fragment (i.e. has a valid |
|
1585 position in a document); otherwise returns false. |
|
1586 */ |
|
1587 |
|
1588 /*! |
|
1589 \fn bool QTextFragment::operator==(const QTextFragment &other) const |
|
1590 |
|
1591 Returns true if this text fragment is the same (at the same |
|
1592 position) as the \a other text fragment; otherwise returns false. |
|
1593 */ |
|
1594 |
|
1595 /*! |
|
1596 \fn bool QTextFragment::operator!=(const QTextFragment &other) const |
|
1597 |
|
1598 Returns true if this text fragment is different (at a different |
|
1599 position) from the \a other text fragment; otherwise returns |
|
1600 false. |
|
1601 */ |
|
1602 |
|
1603 /*! |
|
1604 \fn bool QTextFragment::operator<(const QTextFragment &other) const |
|
1605 |
|
1606 Returns true if this text fragment appears earlier in the document |
|
1607 than the \a other text fragment; otherwise returns false. |
|
1608 */ |
|
1609 |
|
1610 |
|
1611 /*! |
|
1612 Returns the position of this text fragment in the document. |
|
1613 */ |
|
1614 int QTextFragment::position() const |
|
1615 { |
|
1616 if (!p || !n) |
|
1617 return 0; // ### -1 instead? |
|
1618 |
|
1619 return p->fragmentMap().position(n); |
|
1620 } |
|
1621 |
|
1622 /*! |
|
1623 Returns the number of characters in the text fragment. |
|
1624 |
|
1625 \sa text() |
|
1626 */ |
|
1627 int QTextFragment::length() const |
|
1628 { |
|
1629 if (!p || !n) |
|
1630 return 0; |
|
1631 |
|
1632 int len = 0; |
|
1633 int f = n; |
|
1634 while (f != ne) { |
|
1635 len += p->fragmentMap().size(f); |
|
1636 f = p->fragmentMap().next(f); |
|
1637 } |
|
1638 return len; |
|
1639 } |
|
1640 |
|
1641 /*! |
|
1642 Returns true if the text fragment contains the text at the given |
|
1643 \a position in the document; otherwise returns false. |
|
1644 */ |
|
1645 bool QTextFragment::contains(int position) const |
|
1646 { |
|
1647 if (!p || !n) |
|
1648 return false; |
|
1649 int pos = this->position(); |
|
1650 return position >= pos && position < pos + length(); |
|
1651 } |
|
1652 |
|
1653 /*! |
|
1654 Returns the text fragment's character format. |
|
1655 |
|
1656 \sa text() |
|
1657 */ |
|
1658 QTextCharFormat QTextFragment::charFormat() const |
|
1659 { |
|
1660 if (!p || !n) |
|
1661 return QTextCharFormat(); |
|
1662 const QTextFragmentData *data = p->fragmentMap().fragment(n); |
|
1663 return p->formatCollection()->charFormat(data->format); |
|
1664 } |
|
1665 |
|
1666 /*! |
|
1667 Returns an index into the document's internal list of character formats |
|
1668 for the text fragment's character format. |
|
1669 |
|
1670 \sa QTextDocument::allFormats() |
|
1671 */ |
|
1672 int QTextFragment::charFormatIndex() const |
|
1673 { |
|
1674 if (!p || !n) |
|
1675 return -1; |
|
1676 const QTextFragmentData *data = p->fragmentMap().fragment(n); |
|
1677 return data->format; |
|
1678 } |
|
1679 |
|
1680 /*! |
|
1681 Returns the text fragment's as plain text. |
|
1682 |
|
1683 \sa length(), charFormat() |
|
1684 */ |
|
1685 QString QTextFragment::text() const |
|
1686 { |
|
1687 if (!p || !n) |
|
1688 return QString(); |
|
1689 |
|
1690 QString result; |
|
1691 QString buffer = p->buffer(); |
|
1692 int f = n; |
|
1693 while (f != ne) { |
|
1694 const QTextFragmentData * const frag = p->fragmentMap().fragment(f); |
|
1695 result += QString(buffer.constData() + frag->stringPosition, frag->size_array[0]); |
|
1696 f = p->fragmentMap().next(f); |
|
1697 } |
|
1698 return result; |
|
1699 } |
|
1700 |
|
1701 QT_END_NAMESPACE |