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()), ev->modifiers(),
1040 ev->buttons(), ev->globalPosition());
1042 case QEvent::MouseMove: {
1043 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1044 d->mouseMoveEvent(ev, ev->button(), transform.map(ev->position()), ev->modifiers(),
1045 ev->buttons(), ev->globalPosition());
1047 case QEvent::MouseButtonRelease: {
1048 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1049 d->mouseReleaseEvent(ev, ev->button(), transform.map(ev->position()), ev->modifiers(),
1050 ev->buttons(), ev->globalPosition());
1052 case QEvent::MouseButtonDblClick: {
1053 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1054 d->mouseDoubleClickEvent(ev, ev->button(), transform.map(ev->position()), ev->modifiers(),
1055 ev->buttons(), ev->globalPosition());
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())))
1096 ev->acceptProposedAction();
1099 case QEvent::Drop: {
1100 QDropEvent *ev =
static_cast<QDropEvent *>(e);
1101 if (d->dropEvent(ev->mimeData(), transform.map(ev->position()), 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 QPointF &globalPos)
1570 Q_Q(QWidgetTextControl);
1572 mousePressPos = pos;
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).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 QPointF &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 - 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 QPointF &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 activateLinkUnderCursor(std::exchange(anchorOnMousePress, QString()));
2039 Q_Q(QWidgetTextControl);
2040 if (!(interactionFlags & (Qt::TextEditable | Qt::TextSelectableByMouse)) || cursor.isNull()) {
2044 bool isGettingInput = !e->commitString().isEmpty()
2045 || e->preeditString() != cursor.block().layout()->preeditAreaText()
2046 || e->replacementLength() > 0;
2048 if (!isGettingInput && e->attributes().isEmpty()) {
2053 int oldCursorPos = cursor.position();
2055 cursor.beginEditBlock();
2056 if (isGettingInput) {
2057 cursor.removeSelectedText();
2063 if (!e->commitString().isEmpty() || e->replacementLength()) {
2064 auto *mimeData = QInputControl::mimeDataForInputEvent(e);
2065 if (mimeData && q->canInsertFromMimeData(mimeData)) {
2066 q->insertFromMimeData(mimeData);
2068 if (e->commitString().endsWith(QChar::LineFeed))
2069 block = cursor.block();
2070 QTextCursor c = cursor;
2071 c.setPosition(c.position() + e->replacementStart());
2072 c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor);
2073 c.insertText(e->commitString());
2077 for (
int i = 0; i < e->attributes().size(); ++i) {
2078 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
2079 if (a.type == QInputMethodEvent::Selection) {
2080 QTextCursor oldCursor = cursor;
2081 int blockStart = a.start + cursor.block().position();
2082 cursor.setPosition(blockStart, QTextCursor::MoveAnchor);
2083 cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
2084 q->ensureCursorVisible();
2085 repaintOldAndNewSelection(oldCursor);
2089 if (!block.isValid())
2090 block = cursor.block();
2091 QTextLayout *layout = block.layout();
2093 layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
2094 QList<QTextLayout::FormatRange> overrides;
2095 overrides.reserve(e->attributes().size());
2096 const int oldPreeditCursor = preeditCursor;
2097 preeditCursor = e->preeditString().size();
2099 for (
int i = 0; i < e->attributes().size(); ++i) {
2100 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
2101 if (a.type == QInputMethodEvent::Cursor) {
2102 preeditCursor = a.start;
2103 hideCursor = !a.length;
2104 }
else if (a.type == QInputMethodEvent::TextFormat) {
2105 QTextCharFormat f = cursor.charFormat();
2106 f.merge(qvariant_cast<QTextFormat>(a.value).toCharFormat());
2108 QTextLayout::FormatRange o;
2109 o.start = a.start + cursor.position() - block.position();
2110 o.length = a.length;
2114 QList<QTextLayout::FormatRange>::iterator it = overrides.end();
2115 while (it != overrides.begin()) {
2116 QList<QTextLayout::FormatRange>::iterator previous = it - 1;
2117 if (o.start >= previous->start) {
2118 overrides.insert(it, o);
2124 if (it == overrides.begin())
2125 overrides.prepend(o);
2130 if (cursor.charFormat().isValid()) {
2131 int start = cursor.position() - block.position();
2132 int end = start + e->preeditString().size();
2134 QList<QTextLayout::FormatRange>::iterator it = overrides.begin();
2135 while (it != overrides.end()) {
2136 QTextLayout::FormatRange range = *it;
2137 int rangeStart = range.start;
2138 if (rangeStart > start) {
2139 QTextLayout::FormatRange o;
2141 o.length = rangeStart - start;
2142 o.format = cursor.charFormat();
2143 it = overrides.insert(it, o) + 1;
2147 start = range.start + range.length;
2151 QTextLayout::FormatRange o;
2153 o.length = end - start;
2154 o.format = cursor.charFormat();
2155 overrides.append(o);
2158 layout->setFormats(overrides);
2160 cursor.endEditBlock();
2164 if (oldCursorPos != cursor.position())
2165 emit q->cursorPositionChanged();
2166 if (oldPreeditCursor != preeditCursor)
2167 emit q->microFocusChanged();
2170QVariant QWidgetTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument)
const
2172 Q_D(
const QWidgetTextControl);
2173 QTextBlock block = d->cursor.block();
2175 case Qt::ImCursorRectangle:
2176 return cursorRect();
2177 case Qt::ImAnchorRectangle:
2178 return d->rectForPosition(d->cursor.anchor());
2180 return QVariant(d->cursor.charFormat().font());
2181 case Qt::ImCursorPosition: {
2182 const QPointF pt = argument.toPointF();
2184 return QVariant(cursorForPosition(pt).position() - block.position());
2185 return QVariant(d->cursor.position() - block.position()); }
2186 case Qt::ImSurroundingText:
2187 return QVariant(block.text());
2188 case Qt::ImCurrentSelection: {
2189 QMimeData *mimeData = createMimeDataFromSelection();
2190 mimeData->deleteLater();
2191 return QInputControl::selectionWrapper(mimeData);
2193 case Qt::ImMaximumTextLength:
2195 case Qt::ImAnchorPosition:
2196 return QVariant(d->cursor.anchor() - block.position());
2197 case Qt::ImAbsolutePosition: {
2198 const QPointF pt = argument.toPointF();
2200 return QVariant(cursorForPosition(pt).position());
2201 return QVariant(d->cursor.position()); }
2202 case Qt::ImTextAfterCursor:
2204 int maxLength = argument.isValid() ? argument.toInt() : 1024;
2205 QTextCursor tmpCursor = d->cursor;
2206 int localPos = d->cursor.position() - block.position();
2207 QString result = block.text().mid(localPos);
2208 while (result.size() < maxLength) {
2209 int currentBlock = tmpCursor.blockNumber();
2210 tmpCursor.movePosition(QTextCursor::NextBlock);
2211 if (tmpCursor.blockNumber() == currentBlock)
2213 result += u'\n' + tmpCursor.block().text();
2215 return QVariant(result);
2217 case Qt::ImTextBeforeCursor:
2219 int maxLength = argument.isValid() ? argument.toInt() : 1024;
2220 QTextCursor tmpCursor = d->cursor;
2221 int localPos = d->cursor.position() - block.position();
2223 int resultLen = localPos;
2224 while (resultLen < maxLength) {
2225 int currentBlock = tmpCursor.blockNumber();
2226 tmpCursor.movePosition(QTextCursor::PreviousBlock);
2227 if (tmpCursor.blockNumber() == currentBlock)
2230 resultLen += tmpCursor.block().length();
2234 result += tmpCursor.block().text() + u'\n';
2235 tmpCursor.movePosition(QTextCursor::NextBlock);
2238 result += QStringView{block.text()}.mid(0, localPos);
2239 return QVariant(result);
2332QMenu *QWidgetTextControl::createStandardContextMenu(
const QPointF &pos, QWidget *parent)
2334 Q_D(QWidgetTextControl);
2336 const bool showTextSelectionActions = d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
2338 d->linkToCopy = QString();
2340 d->linkToCopy = anchorAt(pos);
2342 if (d->linkToCopy.isEmpty() && !showTextSelectionActions)
2345 QMenu *menu =
new QMenu(parent);
2348 if (d->interactionFlags & Qt::TextEditable) {
2349 a = menu->addAction(tr(
"&Undo") +
ACCEL_KEY(QKeySequence::Undo),
this, SLOT(undo()));
2350 a->setEnabled(d->doc->isUndoAvailable());
2351 a->setObjectName(QStringLiteral(
"edit-undo"));
2352 setActionIcon(a, QStringLiteral(
"edit-undo"));
2353 a = menu->addAction(tr(
"&Redo") +
ACCEL_KEY(QKeySequence::Redo),
this, SLOT(redo()));
2354 a->setEnabled(d->doc->isRedoAvailable());
2355 a->setObjectName(QStringLiteral(
"edit-redo"));
2356 setActionIcon(a, QStringLiteral(
"edit-redo"));
2357 menu->addSeparator();
2359#ifndef QT_NO_CLIPBOARD
2360 a = menu->addAction(tr(
"Cu&t") +
ACCEL_KEY(QKeySequence::Cut),
this, SLOT(cut()));
2361 a->setEnabled(d->cursor.hasSelection());
2362 a->setObjectName(QStringLiteral(
"edit-cut"));
2363 setActionIcon(a, QStringLiteral(
"edit-cut"));
2367#ifndef QT_NO_CLIPBOARD
2368 if (showTextSelectionActions) {
2369 a = menu->addAction(tr(
"&Copy") +
ACCEL_KEY(QKeySequence::Copy),
this, SLOT(copy()));
2370 a->setEnabled(d->cursor.hasSelection());
2371 a->setObjectName(QStringLiteral(
"edit-copy"));
2372 setActionIcon(a, QStringLiteral(
"edit-copy"));
2375 if ((d->interactionFlags & Qt::LinksAccessibleByKeyboard)
2376 || (d->interactionFlags & Qt::LinksAccessibleByMouse)) {
2378 a = menu->addAction(tr(
"Copy &Link Location"),
this, SLOT(_q_copyLink()));
2379 a->setEnabled(!d->linkToCopy.isEmpty());
2380 a->setObjectName(QStringLiteral(
"link-copy"));
2384 if (d->interactionFlags & Qt::TextEditable) {
2385#ifndef QT_NO_CLIPBOARD
2386 a = menu->addAction(tr(
"&Paste") +
ACCEL_KEY(QKeySequence::Paste),
this, SLOT(paste()));
2387 a->setEnabled(canPaste());
2388 a->setObjectName(QStringLiteral(
"edit-paste"));
2389 setActionIcon(a, QStringLiteral(
"edit-paste"));
2391 a = menu->addAction(tr(
"Delete"),
this, SLOT(_q_deleteSelected()));
2392 a->setEnabled(d->cursor.hasSelection());
2393 a->setObjectName(QStringLiteral(
"edit-delete"));
2394 setActionIcon(a, QStringLiteral(
"edit-delete"));
2398 if (showTextSelectionActions) {
2399 menu->addSeparator();
2400 a = menu->addAction(tr(
"Select All") +
ACCEL_KEY(QKeySequence::SelectAll),
this, SLOT(selectAll()));
2401 a->setEnabled(!d->doc->isEmpty());
2402 a->setObjectName(QStringLiteral(
"select-all"));
2403 setActionIcon(a, QStringLiteral(
"edit-select-all"));
2406 if ((d->interactionFlags & Qt::TextEditable) && QGuiApplication::styleHints()->useRtlExtensions()) {
2407 menu->addSeparator();
2408 QUnicodeControlCharacterMenu *ctrlCharacterMenu =
new QUnicodeControlCharacterMenu(
this, menu);
2409 menu->addMenu(ctrlCharacterMenu);
2771bool QWidgetTextControl::findNextPrevAnchor(
const QTextCursor &startCursor,
bool next, QTextCursor &newAnchor)
2773 Q_D(QWidgetTextControl);
2775 int anchorStart = -1;
2780 const int startPos = startCursor.selectionEnd();
2782 QTextBlock block = d->doc->findBlock(startPos);
2783 QTextBlock::Iterator it = block.begin();
2785 while (!it.atEnd() && it.fragment().position() < startPos)
2788 while (block.isValid()) {
2792 for (; !it.atEnd(); ++it) {
2793 const QTextFragment fragment = it.fragment();
2794 const QTextCharFormat fmt = fragment.charFormat();
2796 if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) {
2797 anchorStart = fragment.position();
2798 anchorHref = fmt.anchorHref();
2803 if (anchorStart != -1) {
2807 for (; !it.atEnd(); ++it) {
2808 const QTextFragment fragment = it.fragment();
2809 const QTextCharFormat fmt = fragment.charFormat();
2811 if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) {
2812 anchorEnd = fragment.position();
2817 if (anchorEnd == -1)
2818 anchorEnd = block.position() + block.length() - 1;
2824 block = block.next();
2828 int startPos = startCursor.selectionStart();
2832 QTextBlock block = d->doc->findBlock(startPos);
2833 QTextBlock::Iterator blockStart = block.begin();
2834 QTextBlock::Iterator it = block.end();
2836 if (startPos == block.position()) {
2840 if (it == blockStart) {
2841 it = QTextBlock::Iterator();
2842 block = QTextBlock();
2846 }
while (!it.atEnd() && it.fragment().position() + it.fragment().length() - 1 > startPos);
2849 while (block.isValid()) {
2854 const QTextFragment fragment = it.fragment();
2855 const QTextCharFormat fmt = fragment.charFormat();
2857 if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) {
2858 anchorStart = fragment.position() + fragment.length();
2859 anchorHref = fmt.anchorHref();
2863 if (it == blockStart)
2864 it = QTextBlock::Iterator();
2867 }
while (!it.atEnd());
2870 if (anchorStart != -1 && !it.atEnd()) {
2874 const QTextFragment fragment = it.fragment();
2875 const QTextCharFormat fmt = fragment.charFormat();
2877 if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) {
2878 anchorEnd = fragment.position() + fragment.length();
2882 if (it == blockStart)
2883 it = QTextBlock::Iterator();
2886 }
while (!it.atEnd());
2888 if (anchorEnd == -1)
2889 anchorEnd = qMax(0, block.position());
2894 block = block.previous();
2896 if (it != block.begin())
2898 blockStart = block.begin();
2903 if (anchorStart != -1 && anchorEnd != -1) {
2904 newAnchor = d->cursor;
2905 newAnchor.setPosition(anchorStart);
2906 newAnchor.setPosition(anchorEnd, QTextCursor::KeepAnchor);
2915 QTextCursor oldCursor = cursor;
2917 if (href.isEmpty()) {
2918 QTextCursor tmp = cursor;
2919 if (tmp.selectionStart() != tmp.position())
2920 tmp.setPosition(tmp.selectionStart());
2921 tmp.movePosition(QTextCursor::NextCharacter);
2922 href = tmp.charFormat().anchorHref();
2927 if (!cursor.hasSelection()) {
2928 QTextBlock block = cursor.block();
2929 const int cursorPos = cursor.position();
2931 QTextBlock::Iterator it = block.begin();
2932 QTextBlock::Iterator linkFragment;
2934 for (; !it.atEnd(); ++it) {
2935 QTextFragment fragment = it.fragment();
2936 const int fragmentPos = fragment.position();
2937 if (fragmentPos <= cursorPos &&
2938 fragmentPos + fragment.length() > cursorPos) {
2944 if (!linkFragment.atEnd()) {
2946 cursor.setPosition(it.fragment().position());
2947 if (it != block.begin()) {
2950 QTextFragment fragment = it.fragment();
2951 if (fragment.charFormat().anchorHref() != href)
2953 cursor.setPosition(fragment.position());
2954 }
while (it != block.begin());
2957 for (it = linkFragment; !it.atEnd(); ++it) {
2958 QTextFragment fragment = it.fragment();
2959 if (fragment.charFormat().anchorHref() != href)
2961 cursor.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor);
2970 cursor.clearSelection();
2972 repaintOldAndNewSelection(oldCursor);
2974#ifndef QT_NO_DESKTOPSERVICES
2976 QDesktopServices::openUrl(QUrl{href});
2979 emit q_func()->linkActivated(href);
3219 auto blockFmt = cursor.blockFormat();
3220 auto charFmt = cursor.charFormat();
3221 blockFmt.clearProperty(QTextFormat::BlockTrailingHorizontalRulerWidth);
3222 if (blockFmt.hasProperty(QTextFormat::HeadingLevel)) {
3223 blockFmt.clearProperty(QTextFormat::HeadingLevel);
3224 charFmt = QTextCharFormat();
3226 if (cursor.currentList()) {
3227 auto existingFmt = cursor.blockFormat();
3228 existingFmt.clearProperty(QTextBlockFormat::BlockBottomMargin);
3229 cursor.setBlockFormat(existingFmt);
3230 if (blockFmt.marker() == QTextBlockFormat::MarkerType::Checked)
3231 blockFmt.setMarker(QTextBlockFormat::MarkerType::Unchecked);
3236 if (cursor.block().text().isEmpty() &&
3237 !cursor.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth) &&
3238 !cursor.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
3239 blockFmt = QTextBlockFormat();
3240 const bool blockFmtChanged = (cursor.blockFormat() != blockFmt);
3241 charFmt = QTextCharFormat();
3242 cursor.setBlockFormat(blockFmt);
3243 cursor.setCharFormat(charFmt);
3248 if (blockFmtChanged)
3252 cursor.insertBlock(blockFmt, charFmt);
3324QAbstractTextDocumentLayout::PaintContext QWidgetTextControl::getPaintContext(QWidget *widget)
const
3326 Q_D(
const QWidgetTextControl);
3328 QAbstractTextDocumentLayout::PaintContext ctx;
3330 ctx.selections = d->extraSelections;
3331 ctx.palette = d->palette;
3332#if QT_CONFIG(style_stylesheet)
3334 if (
auto cssStyle = qt_styleSheet(widget->style())) {
3335 QStyleOption option;
3336 option.initFrom(widget);
3337 cssStyle->styleSheetPalette(widget, &option, &ctx.palette);
3341 if (d->cursorOn && d->isEnabled) {
3343 ctx.cursorPosition = -1;
3344 else if (d->preeditCursor != 0)
3345 ctx.cursorPosition = - (d->preeditCursor + 2);
3347 ctx.cursorPosition = d->cursor.position();
3350 if (!d->dndFeedbackCursor.isNull())
3351 ctx.cursorPosition = d->dndFeedbackCursor.position();
3352#ifdef QT_KEYPAD_NAVIGATION
3353 if (!QApplicationPrivate::keypadNavigationEnabled() || d->hasEditFocus)
3355 if (d->cursor.hasSelection()) {
3356 QAbstractTextDocumentLayout::Selection selection;
3357 selection.cursor = d->cursor;
3358 if (d->cursorIsFocusIndicator) {
3360 opt.palette = ctx.palette;
3361 QStyleHintReturnVariant ret;
3362 QStyle *style = QApplication::style();
3364 style = widget->style();
3365 style->styleHint(QStyle::SH_TextControl_FocusIndicatorTextCharFormat, &opt, widget, &ret);
3366 selection.format = qvariant_cast<QTextFormat>(ret.variant).toCharFormat();
3368 QPalette::ColorGroup cg = d->hasFocus ? QPalette::Active : QPalette::Inactive;
3369 selection.format.setBackground(ctx.palette.brush(cg, QPalette::Highlight));
3370 selection.format.setForeground(ctx.palette.brush(cg, QPalette::HighlightedText));
3372 QStyle *style = QApplication::style();
3374 opt.initFrom(widget);
3375 style = widget->style();
3377 if (style->styleHint(QStyle::SH_RichText_FullWidthSelection, &opt, widget))
3378 selection.format.setProperty(QTextFormat::FullWidthSelection,
true);
3380 ctx.selections.append(selection);