133 Q_Q(QWidgetTextControl);
137 const QTextCursor oldSelection = cursor;
138 const int oldCursorPos = cursor.position();
140 QTextCursor::MoveMode mode = QTextCursor::MoveAnchor;
141 QTextCursor::MoveOperation op = QTextCursor::NoMove;
145#ifndef QT_NO_SHORTCUT
146 if (e == QKeySequence::MoveToNextChar) {
147 op = QTextCursor::Right;
149 else if (e == QKeySequence::MoveToPreviousChar) {
150 op = QTextCursor::Left;
152 else if (e == QKeySequence::SelectNextChar) {
153 op = QTextCursor::Right;
154 mode = QTextCursor::KeepAnchor;
156 else if (e == QKeySequence::SelectPreviousChar) {
157 op = QTextCursor::Left;
158 mode = QTextCursor::KeepAnchor;
160 else if (e == QKeySequence::SelectNextWord) {
161 op = QTextCursor::WordRight;
162 mode = QTextCursor::KeepAnchor;
164 else if (e == QKeySequence::SelectPreviousWord) {
165 op = QTextCursor::WordLeft;
166 mode = QTextCursor::KeepAnchor;
168 else if (e == QKeySequence::SelectStartOfLine) {
169 op = QTextCursor::StartOfLine;
170 mode = QTextCursor::KeepAnchor;
172 else if (e == QKeySequence::SelectEndOfLine) {
173 op = QTextCursor::EndOfLine;
174 mode = QTextCursor::KeepAnchor;
176 else if (e == QKeySequence::SelectStartOfBlock) {
177 op = QTextCursor::StartOfBlock;
178 mode = QTextCursor::KeepAnchor;
180 else if (e == QKeySequence::SelectEndOfBlock) {
181 op = QTextCursor::EndOfBlock;
182 mode = QTextCursor::KeepAnchor;
184 else if (e == QKeySequence::SelectStartOfDocument) {
185 op = QTextCursor::Start;
186 mode = QTextCursor::KeepAnchor;
188 else if (e == QKeySequence::SelectEndOfDocument) {
189 op = QTextCursor::End;
190 mode = QTextCursor::KeepAnchor;
192 else if (e == QKeySequence::SelectPreviousLine) {
193 op = QTextCursor::Up;
194 mode = QTextCursor::KeepAnchor;
196 QTextBlock block = cursor.block();
197 QTextLine line = currentTextLine(cursor);
198 if (!block.previous().isValid()
200 && line.lineNumber() == 0)
201 op = QTextCursor::Start;
204 else if (e == QKeySequence::SelectNextLine) {
205 op = QTextCursor::Down;
206 mode = QTextCursor::KeepAnchor;
208 QTextBlock block = cursor.block();
209 QTextLine line = currentTextLine(cursor);
210 if (!block.next().isValid()
212 && line.lineNumber() == block.layout()->lineCount() - 1)
213 op = QTextCursor::End;
216 else if (e == QKeySequence::MoveToNextWord) {
217 op = QTextCursor::WordRight;
219 else if (e == QKeySequence::MoveToPreviousWord) {
220 op = QTextCursor::WordLeft;
222 else if (e == QKeySequence::MoveToEndOfBlock) {
223 op = QTextCursor::EndOfBlock;
225 else if (e == QKeySequence::MoveToStartOfBlock) {
226 op = QTextCursor::StartOfBlock;
228 else if (e == QKeySequence::MoveToNextLine) {
229 op = QTextCursor::Down;
231 else if (e == QKeySequence::MoveToPreviousLine) {
232 op = QTextCursor::Up;
234 else if (e == QKeySequence::MoveToStartOfLine) {
235 op = QTextCursor::StartOfLine;
237 else if (e == QKeySequence::MoveToEndOfLine) {
238 op = QTextCursor::EndOfLine;
240 else if (e == QKeySequence::MoveToStartOfDocument) {
241 op = QTextCursor::Start;
243 else if (e == QKeySequence::MoveToEndOfDocument) {
244 op = QTextCursor::End;
261 bool visualNavigation = cursor.visualNavigation();
262 cursor.setVisualNavigation(
true);
263 const bool moved = cursor.movePosition(op, mode);
264 cursor.setVisualNavigation(visualNavigation);
265 q->ensureCursorVisible();
267 bool ignoreNavigationEvents = ignoreUnusedNavigationEvents;
268 bool isNavigationEvent = e->key() == Qt::Key_Up || e->key() == Qt::Key_Down;
270#ifdef QT_KEYPAD_NAVIGATION
271 ignoreNavigationEvents = ignoreNavigationEvents || QApplicationPrivate::keypadNavigationEnabled();
272 isNavigationEvent = isNavigationEvent ||
273 (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional
274 && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right));
276 isNavigationEvent = isNavigationEvent || e->key() == Qt::Key_Left || e->key() == Qt::Key_Right;
280 if (cursor.position() != oldCursorPos)
281 emit q->cursorPositionChanged();
282 emit q->microFocusChanged();
283 }
else if (ignoreNavigationEvents && isNavigationEvent && oldSelection.anchor() == cursor.anchor()) {
287 selectionChanged((mode == QTextCursor::KeepAnchor));
289 repaintOldAndNewSelection(oldSelection);
411 Q_Q(QWidgetTextControl);
415 const QTextCharFormat charFormatForInsertion = cursor.charFormat();
417 bool clearDocument =
true;
422 palette = QApplication::palette(
"QWidgetTextControl");
423 doc =
new QTextDocument(q);
425 clearDocument =
false;
427 cursor = QTextCursor(doc);
431 QObjectPrivate::connect(doc, &QTextDocument::contentsChanged,
this,
432 &QWidgetTextControlPrivate::_q_updateCurrentCharFormatAndSelection);
433 QObjectPrivate::connect(doc, &QTextDocument::cursorPositionChanged,
this,
434 &QWidgetTextControlPrivate::_q_emitCursorPosChanged);
435 QObjectPrivate::connect(doc, &QTextDocument::documentLayoutChanged,
this,
436 &QWidgetTextControlPrivate::_q_documentLayoutChanged);
439 QObject::connect(doc, &QTextDocument::undoAvailable, q, &QWidgetTextControl::undoAvailable);
440 QObject::connect(doc, &QTextDocument::redoAvailable, q, &QWidgetTextControl::redoAvailable);
441 QObject::connect(doc, &QTextDocument::modificationChanged, q,
442 &QWidgetTextControl::modificationChanged);
443 QObject::connect(doc, &QTextDocument::blockCountChanged, q,
444 &QWidgetTextControl::blockCountChanged);
447 bool previousUndoRedoState =
doc->isUndoRedoEnabled();
449 doc->setUndoRedoEnabled(
false);
452 static int contentsChangedIndex = QMetaMethod::fromSignal(&QTextDocument::contentsChanged).methodIndex();
453 static int textChangedIndex = QMetaMethod::fromSignal(&QWidgetTextControl::textChanged).methodIndex();
455 QMetaObject::disconnect(doc, contentsChangedIndex, q, textChangedIndex);
457 if (!text.isEmpty()) {
464 cursor = QTextCursor();
465 if (format == Qt::PlainText) {
466 QTextCursor formatCursor(doc);
470 formatCursor.beginEditBlock();
471 doc->setPlainText(text);
472 doc->setUndoRedoEnabled(
false);
473 formatCursor.select(QTextCursor::Document);
474 formatCursor.setCharFormat(charFormatForInsertion);
475 formatCursor.endEditBlock();
476#if QT_CONFIG(textmarkdownreader)
477 }
else if (format == Qt::MarkdownText) {
478 doc->setMarkdown(text);
479 doc->setUndoRedoEnabled(
false);
482#ifndef QT_NO_TEXTHTMLPARSER
485 doc->setPlainText(text);
487 doc->setUndoRedoEnabled(
false);
489 cursor = QTextCursor(doc);
490 }
else if (clearDocument) {
493 cursor.setCharFormat(charFormatForInsertion);
495 QMetaObject::connect(doc, contentsChangedIndex, q, textChangedIndex);
496 emit q->textChanged();
498 doc->setUndoRedoEnabled(previousUndoRedoState);
501 doc->setModified(
false);
503 q->ensureCursorVisible();
504 emit q->cursorPositionChanged();
506 QObjectPrivate::connect(doc, &QTextDocument::contentsChange,
this,
507 &QWidgetTextControlPrivate::_q_contentsChanged, Qt::UniqueConnection);
591 Q_Q(QWidgetTextControl);
592 if (forceEmitSelectionChanged) {
593 emit q->selectionChanged();
594#if QT_CONFIG(accessibility)
595 if (q->parent() && q->parent()->isWidgetType()) {
596 QAccessibleTextSelectionEvent ev(q->parent(), cursor.anchor(), cursor.position());
597 QAccessible::updateAccessibility(&ev);
602 if (cursor.position() == lastSelectionPosition
603 && cursor.anchor() == lastSelectionAnchor)
606 bool selectionStateChange = (cursor.hasSelection()
607 != (lastSelectionPosition != lastSelectionAnchor));
608 if (selectionStateChange)
609 emit q->copyAvailable(cursor.hasSelection());
611 if (!forceEmitSelectionChanged
612 && (selectionStateChange
613 || (cursor.hasSelection()
614 && (cursor.position() != lastSelectionPosition
615 || cursor.anchor() != lastSelectionAnchor)))) {
616 emit q->selectionChanged();
617#if QT_CONFIG(accessibility)
618 if (q->parent() && q->parent()->isWidgetType()) {
619 QAccessibleTextSelectionEvent ev(q->parent(), cursor.anchor(), cursor.position());
620 QAccessible::updateAccessibility(&ev);
624 emit q->microFocusChanged();
625 lastSelectionPosition = cursor.position();
626 lastSelectionAnchor = cursor.anchor();
731 Q_Q(QWidgetTextControl);
734 if (suggestedNewPosition >= selectedWordOnDoubleClick.selectionStart()
735 && suggestedNewPosition <= selectedWordOnDoubleClick.selectionEnd()) {
736 q->setTextCursor(selectedWordOnDoubleClick);
740 QTextCursor curs = selectedWordOnDoubleClick;
741 curs.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
743 if (!curs.movePosition(QTextCursor::StartOfWord))
745 const int wordStartPos = curs.position();
747 const int blockPos = curs.block().position();
748 const QPointF blockCoordinates = q->blockBoundingRect(curs.block()).topLeft();
750 QTextLine line = currentTextLine(curs);
754 const qreal wordStartX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x();
756 if (!curs.movePosition(QTextCursor::EndOfWord))
758 const int wordEndPos = curs.position();
760 const QTextLine otherLine = currentTextLine(curs);
761 if (otherLine.textStart() != line.textStart()
762 || wordEndPos == wordStartPos)
765 const qreal wordEndX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x();
771 if (suggestedNewPosition < selectedWordOnDoubleClick.position()) {
772 cursor.setPosition(selectedWordOnDoubleClick.selectionEnd());
773 setCursorPosition(wordStartPos, QTextCursor::KeepAnchor);
775 cursor.setPosition(selectedWordOnDoubleClick.selectionStart());
776 setCursorPosition(wordEndPos, QTextCursor::KeepAnchor);
781 if (suggestedNewPosition < selectedWordOnDoubleClick.position())
782 cursor.setPosition(selectedWordOnDoubleClick.selectionEnd());
784 cursor.setPosition(selectedWordOnDoubleClick.selectionStart());
786 const qreal differenceToStart = mouseXPosition - wordStartX;
787 const qreal differenceToEnd = wordEndX - mouseXPosition;
789 if (differenceToStart < differenceToEnd)
790 setCursorPosition(wordStartPos, QTextCursor::KeepAnchor);
792 setCursorPosition(wordEndPos, QTextCursor::KeepAnchor);
795 if (interactionFlags & Qt::TextSelectableByMouse) {
796#ifndef QT_NO_CLIPBOARD
998void QWidgetTextControl::processEvent(QEvent *e,
const QTransform &transform, QWidget *contextWidget)
1000 Q_D(QWidgetTextControl);
1001 if (d->interactionFlags == Qt::NoTextInteraction) {
1006 d->contextWidget = contextWidget;
1008 if (!d->contextWidget) {
1009 switch (e->type()) {
1010#if QT_CONFIG(graphicsview)
1011 case QEvent::GraphicsSceneMouseMove:
1012 case QEvent::GraphicsSceneMousePress:
1013 case QEvent::GraphicsSceneMouseRelease:
1014 case QEvent::GraphicsSceneMouseDoubleClick:
1015 case QEvent::GraphicsSceneContextMenu:
1016 case QEvent::GraphicsSceneHoverEnter:
1017 case QEvent::GraphicsSceneHoverMove:
1018 case QEvent::GraphicsSceneHoverLeave:
1019 case QEvent::GraphicsSceneHelp:
1020 case QEvent::GraphicsSceneDragEnter:
1021 case QEvent::GraphicsSceneDragMove:
1022 case QEvent::GraphicsSceneDragLeave:
1023 case QEvent::GraphicsSceneDrop: {
1024 QGraphicsSceneEvent *ev =
static_cast<QGraphicsSceneEvent *>(e);
1025 d->contextWidget = ev->widget();
1033 switch (e->type()) {
1034 case QEvent::KeyPress:
1035 d->keyPressEvent(
static_cast<QKeyEvent *>(e));
1037 case QEvent::MouseButtonPress: {
1038 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1039 d->mousePressEvent(ev, ev->button(), transform.map(ev->position().toPoint()), ev->modifiers(),
1040 ev->buttons(), ev->globalPosition().toPoint());
1042 case QEvent::MouseMove: {
1043 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1044 d->mouseMoveEvent(ev, ev->button(), transform.map(ev->position().toPoint()), ev->modifiers(),
1045 ev->buttons(), ev->globalPosition().toPoint());
1047 case QEvent::MouseButtonRelease: {
1048 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1049 d->mouseReleaseEvent(ev, ev->button(), transform.map(ev->position().toPoint()), ev->modifiers(),
1050 ev->buttons(), ev->globalPosition().toPoint());
1052 case QEvent::MouseButtonDblClick: {
1053 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1054 d->mouseDoubleClickEvent(ev, ev->button(), transform.map(ev->position().toPoint()), ev->modifiers(),
1055 ev->buttons(), ev->globalPosition().toPoint());
1057 case QEvent::InputMethod:
1058 d->inputMethodEvent(
static_cast<QInputMethodEvent *>(e));
1060#ifndef QT_NO_CONTEXTMENU
1061 case QEvent::ContextMenu: {
1062 QContextMenuEvent *ev =
static_cast<QContextMenuEvent *>(e);
1063 d->contextMenuEvent(ev->globalPos(), transform.map(ev->pos()), contextWidget);
1066 case QEvent::FocusIn:
1067 case QEvent::FocusOut:
1068 d->focusEvent(
static_cast<QFocusEvent *>(e));
1071 case QEvent::EnabledChange:
1072 d->isEnabled = e->isAccepted();
1075#if QT_CONFIG(tooltip)
1076 case QEvent::ToolTip: {
1077 QHelpEvent *ev =
static_cast<QHelpEvent *>(e);
1078 d->showToolTip(ev->globalPos(), transform.map(ev->pos()), contextWidget);
1083#if QT_CONFIG(draganddrop)
1084 case QEvent::DragEnter: {
1085 QDragEnterEvent *ev =
static_cast<QDragEnterEvent *>(e);
1086 if (d->dragEnterEvent(e, ev->mimeData()))
1087 ev->acceptProposedAction();
1090 case QEvent::DragLeave:
1091 d->dragLeaveEvent();
1093 case QEvent::DragMove: {
1094 QDragMoveEvent *ev =
static_cast<QDragMoveEvent *>(e);
1095 if (d->dragMoveEvent(e, ev->mimeData(), transform.map(ev->position().toPoint())))
1096 ev->acceptProposedAction();
1099 case QEvent::Drop: {
1100 QDropEvent *ev =
static_cast<QDropEvent *>(e);
1101 if (d->dropEvent(ev->mimeData(), transform.map(ev->position().toPoint()), ev->dropAction(), ev->source()))
1102 ev->acceptProposedAction();
1107#if QT_CONFIG(graphicsview)
1108 case QEvent::GraphicsSceneMousePress: {
1109 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1110 d->mousePressEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1113 case QEvent::GraphicsSceneMouseMove: {
1114 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1115 d->mouseMoveEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1118 case QEvent::GraphicsSceneMouseRelease: {
1119 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1120 d->mouseReleaseEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1123 case QEvent::GraphicsSceneMouseDoubleClick: {
1124 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1125 d->mouseDoubleClickEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1128 case QEvent::GraphicsSceneContextMenu: {
1129 QGraphicsSceneContextMenuEvent *ev =
static_cast<QGraphicsSceneContextMenuEvent *>(e);
1130 d->contextMenuEvent(ev->screenPos(), transform.map(ev->pos()), contextWidget);
1133 case QEvent::GraphicsSceneHoverMove: {
1134 QGraphicsSceneHoverEvent *ev =
static_cast<QGraphicsSceneHoverEvent *>(e);
1135 d->mouseMoveEvent(ev, Qt::NoButton, transform.map(ev->pos()), ev->modifiers(),Qt::NoButton,
1139 case QEvent::GraphicsSceneDragEnter: {
1140 QGraphicsSceneDragDropEvent *ev =
static_cast<QGraphicsSceneDragDropEvent *>(e);
1141 if (d->dragEnterEvent(e, ev->mimeData()))
1142 ev->acceptProposedAction();
1144 case QEvent::GraphicsSceneDragLeave:
1145 d->dragLeaveEvent();
1147 case QEvent::GraphicsSceneDragMove: {
1148 QGraphicsSceneDragDropEvent *ev =
static_cast<QGraphicsSceneDragDropEvent *>(e);
1149 if (d->dragMoveEvent(e, ev->mimeData(), transform.map(ev->pos())))
1150 ev->acceptProposedAction();
1152 case QEvent::GraphicsSceneDrop: {
1153 QGraphicsSceneDragDropEvent *ev =
static_cast<QGraphicsSceneDragDropEvent *>(e);
1154 if (d->dropEvent(ev->mimeData(), transform.map(ev->pos()), ev->dropAction(), ev->source()))
1158#ifdef QT_KEYPAD_NAVIGATION
1159 case QEvent::EnterEditFocus:
1160 case QEvent::LeaveEditFocus:
1161 if (QApplicationPrivate::keypadNavigationEnabled())
1162 d->editFocusEvent(e);
1165 case QEvent::ShortcutOverride:
1166 if (d->interactionFlags & Qt::TextEditable) {
1167 QKeyEvent* ke =
static_cast<QKeyEvent *>(e);
1168 if (isCommonTextEditShortcut(ke))
1220 Q_Q(QWidgetTextControl);
1221#ifndef QT_NO_SHORTCUT
1222 if (e == QKeySequence::SelectAll) {
1225#ifndef QT_NO_CLIPBOARD
1226 setClipboardSelection();
1230#ifndef QT_NO_CLIPBOARD
1231 else if (e == QKeySequence::Copy) {
1239 if (interactionFlags & Qt::TextSelectableByKeyboard
1240 && cursorMoveKeyEvent(e))
1243 if (interactionFlags & Qt::LinksAccessibleByKeyboard) {
1244 if ((e->key() == Qt::Key_Return
1245 || e->key() == Qt::Key_Enter
1246#ifdef QT_KEYPAD_NAVIGATION
1247 || e->key() == Qt::Key_Select
1250 && cursor.hasSelection()) {
1253 activateLinkUnderCursor();
1258 if (!(interactionFlags & Qt::TextEditable)) {
1263 if (e->key() == Qt::Key_Direction_L || e->key() == Qt::Key_Direction_R) {
1264 QTextBlockFormat fmt;
1265 fmt.setLayoutDirection((e->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
1266 cursor.mergeBlockFormat(fmt);
1276 if (e->key() == Qt::Key_Backspace && !(e->modifiers() & ~(Qt::ShiftModifier | Qt::GroupSwitchModifier))) {
1277 QTextBlockFormat blockFmt = cursor.blockFormat();
1278 QTextList *list = cursor.currentList();
1279 if (list && cursor.atBlockStart() && !cursor.hasSelection()) {
1280 list->remove(cursor.block());
1281 }
else if (cursor.atBlockStart() && blockFmt.indent() > 0) {
1282 blockFmt.setIndent(blockFmt.indent() - 1);
1283 cursor.setBlockFormat(blockFmt);
1285 QTextCursor localCursor = cursor;
1286 localCursor.deletePreviousChar();
1292#ifndef QT_NO_SHORTCUT
1293 else if (e == QKeySequence::InsertParagraphSeparator) {
1294 insertParagraphSeparator();
1297 }
else if (e == QKeySequence::InsertLineSeparator) {
1298 cursor.insertText(QString(QChar::LineSeparator));
1305#ifndef QT_NO_SHORTCUT
1306 else if (e == QKeySequence::Undo) {
1309 else if (e == QKeySequence::Redo) {
1312#ifndef QT_NO_CLIPBOARD
1313 else if (e == QKeySequence::Cut) {
1316 else if (e == QKeySequence::Paste) {
1317 QClipboard::Mode mode = QClipboard::Clipboard;
1318 if (QGuiApplication::clipboard()->supportsSelection()) {
1319 if (e->modifiers() == (Qt::CTRL | Qt::SHIFT) && e->key() == Qt::Key_Insert)
1320 mode = QClipboard::Selection;
1325 else if (e == QKeySequence::Delete) {
1326 QTextCursor localCursor = cursor;
1327 localCursor.deleteChar();
1330 }
else if (e == QKeySequence::Backspace) {
1331 QTextCursor localCursor = cursor;
1332 localCursor.deletePreviousChar();
1335 }
else if (e == QKeySequence::DeleteEndOfWord) {
1336 if (!cursor.hasSelection())
1337 cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor);
1338 cursor.removeSelectedText();
1340 else if (e == QKeySequence::DeleteStartOfWord) {
1341 if (!cursor.hasSelection())
1342 cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor);
1343 cursor.removeSelectedText();
1345 else if (e == QKeySequence::DeleteEndOfLine) {
1346 QTextBlock block = cursor.block();
1347 if (cursor.position() == block.position() + block.length() - 2)
1348 cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
1350 cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
1351 cursor.removeSelectedText();
1361 if (q->isAcceptableInput(e)) {
1365 && !cursor.hasSelection()
1366 && !cursor.atBlockEnd())
1367 cursor.deleteChar();
1369 cursor.insertText(e->text());
1379#ifndef QT_NO_CLIPBOARD
1380 setClipboardSelection();
1386 q->ensureCursorVisible();
1388 updateCurrentCharFormat();
1477QRectF QWidgetTextControl::selectionRect(
const QTextCursor &cursor)
const
1479 Q_D(
const QWidgetTextControl);
1481 QRectF r = d->rectForPosition(cursor.selectionStart());
1483 if (cursor.hasComplexSelection() && cursor.currentTable()) {
1484 QTextTable *table = cursor.currentTable();
1486 r = d->doc->documentLayout()->frameBoundingRect(table);
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
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528 }
else if (cursor.hasSelection()) {
1529 const int position = cursor.selectionStart();
1530 const int anchor = cursor.selectionEnd();
1531 const QTextBlock posBlock = d->doc->findBlock(position);
1532 const QTextBlock anchorBlock = d->doc->findBlock(anchor);
1533 if (posBlock == anchorBlock && posBlock.isValid() && posBlock.layout()->lineCount()) {
1534 const QTextLine posLine = posBlock.layout()->lineForTextPosition(position - posBlock.position());
1535 const QTextLine anchorLine = anchorBlock.layout()->lineForTextPosition(anchor - anchorBlock.position());
1537 const int firstLine = qMin(posLine.lineNumber(), anchorLine.lineNumber());
1538 const int lastLine = qMax(posLine.lineNumber(), anchorLine.lineNumber());
1539 const QTextLayout *layout = posBlock.layout();
1541 for (
int i = firstLine; i <= lastLine; ++i) {
1542 r |= layout->lineAt(i).rect();
1543 r |= layout->lineAt(i).naturalTextRect();
1545 r.translate(blockBoundingRect(posBlock).topLeft());
1547 QRectF anchorRect = d->rectForPosition(cursor.selectionEnd());
1549 r |= boundingRectOfFloatsInSelection(cursor);
1550 QRectF frameRect(d->doc->documentLayout()->frameBoundingRect(cursor.currentFrame()));
1551 r.setLeft(frameRect.left());
1552 r.setRight(frameRect.right());
1555 r.adjust(-1, -1, 1, 1);
1568 Qt::MouseButtons buttons,
const QPoint &globalPos)
1570 Q_Q(QWidgetTextControl);
1572 mousePressPos = pos.toPoint();
1574#if QT_CONFIG(draganddrop)
1575 mightStartDrag =
false;
1578 if (sendMouseEventToInputContext(
1579 e, QEvent::MouseButtonPress, button, pos, modifiers, buttons, globalPos)) {
1583 if (interactionFlags & Qt::LinksAccessibleByMouse) {
1584 anchorOnMousePress = q->anchorAt(pos);
1589 cursor.clearSelection();
1592 if (!(button & Qt::LeftButton) ||
1593 !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))) {
1597 bool wasValid = blockWithMarkerUnderMouse.isValid();
1598 blockWithMarkerUnderMouse = q->blockWithMarkerAt(pos);
1599 if (wasValid != blockWithMarkerUnderMouse.isValid())
1600 emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
1604 const QTextCursor oldSelection = cursor;
1605 const int oldCursorPos = cursor.position();
1607 mousePressed = (interactionFlags & Qt::TextSelectableByMouse);
1611 if (trippleClickTimer.isActive()
1612 && ((pos - trippleClickPoint).toPoint().manhattanLength() < QApplication::startDragDistance())) {
1614 cursor.movePosition(QTextCursor::StartOfBlock);
1615 cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
1616 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
1617 selectedBlockOnTrippleClick = cursor;
1619 anchorOnMousePress = QString();
1620 blockWithMarkerUnderMouse = QTextBlock();
1621 emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
1623 trippleClickTimer.stop();
1625 int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
1626 if (cursorPos == -1) {
1631 if (modifiers == Qt::ShiftModifier && (interactionFlags & Qt::TextSelectableByMouse)) {
1632 if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) {
1633 selectedWordOnDoubleClick = cursor;
1634 selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor);
1637 if (selectedBlockOnTrippleClick.hasSelection())
1639 else if (selectedWordOnDoubleClick.hasSelection())
1640 extendWordwiseSelection(cursorPos, pos.x());
1641 else if (!wordSelectionEnabled)
1642 setCursorPosition(cursorPos, QTextCursor::KeepAnchor);
1646 && cursor.hasSelection()
1647 && !cursorIsFocusIndicator
1648 && cursorPos >= cursor.selectionStart()
1649 && cursorPos <= cursor.selectionEnd()
1650 && q->hitTest(pos, Qt::ExactHit) != -1) {
1651#if QT_CONFIG(draganddrop)
1652 mightStartDrag =
true;
1657 setCursorPosition(cursorPos);
1661 if (interactionFlags & Qt::TextEditable) {
1662 q->ensureCursorVisible();
1663 if (cursor.position() != oldCursorPos)
1664 emit q->cursorPositionChanged();
1667 if (cursor.position() != oldCursorPos) {
1668 emit q->cursorPositionChanged();
1669 emit q->microFocusChanged();
1673 repaintOldAndNewSelection(oldSelection);
1674 hadSelectionOnMousePress = cursor.hasSelection();
1678 Qt::MouseButtons buttons,
const QPoint &globalPos)
1680 Q_Q(QWidgetTextControl);
1682 if (interactionFlags & Qt::LinksAccessibleByMouse) {
1683 QString anchor = q->anchorAt(mousePos);
1684 if (anchor != highlightedAnchor) {
1685 highlightedAnchor = anchor;
1686 emit q->linkHovered(anchor);
1690 if (buttons & Qt::LeftButton) {
1691 const bool editable = interactionFlags & Qt::TextEditable;
1696 || selectedWordOnDoubleClick.hasSelection()
1697 || selectedBlockOnTrippleClick.hasSelection()))
1700 const QTextCursor oldSelection = cursor;
1701 const int oldCursorPos = cursor.position();
1704 if ((mousePos.toPoint() - mousePressPos).manhattanLength() > QApplication::startDragDistance())
1709 const qreal mouseX = qreal(mousePos.x());
1711 int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1715 int selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1717 if (newCursorPos != selectionStartPos) {
1720 newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1721 selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1722 setCursorPosition(selectionStartPos);
1726 if (newCursorPos == -1)
1729 if (mousePressed && wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) {
1730 selectedWordOnDoubleClick = cursor;
1731 selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor);
1734 if (selectedBlockOnTrippleClick.hasSelection())
1736 else if (selectedWordOnDoubleClick.hasSelection())
1737 extendWordwiseSelection(newCursorPos, mouseX);
1738 else if (mousePressed && !isPreediting())
1739 setCursorPosition(newCursorPos, QTextCursor::KeepAnchor);
1741 if (interactionFlags & Qt::TextEditable) {
1745 if (cursor.position() != oldCursorPos)
1746 emit q->cursorPositionChanged();
1750 QGuiApplication::inputMethod()->update(Qt::ImQueryInput);
1754 if (cursor.position() != oldCursorPos) {
1755 emit q->cursorPositionChanged();
1756 emit q->microFocusChanged();
1760 repaintOldAndNewSelection(oldSelection);
1762 bool wasValid = blockWithMarkerUnderMouse.isValid();
1763 blockWithMarkerUnderMouse = q->blockWithMarkerAt(mousePos);
1764 if (wasValid != blockWithMarkerUnderMouse.isValid())
1765 emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
1768 sendMouseEventToInputContext(e, QEvent::MouseMove, button, mousePos, modifiers, buttons, globalPos);
1772 Qt::MouseButtons buttons,
const QPoint &globalPos)
1774 Q_Q(QWidgetTextControl);
1776 const QTextCursor oldSelection = cursor;
1777 if (sendMouseEventToInputContext(
1778 e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) {
1779 repaintOldAndNewSelection(oldSelection);
1783 const int oldCursorPos = cursor.position();
1785#if QT_CONFIG(draganddrop)
1786 if (mightStartDrag && (button & Qt::LeftButton)) {
1787 mousePressed =
false;
1788 setCursorPosition(pos);
1789 cursor.clearSelection();
1795#ifndef QT_NO_CLIPBOARD
1798 }
else if (button == Qt::MiddleButton
1799 && (interactionFlags & Qt::TextEditable)
1800 && QGuiApplication::clipboard()->supportsSelection()) {
1801 setCursorPosition(pos);
1802 const QMimeData *md = QGuiApplication::clipboard()->mimeData(QClipboard::Selection);
1804 q->insertFromMimeData(md);
1808 repaintOldAndNewSelection(oldSelection);
1810 if (cursor.position() != oldCursorPos) {
1811 emit q->cursorPositionChanged();
1812 emit q->microFocusChanged();
1816 if ((interactionFlags & Qt::TextEditable) && (button & Qt::LeftButton) &&
1817 (blockWithMarkerUnderMouse.isValid()) && !cursor.hasSelection()) {
1818 QTextBlock markerBlock = q->blockWithMarkerAt(pos);
1819 if (markerBlock == blockWithMarkerUnderMouse) {
1820 auto fmt = blockWithMarkerUnderMouse.blockFormat();
1821 switch (fmt.marker()) {
1822 case QTextBlockFormat::MarkerType::Unchecked :
1823 fmt.setMarker(QTextBlockFormat::MarkerType::Checked);
1825 case QTextBlockFormat::MarkerType::Checked:
1826 fmt.setMarker(QTextBlockFormat::MarkerType::Unchecked);
1831 cursor.setBlockFormat(fmt);
1835 if (interactionFlags & Qt::LinksAccessibleByMouse) {
1838 if (!(button & Qt::LeftButton)) {
1843 const QString anchor = q->anchorAt(pos);
1846 if (anchor.isEmpty()) {
1851 if (!cursor.hasSelection()
1852 || (anchor == anchorOnMousePress && hadSelectionOnMousePress)) {
1854 const int anchorPos = q->hitTest(pos, Qt::ExactHit);
1857 if (anchorPos < 0) {
1862 cursor.setPosition(anchorPos);
1863 QString anchor = anchorOnMousePress;
1864 anchorOnMousePress = QString();
1865 activateLinkUnderCursor(anchor);
2041 Q_Q(QWidgetTextControl);
2042 if (!(interactionFlags & (Qt::TextEditable | Qt::TextSelectableByMouse)) || cursor.isNull()) {
2046 bool isGettingInput = !e->commitString().isEmpty()
2047 || e->preeditString() != cursor.block().layout()->preeditAreaText()
2048 || e->replacementLength() > 0;
2050 if (!isGettingInput && e->attributes().isEmpty()) {
2055 int oldCursorPos = cursor.position();
2057 cursor.beginEditBlock();
2058 if (isGettingInput) {
2059 cursor.removeSelectedText();
2065 if (!e->commitString().isEmpty() || e->replacementLength()) {
2066 auto *mimeData = QInputControl::mimeDataForInputEvent(e);
2067 if (mimeData && q->canInsertFromMimeData(mimeData)) {
2068 q->insertFromMimeData(mimeData);
2070 if (e->commitString().endsWith(QChar::LineFeed))
2071 block = cursor.block();
2072 QTextCursor c = cursor;
2073 c.setPosition(c.position() + e->replacementStart());
2074 c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor);
2075 c.insertText(e->commitString());
2079 for (
int i = 0; i < e->attributes().size(); ++i) {
2080 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
2081 if (a.type == QInputMethodEvent::Selection) {
2082 QTextCursor oldCursor = cursor;
2083 int blockStart = a.start + cursor.block().position();
2084 cursor.setPosition(blockStart, QTextCursor::MoveAnchor);
2085 cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
2086 q->ensureCursorVisible();
2087 repaintOldAndNewSelection(oldCursor);
2091 if (!block.isValid())
2092 block = cursor.block();
2093 QTextLayout *layout = block.layout();
2095 layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
2096 QList<QTextLayout::FormatRange> overrides;
2097 overrides.reserve(e->attributes().size());
2098 const int oldPreeditCursor = preeditCursor;
2099 preeditCursor = e->preeditString().size();
2101 for (
int i = 0; i < e->attributes().size(); ++i) {
2102 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
2103 if (a.type == QInputMethodEvent::Cursor) {
2104 preeditCursor = a.start;
2105 hideCursor = !a.length;
2106 }
else if (a.type == QInputMethodEvent::TextFormat) {
2107 QTextCharFormat f = cursor.charFormat();
2108 f.merge(qvariant_cast<QTextFormat>(a.value).toCharFormat());
2110 QTextLayout::FormatRange o;
2111 o.start = a.start + cursor.position() - block.position();
2112 o.length = a.length;
2116 QList<QTextLayout::FormatRange>::iterator it = overrides.end();
2117 while (it != overrides.begin()) {
2118 QList<QTextLayout::FormatRange>::iterator previous = it - 1;
2119 if (o.start >= previous->start) {
2120 overrides.insert(it, o);
2126 if (it == overrides.begin())
2127 overrides.prepend(o);
2132 if (cursor.charFormat().isValid()) {
2133 int start = cursor.position() - block.position();
2134 int end = start + e->preeditString().size();
2136 QList<QTextLayout::FormatRange>::iterator it = overrides.begin();
2137 while (it != overrides.end()) {
2138 QTextLayout::FormatRange range = *it;
2139 int rangeStart = range.start;
2140 if (rangeStart > start) {
2141 QTextLayout::FormatRange o;
2143 o.length = rangeStart - start;
2144 o.format = cursor.charFormat();
2145 it = overrides.insert(it, o) + 1;
2149 start = range.start + range.length;
2153 QTextLayout::FormatRange o;
2155 o.length = end - start;
2156 o.format = cursor.charFormat();
2157 overrides.append(o);
2160 layout->setFormats(overrides);
2162 cursor.endEditBlock();
2166 if (oldCursorPos != cursor.position())
2167 emit q->cursorPositionChanged();
2168 if (oldPreeditCursor != preeditCursor)
2169 emit q->microFocusChanged();
2172QVariant QWidgetTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument)
const
2174 Q_D(
const QWidgetTextControl);
2175 QTextBlock block = d->cursor.block();
2177 case Qt::ImCursorRectangle:
2178 return cursorRect();
2179 case Qt::ImAnchorRectangle:
2180 return d->rectForPosition(d->cursor.anchor());
2182 return QVariant(d->cursor.charFormat().font());
2183 case Qt::ImCursorPosition: {
2184 const QPointF pt = argument.toPointF();
2186 return QVariant(cursorForPosition(pt).position() - block.position());
2187 return QVariant(d->cursor.position() - block.position()); }
2188 case Qt::ImSurroundingText:
2189 return QVariant(block.text());
2190 case Qt::ImCurrentSelection: {
2191 QMimeData *mimeData = createMimeDataFromSelection();
2192 mimeData->deleteLater();
2193 return QInputControl::selectionWrapper(mimeData);
2195 case Qt::ImMaximumTextLength:
2197 case Qt::ImAnchorPosition:
2198 return QVariant(d->cursor.anchor() - block.position());
2199 case Qt::ImAbsolutePosition: {
2200 const QPointF pt = argument.toPointF();
2202 return QVariant(cursorForPosition(pt).position());
2203 return QVariant(d->cursor.position()); }
2204 case Qt::ImTextAfterCursor:
2206 int maxLength = argument.isValid() ? argument.toInt() : 1024;
2207 QTextCursor tmpCursor = d->cursor;
2208 int localPos = d->cursor.position() - block.position();
2209 QString result = block.text().mid(localPos);
2210 while (result.size() < maxLength) {
2211 int currentBlock = tmpCursor.blockNumber();
2212 tmpCursor.movePosition(QTextCursor::NextBlock);
2213 if (tmpCursor.blockNumber() == currentBlock)
2215 result += u'\n' + tmpCursor.block().text();
2217 return QVariant(result);
2219 case Qt::ImTextBeforeCursor:
2221 int maxLength = argument.isValid() ? argument.toInt() : 1024;
2222 QTextCursor tmpCursor = d->cursor;
2223 int localPos = d->cursor.position() - block.position();
2225 int resultLen = localPos;
2226 while (resultLen < maxLength) {
2227 int currentBlock = tmpCursor.blockNumber();
2228 tmpCursor.movePosition(QTextCursor::PreviousBlock);
2229 if (tmpCursor.blockNumber() == currentBlock)
2232 resultLen += tmpCursor.block().length();
2236 result += tmpCursor.block().text() + u'\n';
2237 tmpCursor.movePosition(QTextCursor::NextBlock);
2240 result += QStringView{block.text()}.mid(0, localPos);
2241 return QVariant(result);
2334QMenu *QWidgetTextControl::createStandardContextMenu(
const QPointF &pos, QWidget *parent)
2336 Q_D(QWidgetTextControl);
2338 const bool showTextSelectionActions = d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
2340 d->linkToCopy = QString();
2342 d->linkToCopy = anchorAt(pos);
2344 if (d->linkToCopy.isEmpty() && !showTextSelectionActions)
2347 QMenu *menu =
new QMenu(parent);
2350 if (d->interactionFlags & Qt::TextEditable) {
2351 a = menu->addAction(tr(
"&Undo") +
ACCEL_KEY(QKeySequence::Undo),
this, SLOT(undo()));
2352 a->setEnabled(d->doc->isUndoAvailable());
2353 a->setObjectName(QStringLiteral(
"edit-undo"));
2354 setActionIcon(a, QStringLiteral(
"edit-undo"));
2355 a = menu->addAction(tr(
"&Redo") +
ACCEL_KEY(QKeySequence::Redo),
this, SLOT(redo()));
2356 a->setEnabled(d->doc->isRedoAvailable());
2357 a->setObjectName(QStringLiteral(
"edit-redo"));
2358 setActionIcon(a, QStringLiteral(
"edit-redo"));
2359 menu->addSeparator();
2361#ifndef QT_NO_CLIPBOARD
2362 a = menu->addAction(tr(
"Cu&t") +
ACCEL_KEY(QKeySequence::Cut),
this, SLOT(cut()));
2363 a->setEnabled(d->cursor.hasSelection());
2364 a->setObjectName(QStringLiteral(
"edit-cut"));
2365 setActionIcon(a, QStringLiteral(
"edit-cut"));
2369#ifndef QT_NO_CLIPBOARD
2370 if (showTextSelectionActions) {
2371 a = menu->addAction(tr(
"&Copy") +
ACCEL_KEY(QKeySequence::Copy),
this, SLOT(copy()));
2372 a->setEnabled(d->cursor.hasSelection());
2373 a->setObjectName(QStringLiteral(
"edit-copy"));
2374 setActionIcon(a, QStringLiteral(
"edit-copy"));
2377 if ((d->interactionFlags & Qt::LinksAccessibleByKeyboard)
2378 || (d->interactionFlags & Qt::LinksAccessibleByMouse)) {
2380 a = menu->addAction(tr(
"Copy &Link Location"),
this, SLOT(_q_copyLink()));
2381 a->setEnabled(!d->linkToCopy.isEmpty());
2382 a->setObjectName(QStringLiteral(
"link-copy"));
2386 if (d->interactionFlags & Qt::TextEditable) {
2387#ifndef QT_NO_CLIPBOARD
2388 a = menu->addAction(tr(
"&Paste") +
ACCEL_KEY(QKeySequence::Paste),
this, SLOT(paste()));
2389 a->setEnabled(canPaste());
2390 a->setObjectName(QStringLiteral(
"edit-paste"));
2391 setActionIcon(a, QStringLiteral(
"edit-paste"));
2393 a = menu->addAction(tr(
"Delete"),
this, SLOT(_q_deleteSelected()));
2394 a->setEnabled(d->cursor.hasSelection());
2395 a->setObjectName(QStringLiteral(
"edit-delete"));
2396 setActionIcon(a, QStringLiteral(
"edit-delete"));
2400 if (showTextSelectionActions) {
2401 menu->addSeparator();
2402 a = menu->addAction(tr(
"Select All") +
ACCEL_KEY(QKeySequence::SelectAll),
this, SLOT(selectAll()));
2403 a->setEnabled(!d->doc->isEmpty());
2404 a->setObjectName(QStringLiteral(
"select-all"));
2405 setActionIcon(a, QStringLiteral(
"edit-select-all"));
2408 if ((d->interactionFlags & Qt::TextEditable) && QGuiApplication::styleHints()->useRtlExtensions()) {
2409 menu->addSeparator();
2410 QUnicodeControlCharacterMenu *ctrlCharacterMenu =
new QUnicodeControlCharacterMenu(
this, menu);
2411 menu->addMenu(ctrlCharacterMenu);
2773bool QWidgetTextControl::findNextPrevAnchor(
const QTextCursor &startCursor,
bool next, QTextCursor &newAnchor)
2775 Q_D(QWidgetTextControl);
2777 int anchorStart = -1;
2782 const int startPos = startCursor.selectionEnd();
2784 QTextBlock block = d->doc->findBlock(startPos);
2785 QTextBlock::Iterator it = block.begin();
2787 while (!it.atEnd() && it.fragment().position() < startPos)
2790 while (block.isValid()) {
2794 for (; !it.atEnd(); ++it) {
2795 const QTextFragment fragment = it.fragment();
2796 const QTextCharFormat fmt = fragment.charFormat();
2798 if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) {
2799 anchorStart = fragment.position();
2800 anchorHref = fmt.anchorHref();
2805 if (anchorStart != -1) {
2809 for (; !it.atEnd(); ++it) {
2810 const QTextFragment fragment = it.fragment();
2811 const QTextCharFormat fmt = fragment.charFormat();
2813 if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) {
2814 anchorEnd = fragment.position();
2819 if (anchorEnd == -1)
2820 anchorEnd = block.position() + block.length() - 1;
2826 block = block.next();
2830 int startPos = startCursor.selectionStart();
2834 QTextBlock block = d->doc->findBlock(startPos);
2835 QTextBlock::Iterator blockStart = block.begin();
2836 QTextBlock::Iterator it = block.end();
2838 if (startPos == block.position()) {
2842 if (it == blockStart) {
2843 it = QTextBlock::Iterator();
2844 block = QTextBlock();
2848 }
while (!it.atEnd() && it.fragment().position() + it.fragment().length() - 1 > startPos);
2851 while (block.isValid()) {
2856 const QTextFragment fragment = it.fragment();
2857 const QTextCharFormat fmt = fragment.charFormat();
2859 if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) {
2860 anchorStart = fragment.position() + fragment.length();
2861 anchorHref = fmt.anchorHref();
2865 if (it == blockStart)
2866 it = QTextBlock::Iterator();
2869 }
while (!it.atEnd());
2872 if (anchorStart != -1 && !it.atEnd()) {
2876 const QTextFragment fragment = it.fragment();
2877 const QTextCharFormat fmt = fragment.charFormat();
2879 if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) {
2880 anchorEnd = fragment.position() + fragment.length();
2884 if (it == blockStart)
2885 it = QTextBlock::Iterator();
2888 }
while (!it.atEnd());
2890 if (anchorEnd == -1)
2891 anchorEnd = qMax(0, block.position());
2896 block = block.previous();
2898 if (it != block.begin())
2900 blockStart = block.begin();
2905 if (anchorStart != -1 && anchorEnd != -1) {
2906 newAnchor = d->cursor;
2907 newAnchor.setPosition(anchorStart);
2908 newAnchor.setPosition(anchorEnd, QTextCursor::KeepAnchor);
2917 QTextCursor oldCursor = cursor;
2919 if (href.isEmpty()) {
2920 QTextCursor tmp = cursor;
2921 if (tmp.selectionStart() != tmp.position())
2922 tmp.setPosition(tmp.selectionStart());
2923 tmp.movePosition(QTextCursor::NextCharacter);
2924 href = tmp.charFormat().anchorHref();
2929 if (!cursor.hasSelection()) {
2930 QTextBlock block = cursor.block();
2931 const int cursorPos = cursor.position();
2933 QTextBlock::Iterator it = block.begin();
2934 QTextBlock::Iterator linkFragment;
2936 for (; !it.atEnd(); ++it) {
2937 QTextFragment fragment = it.fragment();
2938 const int fragmentPos = fragment.position();
2939 if (fragmentPos <= cursorPos &&
2940 fragmentPos + fragment.length() > cursorPos) {
2946 if (!linkFragment.atEnd()) {
2948 cursor.setPosition(it.fragment().position());
2949 if (it != block.begin()) {
2952 QTextFragment fragment = it.fragment();
2953 if (fragment.charFormat().anchorHref() != href)
2955 cursor.setPosition(fragment.position());
2956 }
while (it != block.begin());
2959 for (it = linkFragment; !it.atEnd(); ++it) {
2960 QTextFragment fragment = it.fragment();
2961 if (fragment.charFormat().anchorHref() != href)
2963 cursor.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor);
2972 cursor.clearSelection();
2974 repaintOldAndNewSelection(oldCursor);
2976#ifndef QT_NO_DESKTOPSERVICES
2978 QDesktopServices::openUrl(href);
2981 emit q_func()->linkActivated(href);
3221 auto blockFmt = cursor.blockFormat();
3222 auto charFmt = cursor.charFormat();
3223 blockFmt.clearProperty(QTextFormat::BlockTrailingHorizontalRulerWidth);
3224 if (blockFmt.hasProperty(QTextFormat::HeadingLevel)) {
3225 blockFmt.clearProperty(QTextFormat::HeadingLevel);
3226 charFmt = QTextCharFormat();
3228 if (cursor.currentList()) {
3229 auto existingFmt = cursor.blockFormat();
3230 existingFmt.clearProperty(QTextBlockFormat::BlockBottomMargin);
3231 cursor.setBlockFormat(existingFmt);
3232 if (blockFmt.marker() == QTextBlockFormat::MarkerType::Checked)
3233 blockFmt.setMarker(QTextBlockFormat::MarkerType::Unchecked);
3238 if (cursor.block().text().isEmpty() &&
3239 !cursor.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth) &&
3240 !cursor.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
3241 blockFmt = QTextBlockFormat();
3242 const bool blockFmtChanged = (cursor.blockFormat() != blockFmt);
3243 charFmt = QTextCharFormat();
3244 cursor.setBlockFormat(blockFmt);
3245 cursor.setCharFormat(charFmt);
3250 if (blockFmtChanged)
3254 cursor.insertBlock(blockFmt, charFmt);
3326QAbstractTextDocumentLayout::PaintContext QWidgetTextControl::getPaintContext(QWidget *widget)
const
3328 Q_D(
const QWidgetTextControl);
3330 QAbstractTextDocumentLayout::PaintContext ctx;
3332 ctx.selections = d->extraSelections;
3333 ctx.palette = d->palette;
3334#if QT_CONFIG(style_stylesheet)
3336 if (
auto cssStyle = qt_styleSheet(widget->style())) {
3337 QStyleOption option;
3338 option.initFrom(widget);
3339 cssStyle->styleSheetPalette(widget, &option, &ctx.palette);
3343 if (d->cursorOn && d->isEnabled) {
3345 ctx.cursorPosition = -1;
3346 else if (d->preeditCursor != 0)
3347 ctx.cursorPosition = - (d->preeditCursor + 2);
3349 ctx.cursorPosition = d->cursor.position();
3352 if (!d->dndFeedbackCursor.isNull())
3353 ctx.cursorPosition = d->dndFeedbackCursor.position();
3354#ifdef QT_KEYPAD_NAVIGATION
3355 if (!QApplicationPrivate::keypadNavigationEnabled() || d->hasEditFocus)
3357 if (d->cursor.hasSelection()) {
3358 QAbstractTextDocumentLayout::Selection selection;
3359 selection.cursor = d->cursor;
3360 if (d->cursorIsFocusIndicator) {
3362 opt.palette = ctx.palette;
3363 QStyleHintReturnVariant ret;
3364 QStyle *style = QApplication::style();
3366 style = widget->style();
3367 style->styleHint(QStyle::SH_TextControl_FocusIndicatorTextCharFormat, &opt, widget, &ret);
3368 selection.format = qvariant_cast<QTextFormat>(ret.variant).toCharFormat();
3370 QPalette::ColorGroup cg = d->hasFocus ? QPalette::Active : QPalette::Inactive;
3371 selection.format.setBackground(ctx.palette.brush(cg, QPalette::Highlight));
3372 selection.format.setForeground(ctx.palette.brush(cg, QPalette::HighlightedText));
3374 QStyle *style = QApplication::style();
3376 opt.initFrom(widget);
3377 style = widget->style();
3379 if (style->styleHint(QStyle::SH_RichText_FullWidthSelection, &opt, widget))
3380 selection.format.setProperty(QTextFormat::FullWidthSelection,
true);
3382 ctx.selections.append(selection);