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());
1043 d->updateHighlightedAnchor(transform.map(
static_cast<QEnterEvent *>(e)->position()));
1046 d->resetHighlightedAnchor();
1048 case QEvent::MouseMove: {
1049 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1050 d->mouseMoveEvent(ev, ev->button(), transform.map(ev->position()), ev->modifiers(),
1051 ev->buttons(), ev->globalPosition());
1053 case QEvent::MouseButtonRelease: {
1054 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1055 d->mouseReleaseEvent(ev, ev->button(), transform.map(ev->position()), ev->modifiers(),
1056 ev->buttons(), ev->globalPosition());
1058 case QEvent::MouseButtonDblClick: {
1059 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
1060 d->mouseDoubleClickEvent(ev, ev->button(), transform.map(ev->position()), ev->modifiers(),
1061 ev->buttons(), ev->globalPosition());
1063 case QEvent::InputMethod:
1064 d->inputMethodEvent(
static_cast<QInputMethodEvent *>(e));
1066#ifndef QT_NO_CONTEXTMENU
1067 case QEvent::ContextMenu: {
1068 QContextMenuEvent *ev =
static_cast<QContextMenuEvent *>(e);
1069 d->contextMenuEvent(ev->globalPos(), transform.map(ev->pos()), contextWidget);
1072 case QEvent::FocusIn:
1073 case QEvent::FocusOut:
1074 d->focusEvent(
static_cast<QFocusEvent *>(e));
1077 case QEvent::EnabledChange:
1078 d->isEnabled = e->isAccepted();
1081#if QT_CONFIG(tooltip)
1082 case QEvent::ToolTip: {
1083 QHelpEvent *ev =
static_cast<QHelpEvent *>(e);
1084 d->showToolTip(ev->globalPos(), transform.map(ev->pos()), contextWidget);
1089#if QT_CONFIG(draganddrop)
1090 case QEvent::DragEnter: {
1091 QDragEnterEvent *ev =
static_cast<QDragEnterEvent *>(e);
1092 if (d->dragEnterEvent(e, ev->mimeData()))
1093 ev->acceptProposedAction();
1096 case QEvent::DragLeave:
1097 d->dragLeaveEvent();
1099 case QEvent::DragMove: {
1100 QDragMoveEvent *ev =
static_cast<QDragMoveEvent *>(e);
1101 if (d->dragMoveEvent(e, ev->mimeData(), transform.map(ev->position())))
1102 ev->acceptProposedAction();
1105 case QEvent::Drop: {
1106 QDropEvent *ev =
static_cast<QDropEvent *>(e);
1107 if (d->dropEvent(ev->mimeData(), transform.map(ev->position()), ev->dropAction(), ev->source()))
1108 ev->acceptProposedAction();
1113#if QT_CONFIG(graphicsview)
1114 case QEvent::GraphicsSceneMousePress: {
1115 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1116 d->mousePressEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1119 case QEvent::GraphicsSceneMouseMove: {
1120 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1121 d->mouseMoveEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1124 case QEvent::GraphicsSceneMouseRelease: {
1125 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1126 d->mouseReleaseEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1129 case QEvent::GraphicsSceneMouseDoubleClick: {
1130 QGraphicsSceneMouseEvent *ev =
static_cast<QGraphicsSceneMouseEvent *>(e);
1131 d->mouseDoubleClickEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
1134 case QEvent::GraphicsSceneContextMenu: {
1135 QGraphicsSceneContextMenuEvent *ev =
static_cast<QGraphicsSceneContextMenuEvent *>(e);
1136 d->contextMenuEvent(ev->screenPos(), transform.map(ev->pos()), contextWidget);
1139 case QEvent::GraphicsSceneHoverMove: {
1140 QGraphicsSceneHoverEvent *ev =
static_cast<QGraphicsSceneHoverEvent *>(e);
1141 d->mouseMoveEvent(ev, Qt::NoButton, transform.map(ev->pos()), ev->modifiers(),Qt::NoButton,
1145 case QEvent::GraphicsSceneDragEnter: {
1146 QGraphicsSceneDragDropEvent *ev =
static_cast<QGraphicsSceneDragDropEvent *>(e);
1147 if (d->dragEnterEvent(e, ev->mimeData()))
1148 ev->acceptProposedAction();
1150 case QEvent::GraphicsSceneDragLeave:
1151 d->dragLeaveEvent();
1153 case QEvent::GraphicsSceneDragMove: {
1154 QGraphicsSceneDragDropEvent *ev =
static_cast<QGraphicsSceneDragDropEvent *>(e);
1155 if (d->dragMoveEvent(e, ev->mimeData(), transform.map(ev->pos())))
1156 ev->acceptProposedAction();
1158 case QEvent::GraphicsSceneDrop: {
1159 QGraphicsSceneDragDropEvent *ev =
static_cast<QGraphicsSceneDragDropEvent *>(e);
1160 if (d->dropEvent(ev->mimeData(), transform.map(ev->pos()), ev->dropAction(), ev->source()))
1164#ifdef QT_KEYPAD_NAVIGATION
1165 case QEvent::EnterEditFocus:
1166 case QEvent::LeaveEditFocus:
1167 if (QApplicationPrivate::keypadNavigationEnabled())
1168 d->editFocusEvent(e);
1171 case QEvent::ShortcutOverride:
1172 if (d->interactionFlags & Qt::TextEditable) {
1173 QKeyEvent* ke =
static_cast<QKeyEvent *>(e);
1174 if (isCommonTextEditShortcut(ke))
1226 Q_Q(QWidgetTextControl);
1227#ifndef QT_NO_SHORTCUT
1228 if (e == QKeySequence::SelectAll) {
1231#ifndef QT_NO_CLIPBOARD
1232 setClipboardSelection();
1236#ifndef QT_NO_CLIPBOARD
1237 else if (e == QKeySequence::Copy) {
1245 if (interactionFlags & Qt::TextSelectableByKeyboard
1246 && cursorMoveKeyEvent(e))
1249 if (interactionFlags & Qt::LinksAccessibleByKeyboard) {
1250 if ((e->key() == Qt::Key_Return
1251 || e->key() == Qt::Key_Enter
1252#ifdef QT_KEYPAD_NAVIGATION
1253 || e->key() == Qt::Key_Select
1256 && cursor.hasSelection()) {
1259 activateLinkUnderCursor();
1264 if (!(interactionFlags & Qt::TextEditable)) {
1269 if (e->key() == Qt::Key_Direction_L || e->key() == Qt::Key_Direction_R) {
1270 QTextBlockFormat fmt;
1271 fmt.setLayoutDirection((e->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
1272 cursor.mergeBlockFormat(fmt);
1282 if (e->key() == Qt::Key_Backspace && !(e->modifiers() & ~(Qt::ShiftModifier | Qt::GroupSwitchModifier))) {
1283 QTextBlockFormat blockFmt = cursor.blockFormat();
1284 QTextList *list = cursor.currentList();
1285 if (list && cursor.atBlockStart() && !cursor.hasSelection()) {
1286 list->remove(cursor.block());
1287 }
else if (cursor.atBlockStart() && blockFmt.indent() > 0) {
1288 blockFmt.setIndent(blockFmt.indent() - 1);
1289 cursor.setBlockFormat(blockFmt);
1291 QTextCursor localCursor = cursor;
1292 localCursor.deletePreviousChar();
1298#ifndef QT_NO_SHORTCUT
1299 else if (e == QKeySequence::InsertParagraphSeparator) {
1300 insertParagraphSeparator();
1303 }
else if (e == QKeySequence::InsertLineSeparator) {
1304 cursor.insertText(QString(QChar::LineSeparator));
1311#ifndef QT_NO_SHORTCUT
1312 else if (e == QKeySequence::Undo) {
1315 else if (e == QKeySequence::Redo) {
1318#ifndef QT_NO_CLIPBOARD
1319 else if (e == QKeySequence::Cut) {
1322 else if (e == QKeySequence::Paste) {
1323 QClipboard::Mode mode = QClipboard::Clipboard;
1324 if (QGuiApplication::clipboard()->supportsSelection()) {
1325 if (e->modifiers() == (Qt::CTRL | Qt::SHIFT) && e->key() == Qt::Key_Insert)
1326 mode = QClipboard::Selection;
1331 else if (e == QKeySequence::Delete) {
1332 QTextCursor localCursor = cursor;
1333 localCursor.deleteChar();
1336 }
else if (e == QKeySequence::Backspace) {
1337 QTextCursor localCursor = cursor;
1338 localCursor.deletePreviousChar();
1341 }
else if (e == QKeySequence::DeleteEndOfWord) {
1342 if (!cursor.hasSelection())
1343 cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor);
1344 cursor.removeSelectedText();
1346 else if (e == QKeySequence::DeleteStartOfWord) {
1347 if (!cursor.hasSelection())
1348 cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor);
1349 cursor.removeSelectedText();
1351 else if (e == QKeySequence::DeleteEndOfLine) {
1352 QTextBlock block = cursor.block();
1353 if (cursor.position() == block.position() + block.length() - 2)
1354 cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
1356 cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
1357 cursor.removeSelectedText();
1367 if (q->isAcceptableInput(e)) {
1371 && !cursor.hasSelection()
1372 && !cursor.atBlockEnd())
1373 cursor.deleteChar();
1375 cursor.insertText(e->text());
1385#ifndef QT_NO_CLIPBOARD
1386 setClipboardSelection();
1392 q->ensureCursorVisible();
1394 updateCurrentCharFormat();
1483QRectF QWidgetTextControl::selectionRect(
const QTextCursor &cursor)
const
1485 Q_D(
const QWidgetTextControl);
1487 QRectF r = d->rectForPosition(cursor.selectionStart());
1489 if (cursor.hasComplexSelection() && cursor.currentTable()) {
1490 QTextTable *table = cursor.currentTable();
1492 r = d->doc->documentLayout()->frameBoundingRect(table);
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
1529
1530
1531
1532
1533
1534 }
else if (cursor.hasSelection()) {
1535 const int position = cursor.selectionStart();
1536 const int anchor = cursor.selectionEnd();
1537 const QTextBlock posBlock = d->doc->findBlock(position);
1538 const QTextBlock anchorBlock = d->doc->findBlock(anchor);
1539 if (posBlock == anchorBlock && posBlock.isValid() && posBlock.layout()->lineCount()) {
1540 const QTextLine posLine = posBlock.layout()->lineForTextPosition(position - posBlock.position());
1541 const QTextLine anchorLine = anchorBlock.layout()->lineForTextPosition(anchor - anchorBlock.position());
1543 const int firstLine = qMin(posLine.lineNumber(), anchorLine.lineNumber());
1544 const int lastLine = qMax(posLine.lineNumber(), anchorLine.lineNumber());
1545 const QTextLayout *layout = posBlock.layout();
1547 for (
int i = firstLine; i <= lastLine; ++i) {
1548 r |= layout->lineAt(i).rect();
1549 r |= layout->lineAt(i).naturalTextRect();
1551 r.translate(blockBoundingRect(posBlock).topLeft());
1553 QRectF anchorRect = d->rectForPosition(cursor.selectionEnd());
1555 r |= boundingRectOfFloatsInSelection(cursor);
1556 QRectF frameRect(d->doc->documentLayout()->frameBoundingRect(cursor.currentFrame()));
1557 r.setLeft(frameRect.left());
1558 r.setRight(frameRect.right());
1561 r.adjust(-1, -1, 1, 1);
1574 Qt::MouseButtons buttons,
const QPointF &globalPos)
1576 Q_Q(QWidgetTextControl);
1578 mousePressPos = pos;
1580#if QT_CONFIG(draganddrop)
1581 mightStartDrag =
false;
1584 if (sendMouseEventToInputContext(
1585 e, QEvent::MouseButtonPress, button, pos, modifiers, buttons, globalPos)) {
1589 if (interactionFlags & Qt::LinksAccessibleByMouse) {
1590 anchorOnMousePress = q->anchorAt(pos);
1595 cursor.clearSelection();
1598 if (!(button & Qt::LeftButton) ||
1599 !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))) {
1603 bool wasValid = blockWithMarkerUnderMouse.isValid();
1604 blockWithMarkerUnderMouse = q->blockWithMarkerAt(pos);
1605 if (wasValid != blockWithMarkerUnderMouse.isValid())
1606 emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
1610 const QTextCursor oldSelection = cursor;
1611 const int oldCursorPos = cursor.position();
1613 mousePressed = (interactionFlags & Qt::TextSelectableByMouse);
1617 if (trippleClickTimer.isActive()
1618 && ((pos - trippleClickPoint).manhattanLength() < QApplication::startDragDistance())) {
1620 cursor.movePosition(QTextCursor::StartOfBlock);
1621 cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
1622 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
1623 selectedBlockOnTrippleClick = cursor;
1625 anchorOnMousePress = QString();
1626 blockWithMarkerUnderMouse = QTextBlock();
1627 emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
1629 trippleClickTimer.stop();
1631 int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
1632 if (cursorPos == -1) {
1637 if (modifiers == Qt::ShiftModifier && (interactionFlags & Qt::TextSelectableByMouse)) {
1638 if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) {
1639 selectedWordOnDoubleClick = cursor;
1640 selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor);
1643 if (selectedBlockOnTrippleClick.hasSelection())
1645 else if (selectedWordOnDoubleClick.hasSelection())
1646 extendWordwiseSelection(cursorPos, pos.x());
1647 else if (!wordSelectionEnabled)
1648 setCursorPosition(cursorPos, QTextCursor::KeepAnchor);
1652 && cursor.hasSelection()
1653 && !cursorIsFocusIndicator
1654 && cursorPos >= cursor.selectionStart()
1655 && cursorPos <= cursor.selectionEnd()
1656 && q->hitTest(pos, Qt::ExactHit) != -1) {
1657#if QT_CONFIG(draganddrop)
1658 mightStartDrag =
true;
1663 setCursorPosition(cursorPos);
1667 if (interactionFlags & Qt::TextEditable) {
1668 q->ensureCursorVisible();
1669 if (cursor.position() != oldCursorPos)
1670 emit q->cursorPositionChanged();
1673 if (cursor.position() != oldCursorPos) {
1674 emit q->cursorPositionChanged();
1675 emit q->microFocusChanged();
1679 repaintOldAndNewSelection(oldSelection);
1680 hadSelectionOnMousePress = cursor.hasSelection();
1684 Qt::MouseButtons buttons,
const QPointF &globalPos)
1686 Q_Q(QWidgetTextControl);
1688 if (interactionFlags & Qt::LinksAccessibleByMouse)
1689 updateHighlightedAnchor(mousePos);
1691 if (buttons & Qt::LeftButton) {
1692 const bool editable = interactionFlags & Qt::TextEditable;
1697 || selectedWordOnDoubleClick.hasSelection()
1698 || selectedBlockOnTrippleClick.hasSelection()))
1701 const QTextCursor oldSelection = cursor;
1702 const int oldCursorPos = cursor.position();
1705 if ((mousePos - mousePressPos).manhattanLength() > QApplication::startDragDistance())
1710 const qreal mouseX = qreal(mousePos.x());
1712 int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1716 int selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1718 if (newCursorPos != selectionStartPos) {
1721 newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1722 selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1723 setCursorPosition(selectionStartPos);
1727 if (newCursorPos == -1)
1730 if (mousePressed && wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) {
1731 selectedWordOnDoubleClick = cursor;
1732 selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor);
1735 if (selectedBlockOnTrippleClick.hasSelection())
1737 else if (selectedWordOnDoubleClick.hasSelection())
1738 extendWordwiseSelection(newCursorPos, mouseX);
1739 else if (mousePressed && !isPreediting())
1740 setCursorPosition(newCursorPos, QTextCursor::KeepAnchor);
1742 if (interactionFlags & Qt::TextEditable) {
1746 if (cursor.position() != oldCursorPos)
1747 emit q->cursorPositionChanged();
1751 QGuiApplication::inputMethod()->update(Qt::ImQueryInput);
1755 if (cursor.position() != oldCursorPos) {
1756 emit q->cursorPositionChanged();
1757 emit q->microFocusChanged();
1761 repaintOldAndNewSelection(oldSelection);
1763 bool wasValid = blockWithMarkerUnderMouse.isValid();
1764 blockWithMarkerUnderMouse = q->blockWithMarkerAt(mousePos);
1765 if (wasValid != blockWithMarkerUnderMouse.isValid())
1766 emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
1769 sendMouseEventToInputContext(e, QEvent::MouseMove, button, mousePos, modifiers, buttons, globalPos);
1773 Qt::MouseButtons buttons,
const QPointF &globalPos)
1775 Q_Q(QWidgetTextControl);
1777 const QTextCursor oldSelection = cursor;
1778 if (sendMouseEventToInputContext(
1779 e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) {
1780 repaintOldAndNewSelection(oldSelection);
1784 const int oldCursorPos = cursor.position();
1786#if QT_CONFIG(draganddrop)
1787 if (mightStartDrag && (button & Qt::LeftButton)) {
1788 mousePressed =
false;
1789 setCursorPosition(pos);
1790 cursor.clearSelection();
1796#ifndef QT_NO_CLIPBOARD
1799 }
else if (button == Qt::MiddleButton
1800 && (interactionFlags & Qt::TextEditable)
1801 && QGuiApplication::clipboard()->supportsSelection()) {
1802 setCursorPosition(pos);
1803 const QMimeData *md = QGuiApplication::clipboard()->mimeData(QClipboard::Selection);
1805 q->insertFromMimeData(md);
1809 repaintOldAndNewSelection(oldSelection);
1811 if (cursor.position() != oldCursorPos) {
1812 emit q->cursorPositionChanged();
1813 emit q->microFocusChanged();
1817 if ((interactionFlags & Qt::TextEditable) && (button & Qt::LeftButton) &&
1818 (blockWithMarkerUnderMouse.isValid()) && !cursor.hasSelection()) {
1819 QTextBlock markerBlock = q->blockWithMarkerAt(pos);
1820 if (markerBlock == blockWithMarkerUnderMouse) {
1821 auto fmt = blockWithMarkerUnderMouse.blockFormat();
1822 switch (fmt.marker()) {
1823 case QTextBlockFormat::MarkerType::Unchecked :
1824 fmt.setMarker(QTextBlockFormat::MarkerType::Checked);
1826 case QTextBlockFormat::MarkerType::Checked:
1827 fmt.setMarker(QTextBlockFormat::MarkerType::Unchecked);
1832 cursor.setBlockFormat(fmt);
1836 if (interactionFlags & Qt::LinksAccessibleByMouse) {
1839 if (!(button & Qt::LeftButton)) {
1844 const QString anchor = q->anchorAt(pos);
1847 if (anchor.isEmpty()) {
1852 if (!cursor.hasSelection()
1853 || (anchor == anchorOnMousePress && hadSelectionOnMousePress)) {
1855 const int anchorPos = q->hitTest(pos, Qt::ExactHit);
1858 if (anchorPos < 0) {
1863 cursor.setPosition(anchorPos);
1864 activateLinkUnderCursor(std::exchange(anchorOnMousePress, QString()));
2050 Q_Q(QWidgetTextControl);
2051 if (!(interactionFlags & (Qt::TextEditable | Qt::TextSelectableByMouse)) || cursor.isNull()) {
2055 bool isGettingInput = !e->commitString().isEmpty()
2056 || e->preeditString() != cursor.block().layout()->preeditAreaText()
2057 || e->replacementLength() > 0;
2059 if (!isGettingInput && e->attributes().isEmpty()) {
2064 int oldCursorPos = cursor.position();
2066 cursor.beginEditBlock();
2067 if (isGettingInput) {
2068 cursor.removeSelectedText();
2074 if (!e->commitString().isEmpty() || e->replacementLength()) {
2075 auto *mimeData = QInputControl::mimeDataForInputEvent(e);
2076 if (mimeData && q->canInsertFromMimeData(mimeData)) {
2077 q->insertFromMimeData(mimeData);
2079 if (e->commitString().endsWith(QChar::LineFeed))
2080 block = cursor.block();
2081 QTextCursor c = cursor;
2082 c.setPosition(c.position() + e->replacementStart());
2083 c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor);
2084 c.insertText(e->commitString());
2088 for (
int i = 0; i < e->attributes().size(); ++i) {
2089 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
2090 if (a.type == QInputMethodEvent::Selection) {
2091 QTextCursor oldCursor = cursor;
2092 int blockStart = a.start + cursor.block().position();
2093 cursor.setPosition(blockStart, QTextCursor::MoveAnchor);
2094 cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
2095 q->ensureCursorVisible();
2096 repaintOldAndNewSelection(oldCursor);
2100 if (!block.isValid())
2101 block = cursor.block();
2102 QTextLayout *layout = block.layout();
2104 layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
2105 QList<QTextLayout::FormatRange> overrides;
2106 overrides.reserve(e->attributes().size());
2107 const int oldPreeditCursor = preeditCursor;
2108 preeditCursor = e->preeditString().size();
2110 for (
int i = 0; i < e->attributes().size(); ++i) {
2111 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
2112 if (a.type == QInputMethodEvent::Cursor) {
2113 preeditCursor = a.start;
2114 hideCursor = !a.length;
2115 }
else if (a.type == QInputMethodEvent::TextFormat) {
2116 QTextCharFormat f = cursor.charFormat();
2117 f.merge(qvariant_cast<QTextFormat>(a.value).toCharFormat());
2119 QTextLayout::FormatRange o;
2120 o.start = a.start + cursor.position() - block.position();
2121 o.length = a.length;
2125 QList<QTextLayout::FormatRange>::iterator it = overrides.end();
2126 while (it != overrides.begin()) {
2127 QList<QTextLayout::FormatRange>::iterator previous = it - 1;
2128 if (o.start >= previous->start) {
2129 overrides.insert(it, o);
2135 if (it == overrides.begin())
2136 overrides.prepend(o);
2141 if (cursor.charFormat().isValid()) {
2142 int start = cursor.position() - block.position();
2143 int end = start + e->preeditString().size();
2145 QList<QTextLayout::FormatRange>::iterator it = overrides.begin();
2146 while (it != overrides.end()) {
2147 QTextLayout::FormatRange range = *it;
2148 int rangeStart = range.start;
2149 if (rangeStart > start) {
2150 QTextLayout::FormatRange o;
2152 o.length = rangeStart - start;
2153 o.format = cursor.charFormat();
2154 it = overrides.insert(it, o) + 1;
2158 start = range.start + range.length;
2162 QTextLayout::FormatRange o;
2164 o.length = end - start;
2165 o.format = cursor.charFormat();
2166 overrides.append(o);
2169 layout->setFormats(overrides);
2171 cursor.endEditBlock();
2175 if (oldCursorPos != cursor.position())
2176 emit q->cursorPositionChanged();
2177 if (oldPreeditCursor != preeditCursor)
2178 emit q->microFocusChanged();
2181QVariant QWidgetTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument)
const
2183 Q_D(
const QWidgetTextControl);
2184 QTextBlock block = d->cursor.block();
2186 case Qt::ImCursorRectangle:
2187 return cursorRect();
2188 case Qt::ImAnchorRectangle:
2189 return d->rectForPosition(d->cursor.anchor());
2191 return QVariant(d->cursor.charFormat().font());
2192 case Qt::ImCursorPosition: {
2193 const QPointF pt = argument.toPointF();
2195 return QVariant(cursorForPosition(pt).position() - block.position());
2196 return QVariant(d->cursor.position() - block.position()); }
2197 case Qt::ImSurroundingText:
2198 return QVariant(block.text());
2199 case Qt::ImCurrentSelection: {
2200 QMimeData *mimeData = createMimeDataFromSelection();
2201 mimeData->deleteLater();
2202 return QInputControl::selectionWrapper(mimeData);
2204 case Qt::ImMaximumTextLength:
2206 case Qt::ImAnchorPosition:
2207 return QVariant(d->cursor.anchor() - block.position());
2208 case Qt::ImAbsolutePosition: {
2209 const QPointF pt = argument.toPointF();
2211 return QVariant(cursorForPosition(pt).position());
2212 return QVariant(d->cursor.position()); }
2213 case Qt::ImTextAfterCursor:
2215 int maxLength = argument.isValid() ? argument.toInt() : 1024;
2216 QTextCursor tmpCursor = d->cursor;
2217 int localPos = d->cursor.position() - block.position();
2218 QString result = block.text().mid(localPos);
2219 while (result.size() < maxLength) {
2220 int currentBlock = tmpCursor.blockNumber();
2221 tmpCursor.movePosition(QTextCursor::NextBlock);
2222 if (tmpCursor.blockNumber() == currentBlock)
2224 result += u'\n' + tmpCursor.block().text();
2226 return QVariant(result);
2228 case Qt::ImTextBeforeCursor:
2230 int maxLength = argument.isValid() ? argument.toInt() : 1024;
2231 QTextCursor tmpCursor = d->cursor;
2232 int localPos = d->cursor.position() - block.position();
2234 int resultLen = localPos;
2235 while (resultLen < maxLength) {
2236 int currentBlock = tmpCursor.blockNumber();
2237 tmpCursor.movePosition(QTextCursor::PreviousBlock);
2238 if (tmpCursor.blockNumber() == currentBlock)
2241 resultLen += tmpCursor.block().length();
2245 result += tmpCursor.block().text() + u'\n';
2246 tmpCursor.movePosition(QTextCursor::NextBlock);
2249 result += QStringView{block.text()}.mid(0, localPos);
2250 return QVariant(result);
2343QMenu *QWidgetTextControl::createStandardContextMenu(
const QPointF &pos, QWidget *parent)
2345 Q_D(QWidgetTextControl);
2347 const bool showTextSelectionActions = d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
2349 d->linkToCopy = QString();
2351 d->linkToCopy = anchorAt(pos);
2353 if (d->linkToCopy.isEmpty() && !showTextSelectionActions)
2356 QMenu *menu =
new QMenu(parent);
2359 if (d->interactionFlags & Qt::TextEditable) {
2360 a = menu->addAction(tr(
"&Undo") +
ACCEL_KEY(QKeySequence::Undo),
this, SLOT(undo()));
2361 a->setEnabled(d->doc->isUndoAvailable());
2362 a->setObjectName(QStringLiteral(
"edit-undo"));
2363 setActionIcon(a, QStringLiteral(
"edit-undo"));
2364 a = menu->addAction(tr(
"&Redo") +
ACCEL_KEY(QKeySequence::Redo),
this, SLOT(redo()));
2365 a->setEnabled(d->doc->isRedoAvailable());
2366 a->setObjectName(QStringLiteral(
"edit-redo"));
2367 setActionIcon(a, QStringLiteral(
"edit-redo"));
2368 menu->addSeparator();
2370#ifndef QT_NO_CLIPBOARD
2371 a = menu->addAction(tr(
"Cu&t") +
ACCEL_KEY(QKeySequence::Cut),
this, SLOT(cut()));
2372 a->setEnabled(d->cursor.hasSelection());
2373 a->setObjectName(QStringLiteral(
"edit-cut"));
2374 setActionIcon(a, QStringLiteral(
"edit-cut"));
2378#ifndef QT_NO_CLIPBOARD
2379 if (showTextSelectionActions) {
2380 a = menu->addAction(tr(
"&Copy") +
ACCEL_KEY(QKeySequence::Copy),
this, SLOT(copy()));
2381 a->setEnabled(d->cursor.hasSelection());
2382 a->setObjectName(QStringLiteral(
"edit-copy"));
2383 setActionIcon(a, QStringLiteral(
"edit-copy"));
2386 if ((d->interactionFlags & Qt::LinksAccessibleByKeyboard)
2387 || (d->interactionFlags & Qt::LinksAccessibleByMouse)) {
2389 a = menu->addAction(tr(
"Copy &Link Location"),
this, SLOT(_q_copyLink()));
2390 a->setEnabled(!d->linkToCopy.isEmpty());
2391 a->setObjectName(QStringLiteral(
"link-copy"));
2395 if (d->interactionFlags & Qt::TextEditable) {
2396#ifndef QT_NO_CLIPBOARD
2397 a = menu->addAction(tr(
"&Paste") +
ACCEL_KEY(QKeySequence::Paste),
this, SLOT(paste()));
2398 a->setEnabled(canPaste());
2399 a->setObjectName(QStringLiteral(
"edit-paste"));
2400 setActionIcon(a, QStringLiteral(
"edit-paste"));
2402 a = menu->addAction(tr(
"Delete"),
this, SLOT(_q_deleteSelected()));
2403 a->setEnabled(d->cursor.hasSelection());
2404 a->setObjectName(QStringLiteral(
"edit-delete"));
2405 setActionIcon(a, QStringLiteral(
"edit-delete"));
2409 if (showTextSelectionActions) {
2410 menu->addSeparator();
2411 a = menu->addAction(tr(
"Select All") +
ACCEL_KEY(QKeySequence::SelectAll),
this, SLOT(selectAll()));
2412 a->setEnabled(!d->doc->isEmpty());
2413 a->setObjectName(QStringLiteral(
"select-all"));
2414 setActionIcon(a, QStringLiteral(
"edit-select-all"));
2417 if ((d->interactionFlags & Qt::TextEditable) && QGuiApplication::styleHints()->useRtlExtensions()) {
2418 menu->addSeparator();
2419 QUnicodeControlCharacterMenu *ctrlCharacterMenu =
new QUnicodeControlCharacterMenu(
this, menu);
2420 menu->addMenu(ctrlCharacterMenu);
2782bool QWidgetTextControl::findNextPrevAnchor(
const QTextCursor &startCursor,
bool next, QTextCursor &newAnchor)
2784 Q_D(QWidgetTextControl);
2786 int anchorStart = -1;
2791 const int startPos = startCursor.selectionEnd();
2793 QTextBlock block = d->doc->findBlock(startPos);
2794 QTextBlock::Iterator it = block.begin();
2796 while (!it.atEnd() && it.fragment().position() < startPos)
2799 while (block.isValid()) {
2803 for (; !it.atEnd(); ++it) {
2804 const QTextFragment fragment = it.fragment();
2805 const QTextCharFormat fmt = fragment.charFormat();
2807 if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) {
2808 anchorStart = fragment.position();
2809 anchorHref = fmt.anchorHref();
2814 if (anchorStart != -1) {
2818 for (; !it.atEnd(); ++it) {
2819 const QTextFragment fragment = it.fragment();
2820 const QTextCharFormat fmt = fragment.charFormat();
2822 if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) {
2823 anchorEnd = fragment.position();
2828 if (anchorEnd == -1)
2829 anchorEnd = block.position() + block.length() - 1;
2835 block = block.next();
2839 int startPos = startCursor.selectionStart();
2843 QTextBlock block = d->doc->findBlock(startPos);
2844 QTextBlock::Iterator blockStart = block.begin();
2845 QTextBlock::Iterator it = block.end();
2847 if (startPos == block.position()) {
2851 if (it == blockStart) {
2852 it = QTextBlock::Iterator();
2853 block = QTextBlock();
2857 }
while (!it.atEnd() && it.fragment().position() + it.fragment().length() - 1 > startPos);
2860 while (block.isValid()) {
2865 const QTextFragment fragment = it.fragment();
2866 const QTextCharFormat fmt = fragment.charFormat();
2868 if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) {
2869 anchorStart = fragment.position() + fragment.length();
2870 anchorHref = fmt.anchorHref();
2874 if (it == blockStart)
2875 it = QTextBlock::Iterator();
2878 }
while (!it.atEnd());
2881 if (anchorStart != -1 && !it.atEnd()) {
2885 const QTextFragment fragment = it.fragment();
2886 const QTextCharFormat fmt = fragment.charFormat();
2888 if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) {
2889 anchorEnd = fragment.position() + fragment.length();
2893 if (it == blockStart)
2894 it = QTextBlock::Iterator();
2897 }
while (!it.atEnd());
2899 if (anchorEnd == -1)
2900 anchorEnd = qMax(0, block.position());
2905 block = block.previous();
2907 if (it != block.begin())
2909 blockStart = block.begin();
2914 if (anchorStart != -1 && anchorEnd != -1) {
2915 newAnchor = d->cursor;
2916 newAnchor.setPosition(anchorStart);
2917 newAnchor.setPosition(anchorEnd, QTextCursor::KeepAnchor);
2926 QTextCursor oldCursor = cursor;
2928 if (href.isEmpty()) {
2929 QTextCursor tmp = cursor;
2930 if (tmp.selectionStart() != tmp.position())
2931 tmp.setPosition(tmp.selectionStart());
2932 tmp.movePosition(QTextCursor::NextCharacter);
2933 href = tmp.charFormat().anchorHref();
2938 if (!cursor.hasSelection()) {
2939 QTextBlock block = cursor.block();
2940 const int cursorPos = cursor.position();
2942 QTextBlock::Iterator it = block.begin();
2943 QTextBlock::Iterator linkFragment;
2945 for (; !it.atEnd(); ++it) {
2946 QTextFragment fragment = it.fragment();
2947 const int fragmentPos = fragment.position();
2948 if (fragmentPos <= cursorPos &&
2949 fragmentPos + fragment.length() > cursorPos) {
2955 if (!linkFragment.atEnd()) {
2957 cursor.setPosition(it.fragment().position());
2958 if (it != block.begin()) {
2961 QTextFragment fragment = it.fragment();
2962 if (fragment.charFormat().anchorHref() != href)
2964 cursor.setPosition(fragment.position());
2965 }
while (it != block.begin());
2968 for (it = linkFragment; !it.atEnd(); ++it) {
2969 QTextFragment fragment = it.fragment();
2970 if (fragment.charFormat().anchorHref() != href)
2972 cursor.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor);
2981 cursor.clearSelection();
2983 repaintOldAndNewSelection(oldCursor);
2985#ifndef QT_NO_DESKTOPSERVICES
2987 QDesktopServices::openUrl(QUrl{href});
2990 emit q_func()->linkActivated(href);
3249 auto blockFmt = cursor.blockFormat();
3250 auto charFmt = cursor.charFormat();
3251 blockFmt.clearProperty(QTextFormat::BlockTrailingHorizontalRulerWidth);
3252 if (blockFmt.hasProperty(QTextFormat::HeadingLevel)) {
3253 blockFmt.clearProperty(QTextFormat::HeadingLevel);
3254 charFmt = QTextCharFormat();
3256 if (cursor.currentList()) {
3257 auto existingFmt = cursor.blockFormat();
3258 existingFmt.clearProperty(QTextBlockFormat::BlockBottomMargin);
3259 cursor.setBlockFormat(existingFmt);
3260 if (blockFmt.marker() == QTextBlockFormat::MarkerType::Checked)
3261 blockFmt.setMarker(QTextBlockFormat::MarkerType::Unchecked);
3266 if (cursor.block().text().isEmpty() &&
3267 !cursor.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth) &&
3268 !cursor.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
3269 blockFmt = QTextBlockFormat();
3270 const bool blockFmtChanged = (cursor.blockFormat() != blockFmt);
3271 charFmt = QTextCharFormat();
3272 cursor.setBlockFormat(blockFmt);
3273 cursor.setCharFormat(charFmt);
3278 if (blockFmtChanged)
3282 cursor.insertBlock(blockFmt, charFmt);
3354QAbstractTextDocumentLayout::PaintContext QWidgetTextControl::getPaintContext(QWidget *widget)
const
3356 Q_D(
const QWidgetTextControl);
3358 QAbstractTextDocumentLayout::PaintContext ctx;
3360 ctx.selections = d->extraSelections;
3361 ctx.palette = d->palette;
3362#if QT_CONFIG(style_stylesheet)
3364 if (
auto cssStyle = qt_styleSheet(widget->style())) {
3365 QStyleOption option;
3366 option.initFrom(widget);
3367 cssStyle->styleSheetPalette(widget, &option, &ctx.palette);
3371 if (d->cursorOn && d->isEnabled) {
3373 ctx.cursorPosition = -1;
3374 else if (d->preeditCursor != 0)
3375 ctx.cursorPosition = - (d->preeditCursor + 2);
3377 ctx.cursorPosition = d->cursor.position();
3380 if (!d->dndFeedbackCursor.isNull())
3381 ctx.cursorPosition = d->dndFeedbackCursor.position();
3382#ifdef QT_KEYPAD_NAVIGATION
3383 if (!QApplicationPrivate::keypadNavigationEnabled() || d->hasEditFocus)
3385 if (d->cursor.hasSelection()) {
3386 QAbstractTextDocumentLayout::Selection selection;
3387 selection.cursor = d->cursor;
3388 if (d->cursorIsFocusIndicator) {
3390 opt.palette = ctx.palette;
3391 QStyleHintReturnVariant ret;
3392 QStyle *style = QApplication::style();
3394 style = widget->style();
3395 style->styleHint(QStyle::SH_TextControl_FocusIndicatorTextCharFormat, &opt, widget, &ret);
3396 selection.format = qvariant_cast<QTextFormat>(ret.variant).toCharFormat();
3398 QPalette::ColorGroup cg = d->hasFocus ? QPalette::Active : QPalette::Inactive;
3399 selection.format.setBackground(ctx.palette.brush(cg, QPalette::Highlight));
3400 selection.format.setForeground(ctx.palette.brush(cg, QPalette::HighlightedText));
3402 QStyle *style = QApplication::style();
3404 opt.initFrom(widget);
3405 style = widget->style();
3407 if (style->styleHint(QStyle::SH_RichText_FullWidthSelection, &opt, widget))
3408 selection.format.setProperty(QTextFormat::FullWidthSelection,
true);
3410 ctx.selections.append(selection);