Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qtextcursor.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qtextcursor.h"
5#include "qtextcursor_p.h"
6#include "qglobal.h"
9#include "qtextlist.h"
10#include "qtexttable.h"
11#include "qtexttable_p.h"
12#include "qtextengine_p.h"
14
15#include <qtextlayout.h>
16#include <qdebug.h>
17
19
20enum {
22 AdjustUp = 0x3,
24 AdjustDown = 0x12
25};
26
28 : priv(p), x(0), position(0), anchor(0), adjusted_anchor(0),
29 currentCharFormat(-1), visualNavigation(false), keepPositionOnInsert(false),
30 changed(false)
31{
32 priv->addCursor(this);
33}
34
50
56
58{
60 // not(!) <= , so that inserting text adjusts the cursor correctly
61 if (position < positionOfChange
62 || (position == positionOfChange
65 )
66 ) {
68 } else {
69 if (charsAddedOrRemoved < 0 && position < positionOfChange - charsAddedOrRemoved)
70 position = positionOfChange;
71 else
72 position += charsAddedOrRemoved;
73
75 }
76
77 if (anchor >= positionOfChange
78 && (anchor != positionOfChange || op != QTextUndoCommand::KeepCursor)) {
79 if (charsAddedOrRemoved < 0 && anchor < positionOfChange - charsAddedOrRemoved)
80 anchor = positionOfChange;
81 else
82 anchor += charsAddedOrRemoved;
83 }
84
85 if (adjusted_anchor >= positionOfChange
86 && (adjusted_anchor != positionOfChange || op != QTextUndoCommand::KeepCursor)) {
87 if (charsAddedOrRemoved < 0 && adjusted_anchor < positionOfChange - charsAddedOrRemoved)
88 adjusted_anchor = positionOfChange;
89 else
90 adjusted_anchor += charsAddedOrRemoved;
91 }
92
93 return result;
94}
95
97{
99 x = -1; // mark dirty
100 return;
101 }
102
103 QTextBlock block = this->block();
105 int pos = position - block.position();
106
107 QTextLine line = layout->lineForTextPosition(pos);
108 if (line.isValid())
109 x = line.cursorToX(pos);
110 else
111 x = -1; // delayed init. Makes movePosition() call setX later on again.
112}
113
115{
116 if (anchor == position)
117 return;
119 int pos1 = position;
120 int pos2 = adjusted_anchor;
122 if (pos1 > pos2) {
123 pos1 = adjusted_anchor;
124 pos2 = position;
126 }
127
128 // deleting inside table? -> delete only content
130 if (table) {
132 int startRow, startCol, numRows, numCols;
133 selectedTableCells(&startRow, &numRows, &startCol, &numCols);
134 clearCells(table, startRow, startCol, numRows, numCols, op);
137 } else {
138 priv->remove(pos1, pos2-pos1, op);
140 }
141
142}
143
144void QTextCursorPrivate::clearCells(QTextTable *table, int startRow, int startCol, int numRows, int numCols, QTextUndoCommand::Operation op)
145{
147
148 for (int row = startRow; row < startRow + numRows; ++row)
149 for (int col = startCol; col < startCol + numCols; ++col) {
150 QTextTableCell cell = table->cellAt(row, col);
151 const int startPos = cell.firstPosition();
152 const int endPos = cell.lastPosition();
153 Q_ASSERT(startPos <= endPos);
154 priv->remove(startPos, endPos - startPos, op);
155 }
156
158}
159
161{
163 QTextCharFormat fmt = priv->formatCollection()->charFormat((*fit)->format);
164 return (fmt.objectIndex() == -1 || fmt.objectType() == QTextFormat::ImageObject);
165}
166
168{
170 int idx = formats->indexForFormat(format);
171 Q_ASSERT(formats->format(idx).isBlockFormat());
172
173 priv->insertBlock(position, idx, formats->indexForFormat(charFormat));
175}
176
178{
180 if (position == anchor)
181 return;
182
183 QTextFrame *f_position = priv->frameAt(position);
185
186 if (f_position != f_anchor) {
187 // find common parent frame
188 QList<QTextFrame *> positionChain;
189 QList<QTextFrame *> anchorChain;
190 QTextFrame *f = f_position;
191 while (f) {
192 positionChain.prepend(f);
193 f = f->parentFrame();
194 }
195 f = f_anchor;
196 while (f) {
197 anchorChain.prepend(f);
198 f = f->parentFrame();
199 }
200 Q_ASSERT(positionChain.at(0) == anchorChain.at(0));
201 int i = 1;
202 int l = qMin(positionChain.size(), anchorChain.size());
203 for (; i < l; ++i) {
204 if (positionChain.at(i) != anchorChain.at(i))
205 break;
206 }
207
208 if (m <= QTextCursor::WordLeft) {
209 if (i < positionChain.size())
210 position = positionChain.at(i)->firstPosition() - 1;
211 } else {
212 if (i < positionChain.size())
213 position = positionChain.at(i)->lastPosition() + 1;
214 }
216 if (i < anchorChain.size())
217 adjusted_anchor = anchorChain.at(i)->lastPosition() + 1;
218 } else {
219 if (i < anchorChain.size())
220 adjusted_anchor = anchorChain.at(i)->firstPosition() - 1;
221 }
222
223 f_position = positionChain.at(i-1);
224 }
225
226 // same frame, either need to adjust to cell boundaries or return
227 QTextTable *table = qobject_cast<QTextTable *>(f_position);
228 if (!table)
229 return;
230
231 QTextTableCell c_position = table->cellAt(position);
232 QTextTableCell c_anchor = table->cellAt(adjusted_anchor);
233 if (c_position != c_anchor) {
234 position = c_position.firstPosition();
236 adjusted_anchor = c_anchor.lastPosition();
237 else
238 adjusted_anchor = c_anchor.firstPosition();
239 }
241}
242
244{
245 Q_ASSERT(from <= to);
246 if (position == anchor)
247 return;
248
249 QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
250 if (!t)
251 return;
252 QTextTableCell removedCellFrom = t->cellAt(from);
253 QTextTableCell removedCellEnd = t->cellAt(to);
254 if (! removedCellFrom.isValid() || !removedCellEnd.isValid())
255 return;
256
257 int curFrom = position;
258 int curTo = adjusted_anchor;
259 if (curTo < curFrom)
260 qSwap(curFrom, curTo);
261
262 QTextTableCell cellStart = t->cellAt(curFrom);
263 QTextTableCell cellEnd = t->cellAt(curTo);
264
265 if (cellStart.row() >= removedCellFrom.row() && cellEnd.row() <= removedCellEnd.row()
266 && cellStart.column() >= removedCellFrom.column()
267 && cellEnd.column() <= removedCellEnd.column()) { // selection is completely removed
268 // find a new position, as close as possible to where we were.
269 QTextTableCell cell;
270 if (removedCellFrom.row() == 0 && removedCellEnd.row() == t->rows()-1) // removed n columns
271 cell = t->cellAt(cellStart.row(), removedCellEnd.column()+1);
272 else if (removedCellFrom.column() == 0 && removedCellEnd.column() == t->columns()-1) // removed n rows
273 cell = t->cellAt(removedCellEnd.row() + 1, cellStart.column());
274
275 int newPosition;
276 if (cell.isValid())
277 newPosition = cell.firstPosition();
278 else
279 newPosition = t->lastPosition()+1;
280
281 setPosition(newPosition);
282 anchor = newPosition;
283 adjusted_anchor = newPosition;
284 x = 0;
285 }
286 else if (cellStart.row() >= removedCellFrom.row() && cellStart.row() <= removedCellEnd.row()
287 && cellEnd.row() > removedCellEnd.row()) {
288 int newPosition = t->cellAt(removedCellEnd.row() + 1, cellStart.column()).firstPosition();
289 if (position < anchor)
290 position = newPosition;
291 else
292 anchor = adjusted_anchor = newPosition;
293 }
294 else if (cellStart.column() >= removedCellFrom.column() && cellStart.column() <= removedCellEnd.column()
295 && cellEnd.column() > removedCellEnd.column()) {
296 int newPosition = t->cellAt(cellStart.row(), removedCellEnd.column()+1).firstPosition();
297 if (position < anchor)
298 position = newPosition;
299 else
300 anchor = adjusted_anchor = newPosition;
301 }
302}
303
305{
307 bool adjustX = true;
308 QTextBlock blockIt = block();
309 bool visualMovement = priv->defaultCursorMoveStyle == Qt::VisualMoveStyle;
310
311 if (!blockIt.isValid())
312 return false;
313
314 if (blockIt.textDirection() == Qt::RightToLeft) {
315 if (op == QTextCursor::WordLeft)
317 else if (op == QTextCursor::WordRight)
319
320 if (!visualMovement) {
321 if (op == QTextCursor::Left)
323 else if (op == QTextCursor::Right)
325 }
326 }
327
328 const QTextLayout *layout = blockLayout(blockIt);
329 int relativePos = position - blockIt.position();
331 if (!priv->isInEditBlock())
332 line = layout->lineForTextPosition(relativePos);
333
335
336 int newPosition = position;
337
338 if (mode == QTextCursor::KeepAnchor && complexSelectionTable() != nullptr) {
340 || (op >= QTextCursor::Right && op <= QTextCursor::WordRight)) {
341 QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
342 Q_ASSERT(t); // as we have already made sure we have a complex selection
343 QTextTableCell cell_pos = t->cellAt(position);
344 if (cell_pos.column() + cell_pos.columnSpan() != t->columns())
346 }
347 }
348
349 if (x == -1 && !priv->isInEditBlock() && (op == QTextCursor::Up || op == QTextCursor::Down))
350 setX();
351
352 switch(op) {
354 return true;
355
357 newPosition = 0;
358 break;
360 newPosition = blockIt.position();
361 if (line.isValid())
362 newPosition += line.textStart();
363
364 break;
365 }
367 newPosition = blockIt.position();
368 break;
369 }
371 if (blockIt == priv->blocksBegin())
372 return false;
373 blockIt = blockIt.previous();
374
375 newPosition = blockIt.position();
376 break;
377 }
380 newPosition = qMin(position, adjusted_anchor);
381 else
383 break;
386 newPosition = visualMovement ? qMax(position, adjusted_anchor)
388 else
389 newPosition = visualMovement ? priv->leftCursorPosition(position)
391 break;
393 if (relativePos == 0)
394 break;
395
396 // skip if already at word start
397 QTextEngine *engine = layout->engine();
398 const QCharAttributes *attributes = engine->attributes();
399 if ((relativePos == blockIt.length() - 1)
400 && (attributes[relativePos - 1].whiteSpace || engine->atWordSeparator(relativePos - 1)))
401 return false;
402
403 if (relativePos < blockIt.length()-1)
404 ++position;
405
407 }
411 break;
412 case QTextCursor::Up: {
413 int i = line.lineNumber() - 1;
414 if (i == -1) {
415 if (blockIt == priv->blocksBegin())
416 return false;
417 int blockPosition = blockIt.position();
418 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
419 if (table) {
420 QTextTableCell cell = table->cellAt(blockPosition);
421 if (cell.firstPosition() == blockPosition) {
422 int row = cell.row() - 1;
423 if (row >= 0) {
424 blockPosition = table->cellAt(row, cell.column()).lastPosition();
425 } else {
426 // move to line above the table
427 blockPosition = table->firstPosition() - 1;
428 }
429 blockIt = priv->blocksFind(blockPosition);
430 } else {
431 blockIt = blockIt.previous();
432 }
433 } else {
434 blockIt = blockIt.previous();
435 }
436 layout = blockLayout(blockIt);
437 i = layout->lineCount()-1;
438 }
439 if (layout->lineCount()) {
440 QTextLine line = layout->lineAt(i);
441 newPosition = line.xToCursor(x) + blockIt.position();
442 } else {
443 newPosition = blockIt.position();
444 }
445 adjustX = false;
446 break;
447 }
448
449 case QTextCursor::End:
450 newPosition = priv->length() - 1;
451 break;
453 if (!line.isValid() || line.textLength() == 0) {
454 if (blockIt.length() >= 1)
455 // position right before the block separator
456 newPosition = blockIt.position() + blockIt.length() - 1;
457 break;
458 }
459 newPosition = blockIt.position() + line.textStart() + line.textLength();
460 if (newPosition >= priv->length())
461 newPosition = priv->length() - 1;
462 if (line.lineNumber() < layout->lineCount() - 1) {
463 const QString text = blockIt.text();
464 // ###### this relies on spaces being the cause for linebreaks.
465 // this doesn't work with japanese
466 if (text.at(line.textStart() + line.textLength() - 1).isSpace())
467 --newPosition;
468 }
469 break;
470 }
472 QTextEngine *engine = layout->engine();
473 const QCharAttributes *attributes = engine->attributes();
474 const int len = blockIt.length() - 1;
475 if (relativePos >= len)
476 return false;
477 if (engine->atWordSeparator(relativePos)) {
478 ++relativePos;
479 while (relativePos < len && engine->atWordSeparator(relativePos))
480 ++relativePos;
481 } else {
482 while (relativePos < len && !attributes[relativePos].whiteSpace && !engine->atWordSeparator(relativePos))
483 ++relativePos;
484 }
485 newPosition = blockIt.position() + relativePos;
486 break;
487 }
489 if (blockIt.length() >= 1)
490 // position right before the block separator
491 newPosition = blockIt.position() + blockIt.length() - 1;
492 break;
494 blockIt = blockIt.next();
495 if (!blockIt.isValid())
496 return false;
497
498 newPosition = blockIt.position();
499 break;
500 }
503 newPosition = qMax(position, adjusted_anchor);
504 else
506 break;
509 newPosition = visualMovement ? qMin(position, adjusted_anchor)
511 else
512 newPosition = visualMovement ? priv->rightCursorPosition(position)
514 break;
518 break;
519
520 case QTextCursor::Down: {
521 int i = line.lineNumber() + 1;
522
523 if (i >= layout->lineCount()) {
524 int blockPosition = blockIt.position() + blockIt.length() - 1;
525 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
526 if (table) {
527 QTextTableCell cell = table->cellAt(blockPosition);
528 if (cell.lastPosition() == blockPosition) {
529 int row = cell.row() + cell.rowSpan();
530 if (row < table->rows()) {
531 blockPosition = table->cellAt(row, cell.column()).firstPosition();
532 } else {
533 // move to line below the table
534 blockPosition = table->lastPosition() + 1;
535 }
536 blockIt = priv->blocksFind(blockPosition);
537 } else {
538 blockIt = blockIt.next();
539 }
540 } else {
541 blockIt = blockIt.next();
542 }
543
544 if (blockIt == priv->blocksEnd())
545 return false;
546 layout = blockLayout(blockIt);
547 i = 0;
548 }
549 if (layout->lineCount()) {
550 QTextLine line = layout->lineAt(i);
551 newPosition = line.xToCursor(x) + blockIt.position();
552 } else {
553 newPosition = blockIt.position();
554 }
555 adjustX = false;
556 break;
557 }
562 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(position));
563 if (!table)
564 return false;
565
566 QTextTableCell cell = table->cellAt(position);
567 Q_ASSERT(cell.isValid());
568 int column = cell.column();
569 int row = cell.row();
570 const int currentRow = row;
571 if (op == QTextCursor::NextCell || op == QTextCursor::NextRow) {
572 do {
573 column += cell.columnSpan();
574 if (column >= table->columns()) {
575 column = 0;
576 ++row;
577 }
578 cell = table->cellAt(row, column);
579 // note we also continue while we have not reached a cell that's not merged with one above us
580 } while (cell.isValid()
581 && ((op == QTextCursor::NextRow && currentRow == cell.row())
582 || cell.row() < row));
583 }
584 else if (op == QTextCursor::PreviousCell || op == QTextCursor::PreviousRow) {
585 do {
586 --column;
587 if (column < 0) {
588 column = table->columns()-1;
589 --row;
590 }
591 cell = table->cellAt(row, column);
592 // note we also continue while we have not reached a cell that's not merged with one above us
593 } while (cell.isValid()
594 && ((op == QTextCursor::PreviousRow && currentRow == cell.row())
595 || cell.row() < row));
596 }
597 if (cell.isValid())
598 newPosition = cell.firstPosition();
599 break;
600 }
601 }
602
604 QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(position));
606 || (op >= QTextCursor::NextBlock && op <= QTextCursor::WordRight))) {
607 int oldColumn = table->cellAt(position).column();
608
609 const QTextTableCell otherCell = table->cellAt(newPosition);
610 if (!otherCell.isValid())
611 return false;
612
613 int newColumn = otherCell.column();
614 if ((oldColumn > newColumn && op >= QTextCursor::End)
615 || (oldColumn < newColumn && op <= QTextCursor::WordLeft))
616 return false;
617 }
618 }
619
620 const bool moved = setPosition(newPosition);
621
625 } else {
626 adjustCursor(op);
627 }
628
629 if (adjustX)
630 setX();
631
632 return moved;
633}
634
636{
637 if (position == anchor)
638 return nullptr;
639
640 QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
641 if (t) {
642 QTextTableCell cell_pos = t->cellAt(position);
643 QTextTableCell cell_anchor = t->cellAt(adjusted_anchor);
644
645 Q_ASSERT(cell_anchor.isValid());
646
647 if (cell_pos == cell_anchor)
648 t = nullptr;
649 }
650 return t;
651}
652
653void QTextCursorPrivate::selectedTableCells(int *firstRow, int *numRows, int *firstColumn, int *numColumns) const
654{
655 *firstRow = -1;
656 *firstColumn = -1;
657 *numRows = -1;
658 *numColumns = -1;
659
660 if (position == anchor)
661 return;
662
663 QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
664 if (!t)
665 return;
666
667 QTextTableCell cell_pos = t->cellAt(position);
668 QTextTableCell cell_anchor = t->cellAt(adjusted_anchor);
669
670 Q_ASSERT(cell_anchor.isValid());
671
672 if (cell_pos == cell_anchor)
673 return;
674
675 *firstRow = qMin(cell_pos.row(), cell_anchor.row());
676 *firstColumn = qMin(cell_pos.column(), cell_anchor.column());
677 *numRows = qMax(cell_pos.row() + cell_pos.rowSpan(), cell_anchor.row() + cell_anchor.rowSpan()) - *firstRow;
678 *numColumns = qMax(cell_pos.column() + cell_pos.columnSpan(), cell_anchor.column() + cell_anchor.columnSpan()) - *firstColumn;
679}
680
681static void setBlockCharFormatHelper(QTextDocumentPrivate *priv, int pos1, int pos2,
683{
684 QTextBlock it = priv->blocksFind(pos1);
685 QTextBlock end = priv->blocksFind(pos2);
686 if (end.isValid())
687 end = end.next();
688
689 for (; it != end; it = it.next()) {
690 priv->setCharFormat(it.position() - 1, 1, format, changeMode);
691 }
692}
693
696{
698
699 QTextCharFormat format = _format;
701
703 if (table) {
704 int row_start, col_start, num_rows, num_cols;
705 selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
706
707 Q_ASSERT(row_start != -1);
708 for (int r = row_start; r < row_start + num_rows; ++r) {
709 for (int c = col_start; c < col_start + num_cols; ++c) {
710 QTextTableCell cell = table->cellAt(r, c);
711 int rspan = cell.rowSpan();
712 int cspan = cell.columnSpan();
713 if (rspan != 1) {
714 int cr = cell.row();
715 if (cr != r)
716 continue;
717 }
718 if (cspan != 1) {
719 int cc = cell.column();
720 if (cc != c)
721 continue;
722 }
723
724 int pos1 = cell.firstPosition();
725 int pos2 = cell.lastPosition();
726 setBlockCharFormatHelper(priv, pos1, pos2, format, changeMode);
727 }
728 }
729 } else {
730 int pos1 = position;
731 int pos2 = adjusted_anchor;
732 if (pos1 > pos2) {
733 pos1 = adjusted_anchor;
734 pos2 = position;
735 }
736
737 setBlockCharFormatHelper(priv, pos1, pos2, format, changeMode);
738 }
740}
741
742
744{
746 if (table) {
748 int row_start, col_start, num_rows, num_cols;
749 selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
750
751 Q_ASSERT(row_start != -1);
752 for (int r = row_start; r < row_start + num_rows; ++r) {
753 for (int c = col_start; c < col_start + num_cols; ++c) {
754 QTextTableCell cell = table->cellAt(r, c);
755 int rspan = cell.rowSpan();
756 int cspan = cell.columnSpan();
757 if (rspan != 1) {
758 int cr = cell.row();
759 if (cr != r)
760 continue;
761 }
762 if (cspan != 1) {
763 int cc = cell.column();
764 if (cc != c)
765 continue;
766 }
767
768 int pos1 = cell.firstPosition();
769 int pos2 = cell.lastPosition();
770 priv->setBlockFormat(priv->blocksFind(pos1), priv->blocksFind(pos2), format, changeMode);
771 }
772 }
774 } else {
775 int pos1 = position;
776 int pos2 = adjusted_anchor;
777 if (pos1 > pos2) {
778 pos1 = adjusted_anchor;
779 pos2 = position;
780 }
781
782 priv->setBlockFormat(priv->blocksFind(pos1), priv->blocksFind(pos2), format, changeMode);
783 }
784}
785
787{
789
790 QTextCharFormat format = _format;
792
794 if (table) {
796 int row_start, col_start, num_rows, num_cols;
797 selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
798
799 Q_ASSERT(row_start != -1);
800 for (int r = row_start; r < row_start + num_rows; ++r) {
801 for (int c = col_start; c < col_start + num_cols; ++c) {
802 QTextTableCell cell = table->cellAt(r, c);
803 int rspan = cell.rowSpan();
804 int cspan = cell.columnSpan();
805 if (rspan != 1) {
806 int cr = cell.row();
807 if (cr != r)
808 continue;
809 }
810 if (cspan != 1) {
811 int cc = cell.column();
812 if (cc != c)
813 continue;
814 }
815
816 int pos1 = cell.firstPosition();
817 int pos2 = cell.lastPosition();
818 priv->setCharFormat(pos1, pos2-pos1, format, changeMode);
819 }
820 }
822 } else {
823 int pos1 = position;
824 int pos2 = adjusted_anchor;
825 if (pos1 > pos2) {
826 pos1 = adjusted_anchor;
827 pos2 = position;
828 }
829
830 priv->setCharFormat(pos1, pos2-pos1, format, changeMode);
831 }
832}
833
834
836 QTextLayout *tl = block.layout();
837 if (!tl->lineCount() && priv->layout())
839 return tl;
840}
841
1011 : d(nullptr)
1012{
1013}
1014
1022
1027 : d(new QTextCursorPrivate(QTextDocumentPrivate::get(frame->document())))
1028{
1029 d->adjusted_anchor = d->anchor = d->position = frame->firstPosition();
1030}
1031
1032
1038{
1039 d->adjusted_anchor = d->anchor = d->position = block.position();
1040}
1041
1042
1047 : d(new QTextCursorPrivate(p))
1048{
1049 d->adjusted_anchor = d->anchor = d->position = pos;
1050
1051 d->setX();
1052}
1053
1058{
1059 Q_ASSERT(d);
1060 this->d = d;
1061}
1062
1067{
1068 d = cursor.d;
1069}
1070
1078{
1079 d = cursor.d;
1080 return *this;
1081}
1082
1097
1103{
1104 return !d || !d->priv;
1105}
1106
1124{
1125 if (!d || !d->priv)
1126 return;
1127
1128 if (pos < 0 || pos >= d->priv->length()) {
1129 qWarning("QTextCursor::setPosition: Position '%d' out of range", pos);
1130 return;
1131 }
1132
1133 d->setPosition(pos);
1134 if (m == MoveAnchor) {
1135 d->anchor = pos;
1136 d->adjusted_anchor = pos;
1137 } else { // keep anchor
1139 if (pos < d->anchor)
1140 op = QTextCursor::Left;
1141 else
1142 op = QTextCursor::Right;
1143 d->adjustCursor(op);
1144 }
1145 d->setX();
1146}
1147
1162{
1163 if (!d || !d->priv)
1164 return -1;
1165 return d->position;
1166}
1167
1185{
1186 if (!d || !d->priv)
1187 return 0;
1188 return d->position - d->block().position();
1189}
1190
1200{
1201 if (!d || !d->priv)
1202 return -1;
1203 return d->anchor;
1204}
1205
1225{
1226 if (!d || !d->priv)
1227 return false;
1228 switch (op) {
1229 case Start:
1230 case StartOfLine:
1231 case End:
1232 case EndOfLine:
1233 n = 1;
1234 break;
1235 default: break;
1236 }
1237
1238 int previousPosition = d->position;
1239 for (; n > 0; --n) {
1240 if (!d->movePosition(op, mode))
1241 return false;
1242 }
1243
1244 if (d->visualNavigation && !d->block().isVisible()) {
1245 QTextBlock b = d->block();
1246 if (previousPosition < d->position) {
1247 while (!b.next().isVisible())
1248 b = b.next();
1249 d->setPosition(b.position() + b.length() - 1);
1250 } else {
1251 while (!b.previous().isVisible())
1252 b = b.previous();
1253 d->setPosition(b.position());
1254 }
1256 d->anchor = d->position;
1257 while (d->movePosition(op, mode)
1258 && !d->block().isVisible())
1259 ;
1260
1261 }
1262 return true;
1263}
1264
1277{
1278 return d ? d->visualNavigation : false;
1279}
1280
1292{
1293 if (d)
1294 d->visualNavigation = b;
1295}
1296
1297
1313{
1314 if (d)
1315 d->x = x;
1316}
1317
1328{
1329 return d ? d->x : -1;
1330}
1331
1343{
1344 return d ? d->keepPositionOnInsert : false;
1345}
1346
1364{
1365 if (d)
1367}
1368
1369
1370
1388{
1390 fmt.clearProperty(QTextFormat::ObjectType);
1392}
1393
1401{
1402 if (!d || !d->priv)
1403 return;
1404
1405 Q_ASSERT(_format.isValid());
1406
1407 QTextCharFormat format = _format;
1409
1410 bool hasEditBlock = false;
1411
1412 if (d->anchor != d->position) {
1413 hasEditBlock = true;
1414 d->priv->beginEditBlock();
1415 d->remove();
1416 }
1417
1418 if (!text.isEmpty()) {
1420 int formatIdx = formats->indexForFormat(format);
1421 Q_ASSERT(formats->format(formatIdx).isCharFormat());
1422
1423 QTextBlockFormat blockFmt = blockFormat();
1424
1425
1426 int textStart = d->priv->text.size();
1427 int blockStart = 0;
1428 d->priv->text += text;
1429 int textEnd = d->priv->text.size();
1430
1431 for (int i = 0; i < text.size(); ++i) {
1432 QChar ch = text.at(i);
1433
1434 const int blockEnd = i;
1435
1436 if (ch == u'\r'
1437 && (i + 1) < text.size()
1438 && text.at(i + 1) == u'\n') {
1439 ++i;
1440 ch = text.at(i);
1441 }
1442
1443 if (ch == u'\n'
1444 || ch == QChar::ParagraphSeparator
1446 || ch == QTextEndOfFrame
1447 || ch == u'\r') {
1448
1449 if (!hasEditBlock) {
1450 hasEditBlock = true;
1451 d->priv->beginEditBlock();
1452 }
1453
1454 if (blockEnd > blockStart)
1455 d->priv->insert(d->position, textStart + blockStart, blockEnd - blockStart, formatIdx);
1456
1457 d->insertBlock(blockFmt, format);
1458 blockStart = i + 1;
1459 }
1460 }
1461 if (textStart + blockStart < textEnd)
1462 d->priv->insert(d->position, textStart + blockStart, textEnd - textStart - blockStart, formatIdx);
1463 }
1464 if (hasEditBlock)
1465 d->priv->endEditBlock();
1466 d->setX();
1467}
1468
1476{
1477 if (!d || !d->priv)
1478 return;
1479
1480 if (d->position != d->anchor) {
1482 return;
1483 }
1484
1485 if (!d->canDelete(d->position))
1486 return;
1487 d->adjusted_anchor = d->anchor =
1489 d->remove();
1490 d->setX();
1491}
1492
1500{
1501 if (!d || !d->priv)
1502 return;
1503
1504 if (d->position != d->anchor) {
1506 return;
1507 }
1508
1509 if (d->anchor < 1 || !d->canDelete(d->anchor-1))
1510 return;
1511 d->anchor--;
1512
1514 const QTextFragmentData * const frag = fragIt.value();
1515 int fpos = fragIt.position();
1516 QChar uc = d->priv->buffer().at(d->anchor - fpos + frag->stringPosition);
1517 if (d->anchor > fpos && uc.isLowSurrogate()) {
1518 // second half of a surrogate, check if we have the first half as well,
1519 // if yes delete both at once
1520 uc = d->priv->buffer().at(d->anchor - 1 - fpos + frag->stringPosition);
1521 if (uc.isHighSurrogate())
1522 --d->anchor;
1523 }
1524
1525 d->adjusted_anchor = d->anchor;
1526 d->remove();
1527 d->setX();
1528}
1529
1534{
1535 if (!d || !d->priv)
1536 return;
1537
1539
1540 const QTextBlock block = d->block();
1541
1542 switch (selection) {
1543 case LineUnderCursor:
1546 break;
1547 case WordUnderCursor:
1550 break;
1551 case BlockUnderCursor:
1552 if (block.length() == 1) // no content
1553 break;
1555 // also select the paragraph separator
1559 }
1561 break;
1562 case Document:
1565 break;
1566 }
1567}
1568
1573{
1574 return !!d && d->position != d->anchor;
1575}
1576
1577
1586{
1587 if (!d)
1588 return false;
1589
1590 return d->complexSelectionTable() != nullptr;
1591}
1592
1601void QTextCursor::selectedTableCells(int *firstRow, int *numRows, int *firstColumn, int *numColumns) const
1602{
1603 *firstRow = -1;
1604 *firstColumn = -1;
1605 *numRows = -1;
1606 *numColumns = -1;
1607
1608 if (!d || d->position == d->anchor)
1609 return;
1610
1611 d->selectedTableCells(firstRow, numRows, firstColumn, numColumns);
1612}
1613
1614
1623{
1624 if (!d)
1625 return;
1626 d->adjusted_anchor = d->anchor = d->position;
1627 d->currentCharFormat = -1;
1628}
1629
1637{
1638 if (!d || !d->priv || d->position == d->anchor)
1639 return;
1640
1641 d->priv->beginEditBlock();
1642 d->remove();
1643 d->priv->endEditBlock();
1644 d->setX();
1645}
1646
1654{
1655 if (!d || !d->priv)
1656 return -1;
1657 return qMin(d->position, d->adjusted_anchor);
1658}
1659
1667{
1668 if (!d || !d->priv)
1669 return -1;
1670 return qMax(d->position, d->adjusted_anchor);
1671}
1672
1673static void getText(QString &text, QTextDocumentPrivate *priv, const QString &docText, int pos, int end)
1674{
1675 while (pos < end) {
1677 const QTextFragmentData * const frag = fragIt.value();
1678
1679 const int offsetInFragment = qMax(0, pos - fragIt.position());
1680 const int len = qMin(int(frag->size_array[0] - offsetInFragment), end - pos);
1681
1682 text += QStringView(docText.constData() + frag->stringPosition + offsetInFragment, len);
1683 pos += len;
1684 }
1685}
1686
1699{
1700 if (!d || !d->priv || d->position == d->anchor)
1701 return QString();
1702
1703 const QString docText = d->priv->buffer();
1704 QString text;
1705
1707 if (table) {
1708 int row_start, col_start, num_rows, num_cols;
1709 selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
1710
1711 Q_ASSERT(row_start != -1);
1712 for (int r = row_start; r < row_start + num_rows; ++r) {
1713 for (int c = col_start; c < col_start + num_cols; ++c) {
1714 QTextTableCell cell = table->cellAt(r, c);
1715 int rspan = cell.rowSpan();
1716 int cspan = cell.columnSpan();
1717 if (rspan != 1) {
1718 int cr = cell.row();
1719 if (cr != r)
1720 continue;
1721 }
1722 if (cspan != 1) {
1723 int cc = cell.column();
1724 if (cc != c)
1725 continue;
1726 }
1727
1728 getText(text, d->priv, docText, cell.firstPosition(), cell.lastPosition());
1729 }
1730 }
1731 } else {
1732 getText(text, d->priv, docText, selectionStart(), selectionEnd());
1733 }
1734
1735 return text;
1736}
1737
1753
1758{
1759 if (!d || !d->priv)
1760 return QTextBlock();
1761 return d->block();
1762}
1763
1770{
1771 if (!d || !d->priv)
1772 return QTextBlockFormat();
1773
1774 return d->block().blockFormat();
1775}
1776
1784{
1785 if (!d || !d->priv)
1786 return;
1787
1789}
1790
1799{
1800 if (!d || !d->priv)
1801 return;
1802
1804}
1805
1815{
1816 if (!d || !d->priv)
1817 return QTextCharFormat();
1818
1819 return d->block().charFormat();
1820}
1821
1835
1844{
1845 if (!d || !d->priv)
1846 return;
1847
1849}
1850
1860{
1861 if (!d || !d->priv)
1862 return QTextCharFormat();
1863
1864 int idx = d->currentCharFormat;
1865 if (idx == -1) {
1866 QTextBlock block = d->block();
1867
1868 int pos;
1869 if (d->position == block.position()
1870 && block.length() > 1)
1871 pos = d->position;
1872 else
1873 pos = d->position - 1;
1874
1875 if (pos == -1) {
1876 idx = d->priv->blockCharFormatIndex(d->priv->blockMap().firstNode());
1877 } else {
1878 Q_ASSERT(pos >= 0 && pos < d->priv->length());
1879
1881 Q_ASSERT(!it.atEnd());
1882 idx = it.value()->format;
1883 }
1884 }
1885
1888
1889 Q_ASSERT(cfmt.isValid());
1890 return cfmt;
1891}
1892
1901{
1902 if (!d || !d->priv)
1903 return;
1904 if (d->position == d->anchor) {
1906 return;
1907 }
1909}
1910
1920{
1921 if (!d || !d->priv)
1922 return;
1923 if (d->position == d->anchor) {
1925 format.merge(modifier);
1927 return;
1928 }
1929
1931}
1932
1940{
1941 if (!d || !d->priv)
1942 return false;
1943
1944 return d->position == d->block().position();
1945}
1946
1954{
1955 if (!d || !d->priv)
1956 return false;
1957
1958 return d->position == d->block().position() + d->block().length() - 1;
1959}
1960
1968{
1969 if (!d || !d->priv)
1970 return false;
1971
1972 return d->position == 0;
1973}
1974
1984{
1985 if (!d || !d->priv)
1986 return false;
1987
1988 return d->position == d->priv->length() - 1;
1989}
1990
2001
2011{
2012 QTextCharFormat charFmt = charFormat();
2013 charFmt.clearProperty(QTextFormat::ObjectType);
2014 insertBlock(format, charFmt);
2015}
2016
2027{
2028 if (!d || !d->priv)
2029 return;
2030
2031 QTextCharFormat charFormat = _charFormat;
2033
2034 d->priv->beginEditBlock();
2035 d->remove();
2037 d->priv->endEditBlock();
2038 d->setX();
2039}
2040
2053
2068
2076{
2077 if (!d || !d->priv)
2078 return nullptr;
2079
2080 QTextList *list = static_cast<QTextList *>(d->priv->createObject(format));
2081 QTextBlockFormat modifier;
2082 modifier.setObjectIndex(list->objectIndex());
2083 mergeBlockFormat(modifier);
2084 return list;
2085}
2086
2103
2111{
2112 if (!d || !d->priv)
2113 return nullptr;
2114
2117 return qobject_cast<QTextList *>(o);
2118}
2119
2134{
2135 return insertTable(rows, cols, QTextTableFormat());
2136}
2137
2151{
2152 if (!d || !d->priv || rows == 0 || cols == 0)
2153 return nullptr;
2154
2155 int pos = d->position;
2157 d->setPosition(pos+1);
2158 // ##### what should we do if we have a selection?
2159 d->anchor = d->position;
2160 d->adjusted_anchor = d->anchor;
2161 return t;
2162}
2163
2171{
2172 if (!d || !d->priv)
2173 return nullptr;
2174
2176 while (frame) {
2177 QTextTable *table = qobject_cast<QTextTable *>(frame);
2178 if (table)
2179 return table;
2180 frame = frame->parentFrame();
2181 }
2182 return nullptr;
2183}
2184
2195{
2196 if (!d || !d->priv)
2197 return nullptr;
2198
2200}
2201
2208{
2209 if (!d || !d->priv)
2210 return nullptr;
2211
2212 return d->priv->frameAt(d->position);
2213}
2214
2215
2220{
2221 if (!d || !d->priv || fragment.isEmpty())
2222 return;
2223
2224 d->priv->beginEditBlock();
2225 d->remove();
2226 fragment.d->insert(*this);
2227 d->priv->endEditBlock();
2228 d->setX();
2229
2230 if (fragment.d && fragment.d->doc)
2232}
2233
2245#ifndef QT_NO_TEXTHTMLPARSER
2246
2248{
2249 if (!d || !d->priv)
2250 return;
2252 insertFragment(fragment);
2253}
2254
2255#endif // QT_NO_TEXTHTMLPARSER
2256
2263#if QT_CONFIG(textmarkdownreader)
2264
2265void QTextCursor::insertMarkdown(const QString &markdown, QTextDocument::MarkdownFeatures features)
2266{
2267 if (!d || !d->priv)
2268 return;
2269 QTextDocumentFragment fragment = QTextDocumentFragment::fromMarkdown(markdown, features);
2270 if (markdown.startsWith(QLatin1Char('\n')))
2271 insertBlock(fragment.d->doc->firstBlock().blockFormat());
2272 insertFragment(fragment);
2273 if (!atEnd() && markdown.endsWith(QLatin1Char('\n')))
2275}
2276
2277#endif // textmarkdownreader
2278
2289{
2290 if (!d || !d->priv)
2291 return;
2292
2293 QTextFrameFormat ffmt;
2294 ffmt.setPosition(alignment);
2295 QTextObject *obj = d->priv->createObject(ffmt);
2296
2298 fmt.setObjectIndex(obj->objectIndex());
2299
2300 d->priv->beginEditBlock();
2301 d->remove();
2302 const int idx = d->priv->formatCollection()->indexForFormat(fmt);
2303 d->priv->insert(d->position, QChar(QChar::ObjectReplacementCharacter), idx);
2304 d->priv->endEditBlock();
2305}
2306
2311{
2312 insertText(QString(QChar::ObjectReplacementCharacter), format);
2313}
2314
2329
2338{
2339 if (image.isNull()) {
2340 qWarning("QTextCursor::insertImage: attempt to add an invalid image");
2341 return;
2342 }
2343 QString imageName = name;
2344 if (name.isEmpty())
2345 imageName = QString::number(image.cacheKey());
2348 format.setName(imageName);
2350}
2351
2359{
2360 return !operator==(rhs);
2361}
2362
2370{
2371 if (!d)
2372 return !!rhs.d;
2373
2374 if (!rhs.d)
2375 return false;
2376
2377 Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator<", "cannot compare cursors attached to different documents");
2378
2379 return d->position < rhs.d->position;
2380}
2381
2390{
2391 if (!d)
2392 return true;
2393
2394 if (!rhs.d)
2395 return false;
2396
2397 Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator<=", "cannot compare cursors attached to different documents");
2398
2399 return d->position <= rhs.d->position;
2400}
2401
2409{
2410 if (!d)
2411 return !rhs.d;
2412
2413 if (!rhs.d)
2414 return false;
2415
2416 return d->position == rhs.d->position && d->priv == rhs.d->priv;
2417}
2418
2427{
2428 if (!d)
2429 return false;
2430
2431 if (!rhs.d)
2432 return true;
2433
2434 Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator>=", "cannot compare cursors attached to different documents");
2435
2436 return d->position >= rhs.d->position;
2437}
2438
2446{
2447 if (!d)
2448 return false;
2449
2450 if (!rhs.d)
2451 return true;
2452
2453 Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator>", "cannot compare cursors attached to different documents");
2454
2455 return d->position > rhs.d->position;
2456}
2457
2476{
2477 if (!d || !d->priv)
2478 return;
2479
2480 if (d->priv->editBlock == 0) // we are the initial edit block, store current cursor position for undo
2481 d->priv->editBlockCursorPosition = d->position;
2482
2483 d->priv->beginEditBlock();
2484}
2485
2501{
2502 if (!d || !d->priv)
2503 return;
2504
2506}
2507
2517{
2518 if (!d || !d->priv)
2519 return;
2520
2521 d->priv->endEditBlock();
2522}
2523
2532{
2533 return d == other.d;
2534}
2535
2544{
2545 if (!d || !d->priv)
2546 return 0;
2547
2548 return d->block().blockNumber();
2549}
2550
2551
2564{
2565 if (!d || !d->priv)
2566 return 0;
2567
2568 QTextBlock block = d->block();
2569 if (!block.isValid())
2570 return 0;
2571
2572 const QTextLayout *layout = d->blockLayout(block);
2573
2574 const int relativePos = d->position - block.position();
2575
2576 if (layout->lineCount() == 0)
2577 return relativePos;
2578
2579 QTextLine line = layout->lineForTextPosition(relativePos);
2580 if (!line.isValid())
2581 return 0;
2582 return relativePos - line.textStart();
2583}
2584
2590{
2591 if (d->priv)
2592 return d->priv->document();
2593 return nullptr; // document went away
2594}
2595
virtual QRectF blockBoundingRect(const QTextBlock &block) const =0
Returns the bounding rectangle of block.
\inmodule QtCore
int firstNode() const
\inmodule QtGui
Definition qimage.h:37
\inmodule QtCore
Definition qshareddata.h:19
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
qsizetype length() const noexcept
Returns the number of characters in this string.
Definition qstring.h:191
\reentrant
int length() const
Returns the length of the block in characters.
QTextBlockFormat blockFormat() const
Returns the QTextBlockFormat that describes block-specific properties.
int blockNumber() const
bool isValid() const
Returns true if this text block is valid; otherwise returns false.
QTextBlock next() const
Returns the text block in the document after this block, or an empty text block if this is the last o...
bool isVisible() const
QTextLayout * layout() const
Returns the QTextLayout that is used to lay out and display the block's contents.
int position() const
Returns the index of the block's first character within the document.
QTextCharFormat charFormat() const
Returns the QTextCharFormat that describes the block's character format.
QTextBlock previous() const
Returns the text block in the document before this block, or an empty text block if this is the first...
bool isValid() const
Returns true if this character format is valid; otherwise returns false.
bool movePosition(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode=QTextCursor::MoveAnchor)
AdjustResult adjustPosition(int positionOfChange, int charsAddedOrRemoved, QTextUndoCommand::Operation op)
void setCharFormat(const QTextCharFormat &format, QTextDocumentPrivate::FormatChangeMode changeMode)
void setBlockCharFormat(const QTextCharFormat &format, QTextDocumentPrivate::FormatChangeMode changeMode)
QTextBlock block() const
void selectedTableCells(int *firstRow, int *numRows, int *firstColumn, int *numColumns) const
QTextLayout * blockLayout(QTextBlock &block) const
void setBlockFormat(const QTextBlockFormat &format, QTextDocumentPrivate::FormatChangeMode changeMode)
bool setPosition(int newPosition)
bool canDelete(int pos) const
QTextDocumentPrivate * priv
QTextCursorPrivate(QTextDocumentPrivate *p)
void clearCells(QTextTable *table, int startRow, int startCol, int numRows, int numCols, QTextUndoCommand::Operation op)
void adjustCursor(QTextCursor::MoveOperation m)
void insertBlock(const QTextBlockFormat &format, const QTextCharFormat &charFormat)
void aboutToRemoveCell(int from, int to)
QTextTable * complexSelectionTable() const
\reentrant \inmodule QtGui
Definition qtextcursor.h:30
QString selectedText() const
Returns the current selection's text (which may be empty).
void setBlockCharFormat(const QTextCharFormat &format)
Sets the block char format of the current block (or all blocks that are contained in the selection) t...
void setVerticalMovementX(int x)
QTextBlockFormat blockFormat() const
Returns the block format of the block the cursor is in.
QTextDocument * document() const
QTextCharFormat charFormat() const
Returns the format of the character immediately before the cursor position().
QTextBlock block() const
Returns the block that contains the cursor.
QTextCharFormat blockCharFormat() const
Returns the block character format of the block the cursor is in.
void beginEditBlock()
Indicates the start of a block of editing operations on the document that should appear as a single o...
bool atBlockStart() const
Returns true if the cursor is at the start of a block; otherwise returns false.
void setPosition(int pos, MoveMode mode=MoveAnchor)
Moves the cursor to the absolute position in the document specified by pos using a MoveMode specified...
void setKeepPositionOnInsert(bool b)
int selectionStart() const
Returns the start of the selection or position() if the cursor doesn't have a selection.
bool atStart() const
Returns true if the cursor is at the start of the document; otherwise returns false.
bool movePosition(MoveOperation op, MoveMode=MoveAnchor, int n=1)
Moves the cursor by performing the given operation n times, using the specified mode,...
bool operator<(const QTextCursor &rhs) const
Returns true if the other cursor is positioned later in the document than this cursor; otherwise retu...
bool atBlockEnd() const
Returns true if the cursor is at the end of a block; otherwise returns false.
int anchor() const
Returns the anchor position; this is the same as position() unless there is a selection in which case...
void insertHtml(const QString &html)
SelectionType
This enum describes the types of selection that can be applied with the select() function.
int blockNumber() const
int positionInBlock() const
void clearSelection()
Clears the current selection by setting the anchor to the cursor position.
void insertFragment(const QTextDocumentFragment &fragment)
Inserts the text fragment at the current position().
bool isNull() const
Returns true if the cursor is null; otherwise returns false.
MoveMode
\value MoveAnchor Moves the anchor to the same position as the cursor itself.
Definition qtextcursor.h:47
bool keepPositionOnInsert() const
void setBlockFormat(const QTextBlockFormat &format)
Sets the block format of the current block (or all blocks that are contained in the selection) to for...
~QTextCursor()
Destroys the QTextCursor.
void setCharFormat(const QTextCharFormat &format)
Sets the cursor's current character format to the given format.
bool visualNavigation() const
QTextCursor()
Constructs a null cursor.
bool atEnd() const
void removeSelectedText()
If there is a selection, its content is deleted; otherwise does nothing.
void mergeBlockCharFormat(const QTextCharFormat &modifier)
Modifies the block char format of the current block (or all blocks that are contained in the selectio...
QTextDocumentFragment selection() const
Returns the current selection (which may be empty) with all its formatting information.
int verticalMovementX() const
void mergeCharFormat(const QTextCharFormat &modifier)
Merges the cursor's current character format with the properties described by format modifier.
void joinPreviousEditBlock()
Like beginEditBlock() indicates the start of a block of editing operations that should appear as a si...
int selectionEnd() const
Returns the end of the selection or position() if the cursor doesn't have a selection.
void selectedTableCells(int *firstRow, int *numRows, int *firstColumn, int *numColumns) const
If the selection spans over table cells, firstRow is populated with the number of the first row in th...
void select(SelectionType selection)
Selects text in the document according to the given selection.
void insertText(const QString &text)
Inserts text at the current position, using the current character format.
QTextList * currentList() const
Returns the current list if the cursor position() is inside a block that is part of a list; otherwise...
void setVisualNavigation(bool b)
bool operator>=(const QTextCursor &rhs) const
Returns true if the other cursor is positioned earlier or at the same position in the document as thi...
bool isCopyOf(const QTextCursor &other) const
Returns true if this cursor and other are copies of each other, i.e.
bool operator>(const QTextCursor &rhs) const
Returns true if the other cursor is positioned earlier in the document than this cursor; otherwise re...
void insertImage(const QTextImageFormat &format, QTextFrameFormat::Position alignment)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void insertBlock()
Inserts a new empty block at the cursor position() with the current blockFormat() and charFormat().
bool hasSelection() const
Returns true if the cursor contains a selection; otherwise returns false.
void endEditBlock()
Indicates the end of a block of editing operations on the document that should appear as a single ope...
QTextList * insertList(const QTextListFormat &format)
Inserts a new block at the current position and makes it the first list item of a newly created list ...
MoveOperation
\value NoMove Keep the cursor where it is
Definition qtextcursor.h:61
bool operator<=(const QTextCursor &rhs) const
Returns true if the other cursor is positioned later or at the same position in the document as this ...
int columnNumber() const
void mergeBlockFormat(const QTextBlockFormat &modifier)
Modifies the block format of the current block (or all blocks that are contained in the selection) wi...
QTextCursor & operator=(const QTextCursor &other)
Makes a copy of cursor and assigns it to this QTextCursor.
bool hasComplexSelection() const
Returns true if the cursor contains a selection that is not simply a range from selectionStart() to s...
QTextTable * insertTable(int rows, int cols, const QTextTableFormat &format)
Creates a new table with the given number of rows and columns in the specified format,...
QTextTable * currentTable() const
Returns a pointer to the current table if the cursor position() is inside a block that is part of a t...
bool operator==(const QTextCursor &rhs) const
Returns true if the other cursor is at the same position in the document as this cursor; otherwise re...
QTextFrame * insertFrame(const QTextFrameFormat &format)
Inserts a frame with the given format at the current cursor position(), moves the cursor position() i...
void deletePreviousChar()
If there is no selected text, deletes the character before the current cursor position; otherwise del...
int position() const
Returns the absolute position of the cursor within the document.
void deleteChar()
If there is no selected text, deletes the character at the current cursor position; otherwise deletes...
QTextFrame * currentFrame() const
Returns a pointer to the current frame.
bool operator!=(const QTextCursor &rhs) const
Returns true if the other cursor is at a different position in the document as this cursor; otherwise...
QTextList * createList(const QTextListFormat &format)
Creates and returns a new list with the given format, and makes the current paragraph the cursor is i...
void insert(QTextCursor &cursor) const
bool isEmpty() const
Returns true if the fragment is empty; otherwise returns false.
static QTextDocumentFragment fromHtml(const QString &html, const QTextDocument *resourceProvider=nullptr)
QTextFormatCollection * formatCollection()
const BlockMap & blockMap() const
QAbstractTextDocumentLayout * layout() const
int insertBlock(int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation=QTextUndoCommand::MoveCursor)
QTextFrame * frameAt(int pos) const
void insert(int pos, QStringView text, int format)
QString buffer() const
void remove(int pos, int length, QTextUndoCommand::Operation=QTextUndoCommand::MoveCursor)
int rightCursorPosition(int position) const
QTextFrame * insertFrame(int start, int end, const QTextFrameFormat &format)
void removeCursor(QTextCursorPrivate *c)
int blockCharFormatIndex(int node) const
QTextBlock blocksBegin() const
int nextCursorPosition(int position, QTextLayout::CursorMode mode) const
QTextDocument * document()
QTextBlock blocksEnd() const
QTextObject * createObject(const QTextFormat &newFormat, int objectIndex=-1)
static const QTextDocumentPrivate * get(const QTextDocument *document)
FragmentMap::ConstIterator FragmentIterator
void setBlockFormat(const QTextBlock &from, const QTextBlock &to, const QTextBlockFormat &newFormat, FormatChangeMode mode=SetFormat)
FragmentIterator find(int pos) const
Qt::CursorMoveStyle defaultCursorMoveStyle
QTextObject * objectForFormat(int formatIndex) const
int leftCursorPosition(int position) const
void setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode=SetFormat)
QTextBlock blocksFind(int pos) const
void mergeCachedResources(const QTextDocumentPrivate *priv)
int previousCursorPosition(int position, QTextLayout::CursorMode mode) const
void addCursor(QTextCursorPrivate *c)
\reentrant \inmodule QtGui
QTextBlock firstBlock() const
void addResource(int type, const QUrl &name, const QVariant &resource)
Adds the resource resource to the resource cache, using type and name as identifiers.
int indexForFormat(const QTextFormat &f)
QTextCharFormat charFormat(int index) const
void setObjectIndex(int object)
Sets the format object's object index.
void clearProperty(int propertyId)
Clears the value of the property given by propertyId.
void setPosition(Position f)
Sets the policy for positioning frames with this frame format.
Position
This enum describes how a frame is located relative to the surrounding text.
\reentrant
Definition qtextobject.h:81
QTextFrame * parentFrame() const
Returns the frame's parent frame.
void setName(const QString &name)
Sets the name of the image.
\reentrant
Definition qtextlayout.h:70
int lineCount() const
Returns the number of lines in this text layout.
\reentrant
void setStyle(Style style)
Sets the list format's style.
Style
This enum describes the symbols used to decorate list items:
\reentrant
Definition qtextlist.h:18
\reentrant
Definition qtextobject.h:25
\reentrant
Definition qtexttable.h:19
int columnSpan() const
Returns the number of columns this cell spans.
int firstPosition() const
int row() const
Returns the number of the row in the table that contains this cell.
int rowSpan() const
Returns the number of rows this cell spans.
int lastPosition() const
bool isValid() const
Returns true if this is a valid table cell; otherwise returns false.
Definition qtexttable.h:36
int column() const
Returns the number of the column in the table that contains this cell.
static QTextTable * createTable(QTextDocumentPrivate *, int pos, int rows, int cols, const QTextTableFormat &tableFormat)
\reentrant
Definition qtexttable.h:63
\inmodule QtCore
Definition qurl.h:94
QString text
QCursor cursor
QSet< QString >::iterator it
uint alignment
EGLint EGLint * formats
Combined button and popup list for selecting options.
@ RightToLeft
@ VisualMoveStyle
Definition image.cpp:4
#define Q_FALLTHROUGH()
static QDBusError::ErrorType get(const char *name)
#define qWarning
Definition qlogging.h:166
static const QMetaObjectPrivate * priv(const uint *data)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
n void setPosition(void) \n\
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLenum mode
const GLfloat * m
GLboolean r
[2]
GLuint GLuint end
GLfloat GLfloat f
GLuint name
GLfloat n
GLint GLsizei GLsizei GLenum format
GLenum GLenum GLsizei void GLsizei void * column
GLhandleARB obj
[2]
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
GLenum GLenum GLsizei void * row
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLenum GLsizei len
GLenum GLenum GLsizei void * table
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
Definition qswap.h:20
static void getText(QString &text, QTextDocumentPrivate *priv, const QString &docText, int pos, int end)
@ AdjustPrev
@ AdjustDown
@ AdjustNext
@ AdjustUp
static void setBlockCharFormatHelper(QTextDocumentPrivate *priv, int pos1, int pos2, const QTextCharFormat &format, QTextDocumentPrivate::FormatChangeMode changeMode)
#define QTextBeginningOfFrame
#define QTextEndOfFrame
QVideoFrameFormat::PixelFormat fmt
QList< int > list
[14]
QObject::connect nullptr
QVBoxLayout * layout
QSharedPointer< T > other(t)
[5]
QItemSelection * selection
[0]
QFrame frame
[0]
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18