130 Q_Q(QWidgetTextControl);
134 const QTextCursor oldSelection = cursor;
135 const int oldCursorPos = cursor.position();
137 QTextCursor::MoveMode mode = QTextCursor::MoveAnchor;
138 QTextCursor::MoveOperation op = QTextCursor::NoMove;
142#ifndef QT_NO_SHORTCUT
143 if (e == QKeySequence::MoveToNextChar) {
144 op = QTextCursor::Right;
146 else if (e == QKeySequence::MoveToPreviousChar) {
147 op = QTextCursor::Left;
149 else if (e == QKeySequence::SelectNextChar) {
150 op = QTextCursor::Right;
151 mode = QTextCursor::KeepAnchor;
153 else if (e == QKeySequence::SelectPreviousChar) {
154 op = QTextCursor::Left;
155 mode = QTextCursor::KeepAnchor;
157 else if (e == QKeySequence::SelectNextWord) {
158 op = QTextCursor::WordRight;
159 mode = QTextCursor::KeepAnchor;
161 else if (e == QKeySequence::SelectPreviousWord) {
162 op = QTextCursor::WordLeft;
163 mode = QTextCursor::KeepAnchor;
165 else if (e == QKeySequence::SelectStartOfLine) {
166 op = QTextCursor::StartOfLine;
167 mode = QTextCursor::KeepAnchor;
169 else if (e == QKeySequence::SelectEndOfLine) {
170 op = QTextCursor::EndOfLine;
171 mode = QTextCursor::KeepAnchor;
173 else if (e == QKeySequence::SelectStartOfBlock) {
174 op = QTextCursor::StartOfBlock;
175 mode = QTextCursor::KeepAnchor;
177 else if (e == QKeySequence::SelectEndOfBlock) {
178 op = QTextCursor::EndOfBlock;
179 mode = QTextCursor::KeepAnchor;
181 else if (e == QKeySequence::SelectStartOfDocument) {
182 op = QTextCursor::Start;
183 mode = QTextCursor::KeepAnchor;
185 else if (e == QKeySequence::SelectEndOfDocument) {
186 op = QTextCursor::End;
187 mode = QTextCursor::KeepAnchor;
189 else if (e == QKeySequence::SelectPreviousLine) {
190 op = QTextCursor::Up;
191 mode = QTextCursor::KeepAnchor;
193 QTextBlock block = cursor.block();
194 QTextLine line = currentTextLine(cursor);
195 if (!block.previous().isValid()
197 && line.lineNumber() == 0)
198 op = QTextCursor::Start;
201 else if (e == QKeySequence::SelectNextLine) {
202 op = QTextCursor::Down;
203 mode = QTextCursor::KeepAnchor;
205 QTextBlock block = cursor.block();
206 QTextLine line = currentTextLine(cursor);
207 if (!block.next().isValid()
209 && line.lineNumber() == block.layout()->lineCount() - 1)
210 op = QTextCursor::End;
213 else if (e == QKeySequence::MoveToNextWord) {
214 op = QTextCursor::WordRight;
216 else if (e == QKeySequence::MoveToPreviousWord) {
217 op = QTextCursor::WordLeft;
219 else if (e == QKeySequence::MoveToEndOfBlock) {
220 op = QTextCursor::EndOfBlock;
222 else if (e == QKeySequence::MoveToStartOfBlock) {
223 op = QTextCursor::StartOfBlock;
225 else if (e == QKeySequence::MoveToNextLine) {
226 op = QTextCursor::Down;
228 else if (e == QKeySequence::MoveToPreviousLine) {
229 op = QTextCursor::Up;
231 else if (e == QKeySequence::MoveToStartOfLine) {
232 op = QTextCursor::StartOfLine;
234 else if (e == QKeySequence::MoveToEndOfLine) {
235 op = QTextCursor::EndOfLine;
237 else if (e == QKeySequence::MoveToStartOfDocument) {
238 op = QTextCursor::Start;
240 else if (e == QKeySequence::MoveToEndOfDocument) {
241 op = QTextCursor::End;
258 bool visualNavigation = cursor.visualNavigation();
259 cursor.setVisualNavigation(
true);
260 const bool moved = cursor.movePosition(op, mode);
261 cursor.setVisualNavigation(visualNavigation);
262 q->ensureCursorVisible();
264 bool ignoreNavigationEvents = ignoreUnusedNavigationEvents;
265 bool isNavigationEvent = e->key() == Qt::Key_Up || e->key() == Qt::Key_Down ||
266 e->key() == Qt::Key_Left || e->key() == Qt::Key_Right;
269 if (cursor.position() != oldCursorPos)
270 emit q->cursorPositionChanged();
271 emit q->microFocusChanged();
272 }
else if (ignoreNavigationEvents && isNavigationEvent && oldSelection.anchor() == cursor.anchor()) {
276 selectionChanged((mode == QTextCursor::KeepAnchor));
278 repaintOldAndNewSelection(oldSelection);
400 Q_Q(QWidgetTextControl);
404 const QTextCharFormat charFormatForInsertion = cursor.charFormat();
406 bool clearDocument =
true;
411 palette = QApplication::palette(
"QWidgetTextControl");
412 doc =
new QTextDocument(q);
414 clearDocument =
false;
416 cursor = QTextCursor(doc);
420 QObjectPrivate::connect(doc, &QTextDocument::contentsChanged,
this,
421 &QWidgetTextControlPrivate::_q_updateCurrentCharFormatAndSelection);
422 QObjectPrivate::connect(doc, &QTextDocument::cursorPositionChanged,
this,
423 &QWidgetTextControlPrivate::_q_emitCursorPosChanged);
424 QObjectPrivate::connect(doc, &QTextDocument::documentLayoutChanged,
this,
425 &QWidgetTextControlPrivate::_q_documentLayoutChanged);
428 QObject::connect(doc, &QTextDocument::undoAvailable, q, &QWidgetTextControl::undoAvailable);
429 QObject::connect(doc, &QTextDocument::redoAvailable, q, &QWidgetTextControl::redoAvailable);
430 QObject::connect(doc, &QTextDocument::modificationChanged, q,
431 &QWidgetTextControl::modificationChanged);
432 QObject::connect(doc, &QTextDocument::blockCountChanged, q,
433 &QWidgetTextControl::blockCountChanged);
436 bool previousUndoRedoState =
doc->isUndoRedoEnabled();
438 doc->setUndoRedoEnabled(
false);
441 static int contentsChangedIndex = QMetaMethod::fromSignal(&QTextDocument::contentsChanged).methodIndex();
442 static int textChangedIndex = QMetaMethod::fromSignal(&QWidgetTextControl::textChanged).methodIndex();
444 QMetaObject::disconnect(doc, contentsChangedIndex, q, textChangedIndex);
446 if (!text.isEmpty()) {
453 cursor = QTextCursor();
454 if (format == Qt::PlainText) {
455 QTextCursor formatCursor(doc);
459 formatCursor.beginEditBlock();
460 doc->setPlainText(text);
461 doc->setUndoRedoEnabled(
false);
462 formatCursor.select(QTextCursor::Document);
463 formatCursor.setCharFormat(charFormatForInsertion);
464 formatCursor.endEditBlock();
465#if QT_CONFIG(textmarkdownreader)
466 }
else if (format == Qt::MarkdownText) {
467 doc->setMarkdown(text);
468 doc->setUndoRedoEnabled(
false);
471#ifndef QT_NO_TEXTHTMLPARSER
474 doc->setPlainText(text);
476 doc->setUndoRedoEnabled(
false);
478 cursor = QTextCursor(doc);
479 }
else if (clearDocument) {
482 cursor.setCharFormat(charFormatForInsertion);
484 QMetaObject::connect(doc, contentsChangedIndex, q, textChangedIndex);
485 emit q->textChanged();
487 doc->setUndoRedoEnabled(previousUndoRedoState);
490 doc->setModified(
false);
492 q->ensureCursorVisible();
493 emit q->cursorPositionChanged();
495 QObjectPrivate::connect(doc, &QTextDocument::contentsChange,
this,
496 &QWidgetTextControlPrivate::_q_contentsChanged, Qt::UniqueConnection);
580 Q_Q(QWidgetTextControl);
581 if (forceEmitSelectionChanged) {
582 emit q->selectionChanged();
583#if QT_CONFIG(accessibility)
584 if (q->parent() && q->parent()->isWidgetType()) {
585 QAccessibleTextSelectionEvent ev(q->parent(), cursor.anchor(), cursor.position());
586 QAccessible::updateAccessibility(&ev);
591 if (cursor.position() == lastSelectionPosition
592 && cursor.anchor() == lastSelectionAnchor)
595 bool selectionStateChange = (cursor.hasSelection()
596 != (lastSelectionPosition != lastSelectionAnchor));
597 if (selectionStateChange)
598 emit q->copyAvailable(cursor.hasSelection());
600 if (!forceEmitSelectionChanged
601 && (selectionStateChange
602 || (cursor.hasSelection()
603 && (cursor.position() != lastSelectionPosition
604 || cursor.anchor() != lastSelectionAnchor)))) {
605 emit q->selectionChanged();
606#if QT_CONFIG(accessibility)
607 if (q->parent() && q->parent()->isWidgetType()) {
608 QAccessibleTextSelectionEvent ev(q->parent(), cursor.anchor(), cursor.position());
609 QAccessible::updateAccessibility(&ev);
613 emit q->microFocusChanged();
614 lastSelectionPosition = cursor.position();
615 lastSelectionAnchor = cursor.anchor();
720 Q_Q(QWidgetTextControl);
723 if (suggestedNewPosition >= selectedWordOnDoubleClick.selectionStart()
724 && suggestedNewPosition <= selectedWordOnDoubleClick.selectionEnd()) {
725 q->setTextCursor(selectedWordOnDoubleClick);
729 QTextCursor curs = selectedWordOnDoubleClick;
730 curs.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
732 if (!curs.movePosition(QTextCursor::StartOfWord))
734 const int wordStartPos = curs.position();
736 const int blockPos = curs.block().position();
737 const QPointF blockCoordinates = q->blockBoundingRect(curs.block()).topLeft();
739 QTextLine line = currentTextLine(curs);
743 const qreal wordStartX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x();
745 if (!curs.movePosition(QTextCursor::EndOfWord))
747 const int wordEndPos = curs.position();
749 const QTextLine otherLine = currentTextLine(curs);
750 if (otherLine.textStart() != line.textStart()
751 || wordEndPos == wordStartPos)
754 const qreal wordEndX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x();
760 if (suggestedNewPosition < selectedWordOnDoubleClick.position()) {
761 cursor.setPosition(selectedWordOnDoubleClick.selectionEnd());
762 setCursorPosition(wordStartPos, QTextCursor::KeepAnchor);
764 cursor.setPosition(selectedWordOnDoubleClick.selectionStart());
765 setCursorPosition(wordEndPos, QTextCursor::KeepAnchor);
770 if (suggestedNewPosition < selectedWordOnDoubleClick.position())
771 cursor.setPosition(selectedWordOnDoubleClick.selectionEnd());
773 cursor.setPosition(selectedWordOnDoubleClick.selectionStart());
775 const qreal differenceToStart = mouseXPosition - wordStartX;
776 const qreal differenceToEnd = wordEndX - mouseXPosition;
778 if (differenceToStart < differenceToEnd)
779 setCursorPosition(wordStartPos, QTextCursor::KeepAnchor);
781 setCursorPosition(wordEndPos, QTextCursor::KeepAnchor);
784 if (interactionFlags & Qt::TextSelectableByMouse) {
785#ifndef QT_NO_CLIPBOARD
987void QWidgetTextControl::processEvent(QEvent *e,
const QTransform &transform, QWidget *contextWidget)
989 Q_D(QWidgetTextControl);
990 if (d->interactionFlags == Qt::NoTextInteraction) {
995 d->contextWidget = contextWidget;
997 if (!d->contextWidget) {
999#if QT_CONFIG(graphicsview)
1000 case QEvent::GraphicsSceneMouseMove:
1001 case QEvent::GraphicsSceneMousePress:
1002 case QEvent::GraphicsSceneMouseRelease:
1003 case QEvent::GraphicsSceneMouseDoubleClick:
1004 case QEvent::GraphicsSceneContextMenu:
1005 case QEvent::GraphicsSceneHoverEnter:
1006 case QEvent::GraphicsSceneHoverMove:
1007 case QEvent::GraphicsSceneHoverLeave:
1008 case QEvent::GraphicsSceneHelp:
1009 case QEvent::GraphicsSceneDragEnter:
1010 case QEvent::GraphicsSceneDragMove:
1011 case QEvent::GraphicsSceneDragLeave:
1012 case QEvent::GraphicsSceneDrop: {
1013 QGraphicsSceneEvent *ev =
static_cast<QGraphicsSceneEvent *>(e);
1014 d->contextWidget = ev->widget();
1022 switch (e->type()) {
1023 case QEvent::KeyPress:
1024 d->keyPressEvent(
static_cast<QKeyEvent *>(e));
1026 case QEvent::MouseButtonPress: {
1027 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1028 d->mousePressEvent(ev, ev->button(), transform.map(ev->position()), ev->modifiers(),
1029 ev->buttons(), ev->globalPosition());
1032 d->updateHighlightedAnchor(transform.map(
static_cast<QEnterEvent *>(e)->position()));
1035 d->resetHighlightedAnchor();
1037 case QEvent::MouseMove: {
1038 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1039 d->mouseMoveEvent(ev, ev->button(), transform.map(ev->position()), ev->modifiers(),
1040 ev->buttons(), ev->globalPosition());
1042 case QEvent::MouseButtonRelease: {
1043 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1044 d->mouseReleaseEvent(ev, ev->button(), transform.map(ev->position()), ev->modifiers(),
1045 ev->buttons(), ev->globalPosition());
1047 case QEvent::MouseButtonDblClick: {
1048 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1049 d->mouseDoubleClickEvent(ev, ev->button(), transform.map(ev->position()), ev->modifiers(),
1050 ev->buttons(), ev->globalPosition());
1052 case QEvent::InputMethod:
1053 d->inputMethodEvent(
static_cast<QInputMethodEvent *>(e));
1055#ifndef QT_NO_CONTEXTMENU
1056 case QEvent::ContextMenu: {
1057 QContextMenuEvent *ev =
static_cast<QContextMenuEvent *>(e);
1058 d->contextMenuEvent(ev->globalPos(), transform.map(ev->pos()), contextWidget);
1061 case QEvent::FocusIn:
1062 case QEvent::FocusOut:
1063 d->focusEvent(
static_cast<QFocusEvent *>(e));
1066 case QEvent::EnabledChange:
1067 d->isEnabled = e->isAccepted();
1070#if QT_CONFIG(tooltip)
1071 case QEvent::ToolTip: {
1072 QHelpEvent *ev =
static_cast<QHelpEvent *>(e);
1073 d->showToolTip(ev->globalPos(), transform.map(ev->pos()), contextWidget);
1078#if QT_CONFIG(draganddrop)
1079 case QEvent::DragEnter: {
1080 QDragEnterEvent *ev =
static_cast<QDragEnterEvent *>(e);
1081 if (d->dragEnterEvent(e, ev->mimeData()))
1082 ev->acceptProposedAction();
1085 case QEvent::DragLeave:
1086 d->dragLeaveEvent();
1088 case QEvent::DragMove: {
1089 QDragMoveEvent *ev =
static_cast<QDragMoveEvent *>(e);
1090 if (d->dragMoveEvent(e, ev->mimeData(), transform.map(ev->position())))
1091 ev->acceptProposedAction();
1094 case QEvent::Drop: {
1095 QDropEvent *ev =
static_cast<QDropEvent *>(e);
1096 if (d->dropEvent(ev->mimeData(), transform.map(ev->position()), ev->dropAction(), ev->source()))
1097 ev->acceptProposedAction();
1102#if QT_CONFIG(graphicsview)
1103 case QEvent::GraphicsSceneMousePress: {
1104 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1105 d->mousePressEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1108 case QEvent::GraphicsSceneMouseMove: {
1109 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1110 d->mouseMoveEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1113 case QEvent::GraphicsSceneMouseRelease: {
1114 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1115 d->mouseReleaseEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1118 case QEvent::GraphicsSceneMouseDoubleClick: {
1119 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1120 d->mouseDoubleClickEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1123 case QEvent::GraphicsSceneContextMenu: {
1124 QGraphicsSceneContextMenuEvent *ev =
static_cast<QGraphicsSceneContextMenuEvent *>(e);
1125 d->contextMenuEvent(ev->screenPos(), transform.map(ev->pos()), contextWidget);
1128 case QEvent::GraphicsSceneHoverMove: {
1129 QGraphicsSceneHoverEvent *ev =
static_cast<QGraphicsSceneHoverEvent *>(e);
1130 d->mouseMoveEvent(ev, Qt::NoButton, transform.map(ev->pos()), ev->modifiers(),Qt::NoButton,
1134 case QEvent::GraphicsSceneDragEnter: {
1135 QGraphicsSceneDragDropEvent *ev =
static_cast<QGraphicsSceneDragDropEvent *>(e);
1136 if (d->dragEnterEvent(e, ev->mimeData()))
1137 ev->acceptProposedAction();
1139 case QEvent::GraphicsSceneDragLeave:
1140 d->dragLeaveEvent();
1142 case QEvent::GraphicsSceneDragMove: {
1143 QGraphicsSceneDragDropEvent *ev =
static_cast<QGraphicsSceneDragDropEvent *>(e);
1144 if (d->dragMoveEvent(e, ev->mimeData(), transform.map(ev->pos())))
1145 ev->acceptProposedAction();
1147 case QEvent::GraphicsSceneDrop: {
1148 QGraphicsSceneDragDropEvent *ev =
static_cast<QGraphicsSceneDragDropEvent *>(e);
1149 if (d->dropEvent(ev->mimeData(), transform.map(ev->pos()), ev->dropAction(), ev->source()))
1153 case QEvent::ShortcutOverride:
1154 if (d->interactionFlags & Qt::TextEditable) {
1155 QKeyEvent* ke =
static_cast<QKeyEvent *>(e);
1156 if (isCommonTextEditShortcut(ke))
1208 Q_Q(QWidgetTextControl);
1209#ifndef QT_NO_SHORTCUT
1210 if (e == QKeySequence::SelectAll) {
1213#ifndef QT_NO_CLIPBOARD
1214 setClipboardSelection();
1218#ifndef QT_NO_CLIPBOARD
1219 else if (e == QKeySequence::Copy) {
1227 if (interactionFlags & Qt::TextSelectableByKeyboard
1228 && cursorMoveKeyEvent(e))
1231 if (interactionFlags & Qt::LinksAccessibleByKeyboard) {
1232 if ((e->key() == Qt::Key_Return
1233 || e->key() == Qt::Key_Enter)
1234 && cursor.hasSelection()) {
1237 activateLinkUnderCursor();
1242 if (!(interactionFlags & Qt::TextEditable)) {
1247 if (e->key() == Qt::Key_Direction_L || e->key() == Qt::Key_Direction_R) {
1248 QTextBlockFormat fmt;
1249 fmt.setLayoutDirection((e->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
1250 cursor.mergeBlockFormat(fmt);
1260 if (e->key() == Qt::Key_Backspace && !(e->modifiers() & ~(Qt::ShiftModifier | Qt::GroupSwitchModifier))) {
1261 QTextBlockFormat blockFmt = cursor.blockFormat();
1262 QTextList *list = cursor.currentList();
1263 if (list && cursor.atBlockStart() && !cursor.hasSelection()) {
1264 list->remove(cursor.block());
1265 }
else if (cursor.atBlockStart() && blockFmt.indent() > 0) {
1266 blockFmt.setIndent(blockFmt.indent() - 1);
1267 cursor.setBlockFormat(blockFmt);
1269 QTextCursor localCursor = cursor;
1270 localCursor.deletePreviousChar();
1276#ifndef QT_NO_SHORTCUT
1277 else if (e == QKeySequence::InsertParagraphSeparator) {
1278 insertParagraphSeparator();
1281 }
else if (e == QKeySequence::InsertLineSeparator) {
1282 cursor.insertText(QString(QChar::LineSeparator));
1289#ifndef QT_NO_SHORTCUT
1290 else if (e == QKeySequence::Undo) {
1293 else if (e == QKeySequence::Redo) {
1296#ifndef QT_NO_CLIPBOARD
1297 else if (e == QKeySequence::Cut) {
1300 else if (e == QKeySequence::Paste) {
1301 QClipboard::Mode mode = QClipboard::Clipboard;
1302 if (QGuiApplication::clipboard()->supportsSelection()) {
1303 if (e->modifiers() == (Qt::CTRL | Qt::SHIFT) && e->key() == Qt::Key_Insert)
1304 mode = QClipboard::Selection;
1309 else if (e == QKeySequence::Delete) {
1310 QTextCursor localCursor = cursor;
1311 localCursor.deleteChar();
1314 }
else if (e == QKeySequence::Backspace) {
1315 QTextCursor localCursor = cursor;
1316 localCursor.deletePreviousChar();
1319 }
else if (e == QKeySequence::DeleteEndOfWord) {
1320 if (!cursor.hasSelection())
1321 cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor);
1322 cursor.removeSelectedText();
1324 else if (e == QKeySequence::DeleteStartOfWord) {
1325 if (!cursor.hasSelection())
1326 cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor);
1327 cursor.removeSelectedText();
1329 else if (e == QKeySequence::DeleteEndOfLine) {
1330 QTextBlock block = cursor.block();
1331 if (cursor.position() == block.position() + block.length() - 2)
1332 cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
1334 cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
1335 cursor.removeSelectedText();
1345 if (q->isAcceptableInput(e)) {
1349 && !cursor.hasSelection()
1350 && !cursor.atBlockEnd())
1351 cursor.deleteChar();
1353 cursor.insertText(e->text());
1363#ifndef QT_NO_CLIPBOARD
1364 setClipboardSelection();
1370 q->ensureCursorVisible();
1372 updateCurrentCharFormat();
1461QRectF QWidgetTextControl::selectionRect(
const QTextCursor &cursor)
const
1463 Q_D(
const QWidgetTextControl);
1465 QRectF r = d->rectForPosition(cursor.selectionStart());
1467 if (cursor.hasComplexSelection() && cursor.currentTable()) {
1468 QTextTable *table = cursor.currentTable();
1470 r = d->doc->documentLayout()->frameBoundingRect(table);
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512 }
else if (cursor.hasSelection()) {
1513 const int position = cursor.selectionStart();
1514 const int anchor = cursor.selectionEnd();
1515 const QTextBlock posBlock = d->doc->findBlock(position);
1516 const QTextBlock anchorBlock = d->doc->findBlock(anchor);
1517 if (posBlock == anchorBlock && posBlock.isValid() && posBlock.layout()->lineCount()) {
1518 const QTextLine posLine = posBlock.layout()->lineForTextPosition(position - posBlock.position());
1519 const QTextLine anchorLine = anchorBlock.layout()->lineForTextPosition(anchor - anchorBlock.position());
1521 const int firstLine = qMin(posLine.lineNumber(), anchorLine.lineNumber());
1522 const int lastLine = qMax(posLine.lineNumber(), anchorLine.lineNumber());
1523 const QTextLayout *layout = posBlock.layout();
1525 for (
int i = firstLine; i <= lastLine; ++i) {
1526 r |= layout->lineAt(i).rect();
1527 r |= layout->lineAt(i).naturalTextRect();
1529 r.translate(blockBoundingRect(posBlock).topLeft());
1531 QRectF anchorRect = d->rectForPosition(cursor.selectionEnd());
1533 r |= boundingRectOfFloatsInSelection(cursor);
1534 QRectF frameRect(d->doc->documentLayout()->frameBoundingRect(cursor.currentFrame()));
1535 r.setLeft(frameRect.left());
1536 r.setRight(frameRect.right());
1539 r.adjust(-1, -1, 1, 1);
1552 Qt::MouseButtons buttons,
const QPointF &globalPos)
1554 Q_Q(QWidgetTextControl);
1556 mousePressPos = pos;
1558#if QT_CONFIG(draganddrop)
1559 mightStartDrag =
false;
1562 if (sendMouseEventToInputContext(
1563 e, QEvent::MouseButtonPress, button, pos, modifiers, buttons, globalPos)) {
1567 if (interactionFlags & Qt::LinksAccessibleByMouse) {
1568 anchorOnMousePress = q->anchorAt(pos);
1573 cursor.clearSelection();
1576 if (!(button & Qt::LeftButton) ||
1577 !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))) {
1581 bool wasValid = blockWithMarkerUnderMouse.isValid();
1582 blockWithMarkerUnderMouse = q->blockWithMarkerAt(pos);
1583 if (wasValid != blockWithMarkerUnderMouse.isValid())
1584 emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
1588 const QTextCursor oldSelection = cursor;
1589 const int oldCursorPos = cursor.position();
1591 mousePressed = (interactionFlags & Qt::TextSelectableByMouse);
1595 if (trippleClickTimer.isActive()
1596 && ((pos - trippleClickPoint).manhattanLength() < QApplication::startDragDistance())) {
1598 cursor.movePosition(QTextCursor::StartOfBlock);
1599 cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
1600 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
1601 selectedBlockOnTrippleClick = cursor;
1603 anchorOnMousePress = QString();
1604 blockWithMarkerUnderMouse = QTextBlock();
1605 emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
1607 trippleClickTimer.stop();
1609 int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
1610 if (cursorPos == -1) {
1615 if (modifiers == Qt::ShiftModifier && (interactionFlags & Qt::TextSelectableByMouse)) {
1616 if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) {
1617 selectedWordOnDoubleClick = cursor;
1618 selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor);
1621 if (selectedBlockOnTrippleClick.hasSelection())
1623 else if (selectedWordOnDoubleClick.hasSelection())
1624 extendWordwiseSelection(cursorPos, pos.x());
1625 else if (!wordSelectionEnabled)
1626 setCursorPosition(cursorPos, QTextCursor::KeepAnchor);
1630 && cursor.hasSelection()
1631 && !cursorIsFocusIndicator
1632 && cursorPos >= cursor.selectionStart()
1633 && cursorPos <= cursor.selectionEnd()
1634 && q->hitTest(pos, Qt::ExactHit) != -1) {
1635#if QT_CONFIG(draganddrop)
1636 mightStartDrag =
true;
1641 setCursorPosition(cursorPos);
1645 if (interactionFlags & Qt::TextEditable) {
1646 q->ensureCursorVisible();
1647 if (cursor.position() != oldCursorPos)
1648 emit q->cursorPositionChanged();
1651 if (cursor.position() != oldCursorPos) {
1652 emit q->cursorPositionChanged();
1653 emit q->microFocusChanged();
1657 repaintOldAndNewSelection(oldSelection);
1658 hadSelectionOnMousePress = cursor.hasSelection();
1662 Qt::MouseButtons buttons,
const QPointF &globalPos)
1664 Q_Q(QWidgetTextControl);
1666 if (interactionFlags & Qt::LinksAccessibleByMouse)
1667 updateHighlightedAnchor(mousePos);
1669 if (buttons & Qt::LeftButton) {
1670 const bool editable = interactionFlags & Qt::TextEditable;
1675 || selectedWordOnDoubleClick.hasSelection()
1676 || selectedBlockOnTrippleClick.hasSelection()))
1679 const QTextCursor oldSelection = cursor;
1680 const int oldCursorPos = cursor.position();
1683 if ((mousePos - mousePressPos).manhattanLength() > QApplication::startDragDistance())
1688 const qreal mouseX = qreal(mousePos.x());
1690 int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1694 int selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1696 if (newCursorPos != selectionStartPos) {
1699 newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1700 selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1701 setCursorPosition(selectionStartPos);
1705 if (newCursorPos == -1)
1708 if (mousePressed && wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) {
1709 selectedWordOnDoubleClick = cursor;
1710 selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor);
1713 if (selectedBlockOnTrippleClick.hasSelection())
1715 else if (selectedWordOnDoubleClick.hasSelection())
1716 extendWordwiseSelection(newCursorPos, mouseX);
1717 else if (mousePressed && !isPreediting())
1718 setCursorPosition(newCursorPos, QTextCursor::KeepAnchor);
1720 if (interactionFlags & Qt::TextEditable) {
1724 if (cursor.position() != oldCursorPos)
1725 emit q->cursorPositionChanged();
1729 QGuiApplication::inputMethod()->update(Qt::ImQueryInput);
1733 if (cursor.position() != oldCursorPos) {
1734 emit q->cursorPositionChanged();
1735 emit q->microFocusChanged();
1739 repaintOldAndNewSelection(oldSelection);
1741 bool wasValid = blockWithMarkerUnderMouse.isValid();
1742 blockWithMarkerUnderMouse = q->blockWithMarkerAt(mousePos);
1743 if (wasValid != blockWithMarkerUnderMouse.isValid())
1744 emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
1747 sendMouseEventToInputContext(e, QEvent::MouseMove, button, mousePos, modifiers, buttons, globalPos);
1751 Qt::MouseButtons buttons,
const QPointF &globalPos)
1753 Q_Q(QWidgetTextControl);
1755 const QTextCursor oldSelection = cursor;
1756 if (sendMouseEventToInputContext(
1757 e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) {
1758 repaintOldAndNewSelection(oldSelection);
1762 const int oldCursorPos = cursor.position();
1764#if QT_CONFIG(draganddrop)
1765 if (mightStartDrag && (button & Qt::LeftButton)) {
1766 mousePressed =
false;
1767 setCursorPosition(pos);
1768 cursor.clearSelection();
1774#ifndef QT_NO_CLIPBOARD
1777 }
else if (button == Qt::MiddleButton
1778 && (interactionFlags & Qt::TextEditable)
1779 && QGuiApplication::clipboard()->supportsSelection()) {
1780 setCursorPosition(pos);
1781 const QMimeData *md = QGuiApplication::clipboard()->mimeData(QClipboard::Selection);
1783 q->insertFromMimeData(md);
1787 repaintOldAndNewSelection(oldSelection);
1789 if (cursor.position() != oldCursorPos) {
1790 emit q->cursorPositionChanged();
1791 emit q->microFocusChanged();
1795 if ((interactionFlags & Qt::TextEditable) && (button & Qt::LeftButton) &&
1796 (blockWithMarkerUnderMouse.isValid()) && !cursor.hasSelection()) {
1797 QTextBlock markerBlock = q->blockWithMarkerAt(pos);
1798 if (markerBlock == blockWithMarkerUnderMouse) {
1799 auto fmt = blockWithMarkerUnderMouse.blockFormat();
1800 switch (fmt.marker()) {
1801 case QTextBlockFormat::MarkerType::Unchecked :
1802 fmt.setMarker(QTextBlockFormat::MarkerType::Checked);
1804 case QTextBlockFormat::MarkerType::Checked:
1805 fmt.setMarker(QTextBlockFormat::MarkerType::Unchecked);
1810 cursor.setBlockFormat(fmt);
1814 if (interactionFlags & Qt::LinksAccessibleByMouse) {
1817 if (!(button & Qt::LeftButton)) {
1822 const QString anchor = q->anchorAt(pos);
1825 if (anchor.isEmpty()) {
1830 if (!cursor.hasSelection()
1831 || (anchor == anchorOnMousePress && hadSelectionOnMousePress)) {
1833 const int anchorPos = q->hitTest(pos, Qt::ExactHit);
1836 if (anchorPos < 0) {
1841 cursor.setPosition(anchorPos);
1842 activateLinkUnderCursor(std::exchange(anchorOnMousePress, QString()));
2028 Q_Q(QWidgetTextControl);
2029 if (!(interactionFlags & (Qt::TextEditable | Qt::TextSelectableByMouse)) || cursor.isNull()) {
2033 bool isGettingInput = !e->commitString().isEmpty()
2034 || e->preeditString() != cursor.block().layout()->preeditAreaText()
2035 || e->replacementLength() > 0;
2037 if (!isGettingInput && e->attributes().isEmpty()) {
2042 int oldCursorPos = cursor.position();
2044 cursor.beginEditBlock();
2045 if (isGettingInput) {
2046 cursor.removeSelectedText();
2052 if (!e->commitString().isEmpty() || e->replacementLength()) {
2053 auto *mimeData = QInputControl::mimeDataForInputEvent(e);
2054 if (mimeData && q->canInsertFromMimeData(mimeData)) {
2055 q->insertFromMimeData(mimeData);
2057 if (e->commitString().endsWith(QChar::LineFeed))
2058 block = cursor.block();
2059 QTextCursor c = cursor;
2060 c.setPosition(c.position() + e->replacementStart());
2061 c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor);
2062 c.insertText(e->commitString());
2066 for (
int i = 0; i < e->attributes().size(); ++i) {
2067 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
2068 if (a.type == QInputMethodEvent::Selection) {
2069 QTextCursor oldCursor = cursor;
2070 int blockStart = a.start + cursor.block().position();
2071 cursor.setPosition(blockStart, QTextCursor::MoveAnchor);
2072 cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
2073 q->ensureCursorVisible();
2074 repaintOldAndNewSelection(oldCursor);
2078 if (!block.isValid())
2079 block = cursor.block();
2080 QTextLayout *layout = block.layout();
2082 layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
2083 QList<QTextLayout::FormatRange> overrides;
2084 overrides.reserve(e->attributes().size());
2085 const int oldPreeditCursor = preeditCursor;
2086 preeditCursor = e->preeditString().size();
2088 for (
int i = 0; i < e->attributes().size(); ++i) {
2089 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
2090 if (a.type == QInputMethodEvent::Cursor) {
2091 preeditCursor = a.start;
2092 hideCursor = !a.length;
2093 }
else if (a.type == QInputMethodEvent::TextFormat) {
2094 QTextCharFormat f = cursor.charFormat();
2095 f.merge(qvariant_cast<QTextFormat>(a.value).toCharFormat());
2097 QTextLayout::FormatRange o;
2098 o.start = a.start + cursor.position() - block.position();
2099 o.length = a.length;
2103 QList<QTextLayout::FormatRange>::iterator it = overrides.end();
2104 while (it != overrides.begin()) {
2105 QList<QTextLayout::FormatRange>::iterator previous = it - 1;
2106 if (o.start >= previous->start) {
2107 overrides.insert(it, o);
2113 if (it == overrides.begin())
2114 overrides.prepend(o);
2119 if (cursor.charFormat().isValid()) {
2120 int start = cursor.position() - block.position();
2121 int end = start + e->preeditString().size();
2123 QList<QTextLayout::FormatRange>::iterator it = overrides.begin();
2124 while (it != overrides.end()) {
2125 QTextLayout::FormatRange range = *it;
2126 int rangeStart = range.start;
2127 if (rangeStart > start) {
2128 QTextLayout::FormatRange o;
2130 o.length = rangeStart - start;
2131 o.format = cursor.charFormat();
2132 it = overrides.insert(it, o) + 1;
2136 start = range.start + range.length;
2140 QTextLayout::FormatRange o;
2142 o.length = end - start;
2143 o.format = cursor.charFormat();
2144 overrides.append(o);
2147 layout->setFormats(overrides);
2149 cursor.endEditBlock();
2153 if (oldCursorPos != cursor.position())
2154 emit q->cursorPositionChanged();
2155 if (oldPreeditCursor != preeditCursor)
2156 emit q->microFocusChanged();
2159QVariant QWidgetTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument)
const
2161 Q_D(
const QWidgetTextControl);
2162 QTextBlock block = d->cursor.block();
2164 case Qt::ImCursorRectangle:
2165 return cursorRect();
2166 case Qt::ImAnchorRectangle:
2167 return d->rectForPosition(d->cursor.anchor());
2169 return QVariant(d->cursor.charFormat().font());
2170 case Qt::ImCursorPosition: {
2171 const QPointF pt = argument.toPointF();
2173 return QVariant(cursorForPosition(pt).position() - block.position());
2174 return QVariant(d->cursor.position() - block.position()); }
2175 case Qt::ImSurroundingText:
2176 return QVariant(block.text());
2177 case Qt::ImCurrentSelection: {
2178 QMimeData *mimeData = createMimeDataFromSelection();
2179 mimeData->deleteLater();
2180 return QInputControl::selectionWrapper(mimeData);
2182 case Qt::ImMaximumTextLength:
2184 case Qt::ImAnchorPosition:
2185 return QVariant(d->cursor.anchor() - block.position());
2186 case Qt::ImAbsolutePosition: {
2187 const QPointF pt = argument.toPointF();
2189 return QVariant(cursorForPosition(pt).position());
2190 return QVariant(d->cursor.position()); }
2191 case Qt::ImTextAfterCursor:
2193 int maxLength = argument.isValid() ? argument.toInt() : 1024;
2194 QTextCursor tmpCursor = d->cursor;
2195 int localPos = d->cursor.position() - block.position();
2196 QString result = block.text().mid(localPos);
2197 while (result.size() < maxLength) {
2198 int currentBlock = tmpCursor.blockNumber();
2199 tmpCursor.movePosition(QTextCursor::NextBlock);
2200 if (tmpCursor.blockNumber() == currentBlock)
2202 result += u'\n' + tmpCursor.block().text();
2204 return QVariant(result);
2206 case Qt::ImTextBeforeCursor:
2208 int maxLength = argument.isValid() ? argument.toInt() : 1024;
2209 QTextCursor tmpCursor = d->cursor;
2210 int localPos = d->cursor.position() - block.position();
2212 int resultLen = localPos;
2213 while (resultLen < maxLength) {
2214 int currentBlock = tmpCursor.blockNumber();
2215 tmpCursor.movePosition(QTextCursor::PreviousBlock);
2216 if (tmpCursor.blockNumber() == currentBlock)
2219 resultLen += tmpCursor.block().length();
2223 result += tmpCursor.block().text() + u'\n';
2224 tmpCursor.movePosition(QTextCursor::NextBlock);
2227 result += QStringView{block.text()}.mid(0, localPos);
2228 return QVariant(result);
2288QMenu *QWidgetTextControl::createStandardContextMenu(
const QPointF &pos, QWidget *parent)
2290 Q_D(QWidgetTextControl);
2292 const bool showTextSelectionActions = d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
2294 d->linkToCopy = QString();
2296 d->linkToCopy = anchorAt(pos);
2298 if (d->linkToCopy.isEmpty() && !showTextSelectionActions)
2301 QMenu *menu =
new QMenu(parent);
2304 if (d->interactionFlags & Qt::TextEditable) {
2305 a = menu->addAction(tr(
"&Undo") +
ACCEL_KEY(QKeySequence::Undo),
this, SLOT(undo()));
2306 a->setEnabled(d->doc->isUndoAvailable());
2307 a->setObjectName(QStringLiteral(
"edit-undo"));
2308 setActionIcon(a, QStringLiteral(
"edit-undo"));
2309 a = menu->addAction(tr(
"&Redo") +
ACCEL_KEY(QKeySequence::Redo),
this, SLOT(redo()));
2310 a->setEnabled(d->doc->isRedoAvailable());
2311 a->setObjectName(QStringLiteral(
"edit-redo"));
2312 setActionIcon(a, QStringLiteral(
"edit-redo"));
2313 menu->addSeparator();
2315#ifndef QT_NO_CLIPBOARD
2316 a = menu->addAction(tr(
"Cu&t") +
ACCEL_KEY(QKeySequence::Cut),
this, SLOT(cut()));
2317 a->setEnabled(d->cursor.hasSelection());
2318 a->setObjectName(QStringLiteral(
"edit-cut"));
2319 setActionIcon(a, QStringLiteral(
"edit-cut"));
2323#ifndef QT_NO_CLIPBOARD
2324 if (showTextSelectionActions) {
2325 a = menu->addAction(tr(
"&Copy") +
ACCEL_KEY(QKeySequence::Copy),
this, SLOT(copy()));
2326 a->setEnabled(d->cursor.hasSelection());
2327 a->setObjectName(QStringLiteral(
"edit-copy"));
2328 setActionIcon(a, QStringLiteral(
"edit-copy"));
2331 if ((d->interactionFlags & Qt::LinksAccessibleByKeyboard)
2332 || (d->interactionFlags & Qt::LinksAccessibleByMouse)) {
2334 a = menu->addAction(tr(
"Copy &Link Location"),
this, SLOT(_q_copyLink()));
2335 a->setEnabled(!d->linkToCopy.isEmpty());
2336 a->setObjectName(QStringLiteral(
"link-copy"));
2340 if (d->interactionFlags & Qt::TextEditable) {
2341#ifndef QT_NO_CLIPBOARD
2342 a = menu->addAction(tr(
"&Paste") +
ACCEL_KEY(QKeySequence::Paste),
this, SLOT(paste()));
2343 a->setEnabled(canPaste());
2344 a->setObjectName(QStringLiteral(
"edit-paste"));
2345 setActionIcon(a, QStringLiteral(
"edit-paste"));
2347 a = menu->addAction(tr(
"Delete"),
this, SLOT(_q_deleteSelected()));
2348 a->setEnabled(d->cursor.hasSelection());
2349 a->setObjectName(QStringLiteral(
"edit-delete"));
2350 setActionIcon(a, QStringLiteral(
"edit-delete"));
2354 if (showTextSelectionActions) {
2355 menu->addSeparator();
2356 a = menu->addAction(tr(
"Select All") +
ACCEL_KEY(QKeySequence::SelectAll),
this, SLOT(selectAll()));
2357 a->setEnabled(!d->doc->isEmpty());
2358 a->setObjectName(QStringLiteral(
"select-all"));
2359 setActionIcon(a, QStringLiteral(
"edit-select-all"));
2362 if ((d->interactionFlags & Qt::TextEditable) && QGuiApplication::styleHints()->useRtlExtensions()) {
2363 menu->addSeparator();
2364 QUnicodeControlCharacterMenu *ctrlCharacterMenu =
new QUnicodeControlCharacterMenu(
this, menu);
2365 menu->addMenu(ctrlCharacterMenu);
2727bool QWidgetTextControl::findNextPrevAnchor(
const QTextCursor &startCursor,
bool next, QTextCursor &newAnchor)
2729 Q_D(QWidgetTextControl);
2731 int anchorStart = -1;
2736 const int startPos = startCursor.selectionEnd();
2738 QTextBlock block = d->doc->findBlock(startPos);
2739 QTextBlock::Iterator it = block.begin();
2741 while (!it.atEnd() && it.fragment().position() < startPos)
2744 while (block.isValid()) {
2748 for (; !it.atEnd(); ++it) {
2749 const QTextFragment fragment = it.fragment();
2750 const QTextCharFormat fmt = fragment.charFormat();
2752 if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) {
2753 anchorStart = fragment.position();
2754 anchorHref = fmt.anchorHref();
2759 if (anchorStart != -1) {
2763 for (; !it.atEnd(); ++it) {
2764 const QTextFragment fragment = it.fragment();
2765 const QTextCharFormat fmt = fragment.charFormat();
2767 if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) {
2768 anchorEnd = fragment.position();
2773 if (anchorEnd == -1)
2774 anchorEnd = block.position() + block.length() - 1;
2780 block = block.next();
2784 int startPos = startCursor.selectionStart();
2788 QTextBlock block = d->doc->findBlock(startPos);
2789 QTextBlock::Iterator blockStart = block.begin();
2790 QTextBlock::Iterator it = block.end();
2792 if (startPos == block.position()) {
2796 if (it == blockStart) {
2797 it = QTextBlock::Iterator();
2798 block = QTextBlock();
2802 }
while (!it.atEnd() && it.fragment().position() + it.fragment().length() - 1 > startPos);
2805 while (block.isValid()) {
2810 const QTextFragment fragment = it.fragment();
2811 const QTextCharFormat fmt = fragment.charFormat();
2813 if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) {
2814 anchorStart = fragment.position() + fragment.length();
2815 anchorHref = fmt.anchorHref();
2819 if (it == blockStart)
2820 it = QTextBlock::Iterator();
2823 }
while (!it.atEnd());
2826 if (anchorStart != -1 && !it.atEnd()) {
2830 const QTextFragment fragment = it.fragment();
2831 const QTextCharFormat fmt = fragment.charFormat();
2833 if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) {
2834 anchorEnd = fragment.position() + fragment.length();
2838 if (it == blockStart)
2839 it = QTextBlock::Iterator();
2842 }
while (!it.atEnd());
2844 if (anchorEnd == -1)
2845 anchorEnd = qMax(0, block.position());
2850 block = block.previous();
2852 if (it != block.begin())
2854 blockStart = block.begin();
2859 if (anchorStart != -1 && anchorEnd != -1) {
2860 newAnchor = d->cursor;
2861 newAnchor.setPosition(anchorStart);
2862 newAnchor.setPosition(anchorEnd, QTextCursor::KeepAnchor);
2871 QTextCursor oldCursor = cursor;
2873 if (href.isEmpty()) {
2874 QTextCursor tmp = cursor;
2875 if (tmp.selectionStart() != tmp.position())
2876 tmp.setPosition(tmp.selectionStart());
2877 tmp.movePosition(QTextCursor::NextCharacter);
2878 href = tmp.charFormat().anchorHref();
2883 if (!cursor.hasSelection()) {
2884 QTextBlock block = cursor.block();
2885 const int cursorPos = cursor.position();
2887 QTextBlock::Iterator it = block.begin();
2888 QTextBlock::Iterator linkFragment;
2890 for (; !it.atEnd(); ++it) {
2891 QTextFragment fragment = it.fragment();
2892 const int fragmentPos = fragment.position();
2893 if (fragmentPos <= cursorPos &&
2894 fragmentPos + fragment.length() > cursorPos) {
2900 if (!linkFragment.atEnd()) {
2902 cursor.setPosition(it.fragment().position());
2903 if (it != block.begin()) {
2906 QTextFragment fragment = it.fragment();
2907 if (fragment.charFormat().anchorHref() != href)
2909 cursor.setPosition(fragment.position());
2910 }
while (it != block.begin());
2913 for (it = linkFragment; !it.atEnd(); ++it) {
2914 QTextFragment fragment = it.fragment();
2915 if (fragment.charFormat().anchorHref() != href)
2917 cursor.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor);
2926 cursor.clearSelection();
2928 repaintOldAndNewSelection(oldCursor);
2930#ifndef QT_NO_DESKTOPSERVICES
2932 QDesktopServices::openUrl(QUrl{href});
2935 emit q_func()->linkActivated(href);
3194 auto blockFmt = cursor.blockFormat();
3195 auto charFmt = cursor.charFormat();
3196 blockFmt.clearProperty(QTextFormat::BlockTrailingHorizontalRulerWidth);
3197 if (blockFmt.hasProperty(QTextFormat::HeadingLevel)) {
3198 blockFmt.clearProperty(QTextFormat::HeadingLevel);
3199 charFmt = QTextCharFormat();
3201 if (cursor.currentList()) {
3202 auto existingFmt = cursor.blockFormat();
3203 existingFmt.clearProperty(QTextBlockFormat::BlockBottomMargin);
3204 cursor.setBlockFormat(existingFmt);
3205 if (blockFmt.marker() == QTextBlockFormat::MarkerType::Checked)
3206 blockFmt.setMarker(QTextBlockFormat::MarkerType::Unchecked);
3211 if (cursor.block().text().isEmpty() &&
3212 !cursor.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth) &&
3213 !cursor.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
3214 blockFmt = QTextBlockFormat();
3215 const bool blockFmtChanged = (cursor.blockFormat() != blockFmt);
3216 charFmt = QTextCharFormat();
3217 cursor.setBlockFormat(blockFmt);
3218 cursor.setCharFormat(charFmt);
3223 if (blockFmtChanged)
3227 cursor.insertBlock(blockFmt, charFmt);
3299QAbstractTextDocumentLayout::PaintContext QWidgetTextControl::getPaintContext(QWidget *widget)
const
3301 Q_D(
const QWidgetTextControl);
3303 QAbstractTextDocumentLayout::PaintContext ctx;
3305 ctx.selections = d->extraSelections;
3306 ctx.palette = d->palette;
3307#if QT_CONFIG(style_stylesheet)
3309 if (
auto cssStyle = qt_styleSheet(widget->style())) {
3310 QStyleOption option;
3311 option.initFrom(widget);
3312 cssStyle->styleSheetPalette(widget, &option, &ctx.palette);
3316 if (d->cursorOn && d->isEnabled) {
3318 ctx.cursorPosition = -1;
3319 else if (d->preeditCursor != 0)
3320 ctx.cursorPosition = - (d->preeditCursor + 2);
3322 ctx.cursorPosition = d->cursor.position();
3325 if (!d->dndFeedbackCursor.isNull())
3326 ctx.cursorPosition = d->dndFeedbackCursor.position();
3327 if (d->cursor.hasSelection()) {
3328 QAbstractTextDocumentLayout::Selection selection;
3329 selection.cursor = d->cursor;
3330 if (d->cursorIsFocusIndicator) {
3332 opt.palette = ctx.palette;
3333 QStyleHintReturnVariant ret;
3334 QStyle *style = QApplication::style();
3336 style = widget->style();
3337 style->styleHint(QStyle::SH_TextControl_FocusIndicatorTextCharFormat, &opt, widget, &ret);
3338 selection.format = qvariant_cast<QTextFormat>(ret.variant).toCharFormat();
3340 QPalette::ColorGroup cg = d->hasFocus ? QPalette::Active : QPalette::Inactive;
3341 selection.format.setBackground(ctx.palette.brush(cg, QPalette::Highlight));
3342 selection.format.setForeground(ctx.palette.brush(cg, QPalette::HighlightedText));
3344 QStyle *style = QApplication::style();
3346 opt.initFrom(widget);
3347 style = widget->style();
3349 if (style->styleHint(QStyle::SH_RichText_FullWidthSelection, &opt, widget))
3350 selection.format.setProperty(QTextFormat::FullWidthSelection,
true);
3352 ctx.selections.append(selection);