8#ifndef QT_NO_TEXTCONTROL
10#include <qcoreapplication.h>
12#include <qfontmetrics.h>
15#include <qclipboard.h>
17#include <qinputmethod.h>
18#include "private/qtextdocumentlayout_p.h"
19#include "private/qabstracttextdocumentlayout_p.h"
21#include "private/qtextdocument_p.h"
24#include "private/qtextcursor_p.h"
25#include <QtCore/qloggingcategory.h>
27#include <qtextformat.h>
28#include <qtransform.h>
31#include <qguiapplication.h>
33#include <qtexttable.h>
36#include <qstylehints.h>
37#include <qmetaobject.h>
39#include <private/qqmlglobal_p.h>
40#include <private/qquickdeliveryagent_p_p.h>
48static QTextLine currentTextLine(
const QTextCursor &cursor)
50 const QTextBlock block = cursor.block();
54 const QTextLayout *layout = block.layout();
58 const int relativePos = cursor.position() - block.position();
59 return layout->lineForTextPosition(relativePos);
67 interactionFlags(Qt::TextEditorInteraction),
92#if !QT_CONFIG(shortcut)
96 Q_Q(QQuickTextControl);
100 const QTextCursor oldSelection = cursor;
101 const int oldCursorPos = cursor.position();
103 QTextCursor::MoveMode mode = QTextCursor::MoveAnchor;
104 QTextCursor::MoveOperation op = QTextCursor::NoMove;
108#if QT_CONFIG(shortcut)
109 if (e == QKeySequence::MoveToNextChar) {
110 op = QTextCursor::Right;
112 else if (e == QKeySequence::MoveToPreviousChar) {
113 op = QTextCursor::Left;
115 else if (e == QKeySequence::SelectNextChar) {
116 op = QTextCursor::Right;
117 mode = QTextCursor::KeepAnchor;
119 else if (e == QKeySequence::SelectPreviousChar) {
120 op = QTextCursor::Left;
121 mode = QTextCursor::KeepAnchor;
123 else if (e == QKeySequence::SelectNextWord) {
124 op = QTextCursor::WordRight;
125 mode = QTextCursor::KeepAnchor;
127 else if (e == QKeySequence::SelectPreviousWord) {
128 op = QTextCursor::WordLeft;
129 mode = QTextCursor::KeepAnchor;
131 else if (e == QKeySequence::SelectStartOfLine) {
132 op = QTextCursor::StartOfLine;
133 mode = QTextCursor::KeepAnchor;
135 else if (e == QKeySequence::SelectEndOfLine) {
136 op = QTextCursor::EndOfLine;
137 mode = QTextCursor::KeepAnchor;
139 else if (e == QKeySequence::SelectStartOfBlock) {
140 op = QTextCursor::StartOfBlock;
141 mode = QTextCursor::KeepAnchor;
143 else if (e == QKeySequence::SelectEndOfBlock) {
144 op = QTextCursor::EndOfBlock;
145 mode = QTextCursor::KeepAnchor;
147 else if (e == QKeySequence::SelectStartOfDocument) {
148 op = QTextCursor::Start;
149 mode = QTextCursor::KeepAnchor;
151 else if (e == QKeySequence::SelectEndOfDocument) {
152 op = QTextCursor::End;
153 mode = QTextCursor::KeepAnchor;
155 else if (e == QKeySequence::SelectPreviousLine) {
156 op = QTextCursor::Up;
157 mode = QTextCursor::KeepAnchor;
159 else if (e == QKeySequence::SelectNextLine) {
160 op = QTextCursor::Down;
161 mode = QTextCursor::KeepAnchor;
163 QTextBlock block = cursor.block();
164 QTextLine line = currentTextLine(cursor);
165 if (!block.next().isValid()
167 && line.lineNumber() == block.layout()->lineCount() - 1)
168 op = QTextCursor::End;
171 else if (e == QKeySequence::MoveToNextWord) {
172 op = QTextCursor::WordRight;
174 else if (e == QKeySequence::MoveToPreviousWord) {
175 op = QTextCursor::WordLeft;
177 else if (e == QKeySequence::MoveToEndOfBlock) {
178 op = QTextCursor::EndOfBlock;
180 else if (e == QKeySequence::MoveToStartOfBlock) {
181 op = QTextCursor::StartOfBlock;
183 else if (e == QKeySequence::MoveToNextLine) {
184 op = QTextCursor::Down;
186 else if (e == QKeySequence::MoveToPreviousLine) {
187 op = QTextCursor::Up;
189 else if (e == QKeySequence::MoveToStartOfLine) {
190 op = QTextCursor::StartOfLine;
192 else if (e == QKeySequence::MoveToEndOfLine) {
193 op = QTextCursor::EndOfLine;
195 else if (e == QKeySequence::MoveToStartOfDocument) {
196 op = QTextCursor::Start;
198 else if (e == QKeySequence::MoveToEndOfDocument) {
199 op = QTextCursor::End;
216 bool visualNavigation = cursor.visualNavigation();
217 cursor.setVisualNavigation(
true);
218 const bool moved = cursor.movePosition(op, mode);
219 cursor.setVisualNavigation(visualNavigation);
221 bool isNavigationEvent
222 = e->key() == Qt::Key_Up
223 || e->key() == Qt::Key_Down
224 || e->key() == Qt::Key_Left
225 || e->key() == Qt::Key_Right;
228 if (cursor.position() != oldCursorPos)
229 emit q->cursorPositionChanged();
230 q->updateCursorRectangle(
true);
231 }
else if (isNavigationEvent && oldSelection.anchor() == cursor.anchor()) {
235 selectionChanged((mode == QTextCursor::KeepAnchor));
237 repaintOldAndNewSelection(oldSelection);
244 Q_Q(QQuickTextControl);
246 QTextCharFormat fmt = cursor.charFormat();
247 if (fmt == lastCharFormat)
249 lastCharFormat = fmt;
251 emit q->currentCharFormatChanged(fmt);
257 Q_Q(QQuickTextControl);
265 const QTextCharFormat charFormatForInsertion = cursor.charFormat();
267 bool previousUndoRedoState =
doc->isUndoRedoEnabled();
268 doc->setUndoRedoEnabled(
false);
270 const int oldCursorPos = cursor.position();
273 QObject::disconnect(doc, &QTextDocument::contentsChanged, q, &QQuickTextControl::textChanged);
275 if (!text.isEmpty()) {
282 cursor = QTextCursor();
283 if (format == Qt::PlainText) {
284 QTextCursor formatCursor(doc);
288 formatCursor.beginEditBlock();
289 doc->setPlainText(text);
290 doc->setUndoRedoEnabled(
false);
291 formatCursor.select(QTextCursor::Document);
292 formatCursor.setCharFormat(charFormatForInsertion);
293 formatCursor.endEditBlock();
294#if QT_CONFIG(textmarkdownreader)
295 }
else if (format == Qt::MarkdownText) {
296 doc->setBaseUrl(doc->baseUrl().adjusted(QUrl::RemoveFilename));
297 doc->setMarkdown(text);
300#if QT_CONFIG(texthtmlparser)
303 doc->setPlainText(text);
305 doc->setUndoRedoEnabled(
false);
307 cursor = QTextCursor(doc);
311 cursor.setCharFormat(charFormatForInsertion);
313 QObject::connect(doc, &QTextDocument::contentsChanged, q, &QQuickTextControl::textChanged);
314 emit q->textChanged();
315 doc->setUndoRedoEnabled(previousUndoRedoState);
317 doc->setModified(
false);
319 q->updateCursorRectangle(
true);
320 if (cursor.position() != oldCursorPos)
321 emit q->cursorPositionChanged();
326 Q_Q(QQuickTextControl);
327 const int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
330 cursor.setPosition(cursorPos);
335 cursor.setPosition(pos, mode);
337 if (mode != QTextCursor::KeepAnchor) {
338 selectedWordOnDoubleClick = QTextCursor();
339 selectedBlockOnTripleClick = QTextCursor();
345 Q_Q(QQuickTextControl);
346 emit q->updateCursorRequest();
351 Q_Q(QQuickTextControl);
352 if (cursor.hasSelection()
353 && oldSelection.hasSelection()
354 && cursor.currentFrame() == oldSelection.currentFrame()
355 && !cursor.hasComplexSelection()
356 && !oldSelection.hasComplexSelection()
357 && cursor.anchor() == oldSelection.anchor()
359 QTextCursor differenceSelection(doc);
360 differenceSelection.setPosition(oldSelection.position());
361 differenceSelection.setPosition(cursor.position(), QTextCursor::KeepAnchor);
362 emit q->updateRequest();
364 if (!oldSelection.hasSelection() && !cursor.hasSelection()) {
365 if (!oldSelection.isNull())
366 emit q->updateCursorRequest();
367 emit q->updateCursorRequest();
370 if (!oldSelection.isNull())
371 emit q->updateRequest();
372 emit q->updateRequest();
379 Q_Q(QQuickTextControl);
380 if (forceEmitSelectionChanged) {
383 qGuiApp->inputMethod()->update(Qt::ImCurrentSelection);
385 emit q->selectionChanged();
388 bool current = cursor.hasSelection();
389 int selectionStart = cursor.selectionStart();
390 int selectionEnd = cursor.selectionEnd();
396 emit q->copyAvailable(current);
402 if (!forceEmitSelectionChanged) {
405 qGuiApp->inputMethod()->update(Qt::ImCurrentSelection);
407 emit q->selectionChanged();
409 q->updateCursorRectangle(
true);
418#if QT_CONFIG(clipboard)
419void QQuickTextControlPrivate::setClipboardSelection()
421 QClipboard *clipboard = QGuiApplication::clipboard();
422 if (!cursor.hasSelection() || !clipboard->supportsSelection())
424 Q_Q(QQuickTextControl);
425 QMimeData *data = q->createMimeDataFromSelection();
426 clipboard->setMimeData(data, QClipboard::Selection);
432 Q_Q(QQuickTextControl);
433 if (someCursor.isCopyOf(cursor)) {
434 emit q->cursorPositionChanged();
435 q->updateCursorRectangle(
true);
448 connect(
qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged,
this, &QQuickTextControlPrivate::updateCursorFlashTime);
450 disconnect(
qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged,
this, &QQuickTextControlPrivate::updateCursorFlashTime);
459 int flashTime = QGuiApplication::styleHints()->cursorFlashTime();
461 if (cursorBlinkingEnabled && flashTime >= 2)
462 cursorBlinkTimer.start(flashTime / 2, q_func());
464 cursorBlinkTimer.stop();
471 Q_Q(QQuickTextControl);
474 if (suggestedNewPosition >= selectedWordOnDoubleClick.selectionStart()
475 && suggestedNewPosition <= selectedWordOnDoubleClick.selectionEnd()) {
476 q->setTextCursor(selectedWordOnDoubleClick);
480 QTextCursor curs = selectedWordOnDoubleClick;
481 curs.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
483 if (!curs.movePosition(QTextCursor::StartOfWord))
485 const int wordStartPos = curs.position();
487 const int blockPos = curs.block().position();
488 const QPointF blockCoordinates = q->blockBoundingRect(curs.block()).topLeft();
490 QTextLine line = currentTextLine(curs);
494 const qreal wordStartX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x();
496 if (!curs.movePosition(QTextCursor::EndOfWord))
498 const int wordEndPos = curs.position();
500 const QTextLine otherLine = currentTextLine(curs);
501 if (otherLine.textStart() != line.textStart()
502 || wordEndPos == wordStartPos)
505 const qreal wordEndX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x();
510 if (suggestedNewPosition < selectedWordOnDoubleClick.position()) {
511 cursor.setPosition(selectedWordOnDoubleClick.selectionEnd());
512 setCursorPosition(wordStartPos, QTextCursor::KeepAnchor);
514 cursor.setPosition(selectedWordOnDoubleClick.selectionStart());
515 setCursorPosition(wordEndPos, QTextCursor::KeepAnchor);
518 if (interactionFlags & Qt::TextSelectableByMouse) {
519#if QT_CONFIG(clipboard)
520 setClipboardSelection();
528 Q_Q(QQuickTextControl);
531 if (suggestedNewPosition >= selectedBlockOnTripleClick.selectionStart()
532 && suggestedNewPosition <= selectedBlockOnTripleClick.selectionEnd()) {
533 q->setTextCursor(selectedBlockOnTripleClick);
537 if (suggestedNewPosition < selectedBlockOnTripleClick.position()) {
538 cursor.setPosition(selectedBlockOnTripleClick.selectionEnd());
539 cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
540 cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
542 cursor.setPosition(selectedBlockOnTripleClick.selectionStart());
543 cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
544 cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
545 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
548 if (interactionFlags & Qt::TextSelectableByMouse) {
549#if QT_CONFIG(clipboard)
550 setClipboardSelection();
556void QQuickTextControl::undo()
558 Q_D(QQuickTextControl);
559 d->repaintSelection();
560 const int oldCursorPos = d->cursor.position();
561 d->doc->undo(&d->cursor);
562 if (d->cursor.position() != oldCursorPos)
563 emit cursorPositionChanged();
564 updateCursorRectangle(
true);
567void QQuickTextControl::redo()
569 Q_D(QQuickTextControl);
570 d->repaintSelection();
571 const int oldCursorPos = d->cursor.position();
572 d->doc->redo(&d->cursor);
573 if (d->cursor.position() != oldCursorPos)
574 emit cursorPositionChanged();
575 updateCursorRectangle(
true);
578void QQuickTextControl::clear()
580 Q_D(QQuickTextControl);
581 d->cursor.select(QTextCursor::Document);
582 d->cursor.removeSelectedText();
585QQuickTextControl::QQuickTextControl(QTextDocument *doc, QObject *parent)
586 : QInputControl(TextEdit, *
new QQuickTextControlPrivate, parent)
591QQuickTextControl::~QQuickTextControl()
595QTextDocument *QQuickTextControl::document()
const
597 Q_D(
const QQuickTextControl);
601void QQuickTextControl::setDocument(QTextDocument *doc)
603 Q_D(QQuickTextControl);
604 if (!doc || d->doc == doc)
608 QAbstractTextDocumentLayout *oldLayout = d->doc->documentLayout();
609 disconnect(oldLayout,
nullptr,
this,
nullptr);
610 disconnect(d->doc,
nullptr,
this,
nullptr);
614 d->cursor = QTextCursor(doc);
615 d->lastCharFormat = d->cursor.charFormat();
617 QAbstractTextDocumentLayout *layout = doc->documentLayout();
618 connect(layout, &QAbstractTextDocumentLayout::update,
this, &QQuickTextControl::updateRequest);
619 connect(layout, &QAbstractTextDocumentLayout::updateBlock,
this, &QQuickTextControl::updateRequest);
620 connect(doc, &QTextDocument::contentsChanged,
this, [d]() {
621 d->_q_updateCurrentCharFormatAndSelection();
623 connect(doc, &QTextDocument::contentsChanged,
this, &QQuickTextControl::textChanged);
624 connect(doc, &QTextDocument::cursorPositionChanged,
this, [d](
const QTextCursor &cursor) {
625 d->_q_updateCursorPosChanged(cursor);
627 connect(doc, &QTextDocument::contentsChange,
this, &QQuickTextControl::contentsChange);
628 if (
auto *qtdlayout = qobject_cast<QTextDocumentLayout *>(layout))
629 qtdlayout->setCursorWidth(textCursorWidth);
632void QQuickTextControl::updateCursorRectangle(
bool force)
634 Q_D(QQuickTextControl);
635 const bool update = d->cursorRectangleChanged || force;
636 d->cursorRectangleChanged =
false;
638 emit cursorRectangleChanged();
641void QQuickTextControl::setTextCursor(
const QTextCursor &cursor)
643 Q_D(QQuickTextControl);
647 d->cursorIsFocusIndicator =
false;
648 const bool posChanged = cursor.position() != d->cursor.position();
649 const QTextCursor oldSelection = d->cursor;
651 d->cursorOn = d->hasFocus && (d->interactionFlags & Qt::TextEditable);
652 d->_q_updateCurrentCharFormatAndSelection();
653 updateCursorRectangle(
true);
654 d->repaintOldAndNewSelection(oldSelection);
656 emit cursorPositionChanged();
659QTextCursor QQuickTextControl::textCursor()
const
661 Q_D(
const QQuickTextControl);
665#if QT_CONFIG(clipboard)
667void QQuickTextControl::cut()
669 Q_D(QQuickTextControl);
670 if (!(d->interactionFlags & Qt::TextEditable) || !d->cursor.hasSelection())
673 d->cursor.removeSelectedText();
676void QQuickTextControl::copy()
678 Q_D(QQuickTextControl);
679 if (!d->cursor.hasSelection())
681 QMimeData *data = createMimeDataFromSelection();
682 QGuiApplication::clipboard()->setMimeData(data);
685void QQuickTextControl::paste(QClipboard::Mode mode)
687 const QMimeData *md = QGuiApplication::clipboard()->mimeData(mode);
689 insertFromMimeData(md);
693void QQuickTextControl::selectAll()
695 Q_D(QQuickTextControl);
696 const int selectionLength = qAbs(d->cursor.position() - d->cursor.anchor());
697 d->cursor.select(QTextCursor::Document);
698 d->selectionChanged(selectionLength != qAbs(d->cursor.position() - d->cursor.anchor()));
699 d->cursorIsFocusIndicator =
false;
700 emit updateRequest();
703void QQuickTextControl::processEvent(QEvent *e,
const QPointF &coordinateOffset)
706 t.translate(coordinateOffset.x(), coordinateOffset.y());
710void QQuickTextControl::processEvent(QEvent *e,
const QTransform &transform)
712 Q_D(QQuickTextControl);
713 if (d->interactionFlags == Qt::NoTextInteraction) {
719 case QEvent::KeyPress:
720 d->keyPressEvent(
static_cast<QKeyEvent *>(e));
722 case QEvent::KeyRelease:
723 d->keyReleaseEvent(
static_cast<QKeyEvent *>(e));
725 case QEvent::MouseButtonPress: {
726 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
727 d->mousePressEvent(ev, transform.map(ev->position()));
729 case QEvent::MouseMove: {
730 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
731 d->mouseMoveEvent(ev, transform.map(ev->position()));
733 case QEvent::MouseButtonRelease: {
734 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
735 d->mouseReleaseEvent(ev, transform.map(ev->position()));
737 case QEvent::MouseButtonDblClick: {
738 QMouseEvent *ev =
static_cast<QMouseEvent *>(e);
739 d->mouseDoubleClickEvent(ev, transform.map(ev->position()));
741 case QEvent::HoverEnter:
742 case QEvent::HoverMove:
743 case QEvent::HoverLeave: {
744 QHoverEvent *ev =
static_cast<QHoverEvent *>(e);
745 d->hoverEvent(ev, transform.map(ev->position()));
748 case QEvent::InputMethod:
749 d->inputMethodEvent(
static_cast<QInputMethodEvent *>(e));
752 case QEvent::FocusIn:
753 case QEvent::FocusOut:
754 d->focusEvent(
static_cast<QFocusEvent *>(e));
757 case QEvent::ShortcutOverride:
758 if (d->interactionFlags & Qt::TextEditable) {
759 QKeyEvent *ke =
static_cast<QKeyEvent *>(e);
760 ke->setAccepted(isCommonTextEditShortcut(ke));
768bool QQuickTextControl::event(QEvent *e)
770 return QObject::event(e);
773bool QQuickTextControl::isBeingEdited()
775 Q_D(QQuickTextControl);
776 return d->beingEdited;
779void QQuickTextControl::timerEvent(QTimerEvent *e)
781 Q_D(QQuickTextControl);
782 if (e->timerId() == d->cursorBlinkTimer.timerId()) {
783 d->cursorOn = !d->cursorOn;
789void QQuickTextControl::setPlainText(
const QString &text)
791 Q_D(QQuickTextControl);
792 d->setContent(Qt::PlainText, text);
795void QQuickTextControl::setMarkdownText(
const QString &text)
797 Q_D(QQuickTextControl);
798 d->setContent(Qt::MarkdownText, text);
801void QQuickTextControl::setHtml(
const QString &text)
803 Q_D(QQuickTextControl);
804 d->setContent(Qt::RichText, text);
815 Q_Q(QQuickTextControl);
817 QScopedValueRollback<
bool> rollbackBeingEdited(beingEdited,
true);
818 if (e->key() == Qt::Key_Back) {
823#if QT_CONFIG(shortcut)
824 if (e == QKeySequence::SelectAll) {
827#if QT_CONFIG(clipboard)
828 setClipboardSelection();
832#if QT_CONFIG(clipboard)
833 else if (e == QKeySequence::Copy) {
841 if (interactionFlags & Qt::TextSelectableByKeyboard
842 && cursorMoveKeyEvent(e))
845 if (!(interactionFlags & Qt::TextEditable)) {
850 if (e->key() == Qt::Key_Direction_L || e->key() == Qt::Key_Direction_R) {
851 QTextBlockFormat fmt;
852 fmt.setLayoutDirection((e->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
853 cursor.mergeBlockFormat(fmt);
863 if (e->key() == Qt::Key_Backspace && !(e->modifiers() & ~Qt::ShiftModifier)) {
864 QTextBlockFormat blockFmt = cursor.blockFormat();
865 QTextList *list = cursor.currentList();
866 if (list && cursor.atBlockStart() && !cursor.hasSelection()) {
867 list->remove(cursor.block());
868 }
else if (cursor.atBlockStart() && blockFmt.indent() > 0) {
869 blockFmt.setIndent(blockFmt.indent() - 1);
870 cursor.setBlockFormat(blockFmt);
872 QTextCursor localCursor = cursor;
873 localCursor.deletePreviousChar();
877#if QT_CONFIG(shortcut)
878 else if (e == QKeySequence::InsertParagraphSeparator) {
879 cursor.insertBlock();
882 }
else if (e == QKeySequence::InsertLineSeparator) {
883 cursor.insertText(QString(QChar::LineSeparator));
890#if QT_CONFIG(shortcut)
891 else if (e == QKeySequence::Undo) {
894 else if (e == QKeySequence::Redo) {
897#if QT_CONFIG(clipboard)
898 else if (e == QKeySequence::Cut) {
901 else if (e == QKeySequence::Paste) {
902 QClipboard::Mode mode = QClipboard::Clipboard;
906 else if (e == QKeySequence::Delete) {
907 QTextCursor localCursor = cursor;
908 localCursor.deleteChar();
910 else if (e == QKeySequence::DeleteEndOfWord) {
911 if (!cursor.hasSelection())
912 cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor);
913 cursor.removeSelectedText();
915 else if (e == QKeySequence::DeleteStartOfWord) {
916 const int oldCursorPos = cursor.position();
917 if (!cursor.hasSelection())
918 cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor);
919 cursor.removeSelectedText();
920 if (cursor.position() != oldCursorPos)
921 emit q->cursorPositionChanged();
923 else if (e == QKeySequence::DeleteEndOfLine) {
924 QTextBlock block = cursor.block();
925 if (cursor.position() == block.position() + block.length() - 2)
926 cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
928 cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
929 cursor.removeSelectedText();
939 if (q->isAcceptableInput(e)) {
949 && !cursor.hasSelection()
950 && !cursor.atBlockEnd()) {
954 cursor.insertText(e->text());
964#if QT_CONFIG(clipboard)
965 setClipboardSelection();
971 q->updateCursorRectangle(
true);
972 updateCurrentCharFormat();
977 Q_Q(
const QQuickTextControl);
978 const QTextBlock block = doc->findBlock(position);
979 if (!block.isValid())
981 const QTextLayout *layout = block.layout();
982 const QPointF layoutPos = q->blockBoundingRect(block).topLeft();
983 int relativePos = position - block.position();
985 if (preeditCursor != 0) {
986 int preeditPos = layout->preeditAreaPosition();
987 if (relativePos == preeditPos)
988 relativePos += preeditCursor;
989 else if (relativePos > preeditPos)
990 relativePos += layout->preeditAreaText().size();
993 QTextLine line = layout->lineForTextPosition(relativePos);
997 if (line.isValid()) {
998 qreal x = line.cursorToX(relativePos);
1001 if (relativePos < line.textLength() - line.textStart())
1002 w = line.cursorToX(relativePos + 1) - x;
1004 w = QFontMetrics(block.layout()->font()).horizontalAdvance(QLatin1Char(
' '));
1006 r = QRectF(layoutPos.x() + x, layoutPos.y() + line.y(), textCursorWidth + w, line.height());
1008 r = QRectF(layoutPos.x(), layoutPos.y(), textCursorWidth, 10);
1016 Q_Q(QQuickTextControl);
1018 mousePressed = (interactionFlags & Qt::TextSelectableByMouse) && (e->button() & Qt::LeftButton);
1019 mousePressPos = pos.toPoint();
1022 if (sendMouseEventToInputContext(e, pos))
1025 if (interactionFlags & Qt::LinksAccessibleByMouse) {
1026 anchorOnMousePress = q->anchorAt(pos);
1031 cursor.clearSelection();
1035 if (!selectByTouchDrag && !QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(e))
1037 if (interactionFlags & Qt::TextEditable)
1038 blockWithMarkerUnderMousePress = q->blockWithMarkerAt(pos);
1039 if (e->button() & Qt::MiddleButton) {
1041 }
else if (!(e->button() & Qt::LeftButton)) {
1044 }
else if (!(interactionFlags & (Qt::TextSelectableByMouse | Qt::TextEditable))) {
1045 if (!(interactionFlags & Qt::LinksAccessibleByMouse))
1051 const QTextCursor oldSelection = cursor;
1052 const int oldCursorPos = cursor.position();
1058 if ((e->timestamp() < (timestampAtLastDoubleClick + QGuiApplication::styleHints()->mouseDoubleClickInterval()))
1059 && ((pos - tripleClickPoint).toPoint().manhattanLength() < QGuiApplication::styleHints()->startDragDistance())) {
1061 cursor.movePosition(QTextCursor::StartOfBlock);
1062 cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
1063 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
1064 selectedBlockOnTripleClick = cursor;
1066 anchorOnMousePress = QString();
1068 timestampAtLastDoubleClick = 0;
1070 int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
1071 if (cursorPos == -1) {
1076 if (e->modifiers() == Qt::ShiftModifier && (interactionFlags & Qt::TextSelectableByMouse)) {
1077 if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) {
1078 selectedWordOnDoubleClick = cursor;
1079 selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor);
1082 if (selectedBlockOnTripleClick.hasSelection())
1084 else if (selectedWordOnDoubleClick.hasSelection())
1085 extendWordwiseSelection(cursorPos, pos.x());
1086 else if (!wordSelectionEnabled)
1087 setCursorPosition(cursorPos, QTextCursor::KeepAnchor);
1089 setCursorPosition(cursorPos);
1093 if (cursor.position() != oldCursorPos) {
1094 q->updateCursorRectangle(
true);
1095 emit q->cursorPositionChanged();
1097 if (interactionFlags & Qt::TextEditable)
1101 repaintOldAndNewSelection(oldSelection);
1102 hadSelectionOnMousePress = cursor.hasSelection();
1107 if (!selectByTouchDrag && !QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(e))
1110 Q_Q(QQuickTextControl);
1112 if ((e->buttons() & Qt::LeftButton)) {
1113 const bool editable = interactionFlags & Qt::TextEditable;
1117 || selectedWordOnDoubleClick.hasSelection()
1118 || selectedBlockOnTripleClick.hasSelection()))
1121 const QTextCursor oldSelection = cursor;
1122 const int oldCursorPos = cursor.position();
1127 const qreal mouseX = qreal(mousePos.x());
1129 int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1132 if (isPreediting()) {
1134 int selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1135 if (newCursorPos != selectionStartPos) {
1138 newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1139 selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1140 setCursorPosition(selectionStartPos);
1145 if (newCursorPos == -1)
1148 if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) {
1149 selectedWordOnDoubleClick = cursor;
1150 selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor);
1153 if (selectedBlockOnTripleClick.hasSelection())
1155 else if (selectedWordOnDoubleClick.hasSelection())
1156 extendWordwiseSelection(newCursorPos, mouseX);
1158 else if (!isPreediting())
1159 setCursorPosition(newCursorPos, QTextCursor::KeepAnchor);
1162 if (interactionFlags & Qt::TextEditable) {
1163 if (cursor.position() != oldCursorPos) {
1164 emit q->cursorPositionChanged();
1169 qGuiApp->inputMethod()->update(Qt::ImQueryInput);
1171 }
else if (cursor.position() != oldCursorPos) {
1172 emit q->cursorPositionChanged();
1175 repaintOldAndNewSelection(oldSelection);
1178 sendMouseEventToInputContext(e, mousePos);
1183 Q_Q(QQuickTextControl);
1185 if (sendMouseEventToInputContext(e, pos))
1188 const QTextCursor oldSelection = cursor;
1189 const int oldCursorPos = cursor.position();
1190 const bool isMouse = QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(e);
1194#if QT_CONFIG(clipboard)
1195 setClipboardSelection();
1196 selectionChanged(
true);
1197 }
else if (e->button() == Qt::MiddleButton
1198 && (interactionFlags & Qt::TextEditable)
1199 && QGuiApplication::clipboard()->supportsSelection()) {
1200 setCursorPosition(pos);
1201 const QMimeData *md = QGuiApplication::clipboard()->mimeData(QClipboard::Selection);
1203 q->insertFromMimeData(md);
1206 if (!isMouse && !selectByTouchDrag && !imSelectionAfterPress && interactionFlags.testFlag(Qt::TextEditable))
1207 setCursorPosition(pos);
1209 repaintOldAndNewSelection(oldSelection);
1211 if (cursor.position() != oldCursorPos) {
1212 emit q->cursorPositionChanged();
1213 q->updateCursorRectangle(
true);
1216 if ((isMouse || selectByTouchDrag) && interactionFlags.testFlag(Qt::TextEditable) &&
1217 (e->button() & Qt::LeftButton) && blockWithMarkerUnderMousePress.isValid()) {
1218 QTextBlock block = q->blockWithMarkerAt(pos);
1219 if (block == blockWithMarkerUnderMousePress) {
1220 auto fmt = block.blockFormat();
1221 fmt.setMarker(fmt.marker() == QTextBlockFormat::MarkerType::Unchecked ?
1222 QTextBlockFormat::MarkerType::Checked : QTextBlockFormat::MarkerType::Unchecked);
1223 cursor.setBlockFormat(fmt);
1227 if (interactionFlags & Qt::LinksAccessibleByMouse) {
1228 if (!(e->button() & Qt::LeftButton))
1231 const QString anchor = q->anchorAt(pos);
1233 if (anchor.isEmpty())
1236 if (!cursor.hasSelection()
1237 || (anchor == anchorOnMousePress && hadSelectionOnMousePress)) {
1239 const int anchorPos = q->hitTest(pos, Qt::ExactHit);
1240 if (anchorPos != -1) {
1241 cursor.setPosition(anchorPos);
1243 QString anchor = anchorOnMousePress;
1244 anchorOnMousePress = QString();
1245 activateLinkUnderCursor(anchor);
1253 Q_Q(QQuickTextControl);
1255 if (e->button() == Qt::LeftButton && (interactionFlags & Qt::TextSelectableByMouse)
1256 && (selectByTouchDrag || QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(e))) {
1261 const QTextCursor oldSelection = cursor;
1262 setCursorPosition(pos);
1263 QTextLine line = currentTextLine(cursor);
1264 bool doEmit =
false;
1265 if (line.isValid() && line.textLength()) {
1266 cursor.select(QTextCursor::WordUnderCursor);
1269 repaintOldAndNewSelection(oldSelection);
1272 selectedWordOnDoubleClick = cursor;
1274 tripleClickPoint = pos;
1275 timestampAtLastDoubleClick = e->timestamp();
1278#if QT_CONFIG(clipboard)
1279 setClipboardSelection();
1281 emit q->cursorPositionChanged();
1282 q->updateCursorRectangle(
true);
1284 }
else if (!sendMouseEventToInputContext(e, pos)) {
1292 Q_Q(QQuickTextControl);
1296 if (isPreediting()) {
1297 QTextLayout *layout = cursor.block().layout();
1298 int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position();
1300 if (cursorPos >= 0 && cursorPos <= layout->preeditAreaText().size()) {
1301 if (e->type() == QEvent::MouseButtonRelease) {
1302 QGuiApplication::inputMethod()->invokeAction(QInputMethod::Click, cursorPos);
1316void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
1318 Q_Q(QQuickTextControl);
1319 if (cursor.isNull()) {
1323 bool textEditable = interactionFlags.testFlag(Qt::TextEditable);
1324 bool isGettingInput = !e->commitString().isEmpty()
1325 || e->preeditString() != cursor.block().layout()->preeditAreaText()
1326 || e->replacementLength() > 0;
1327 bool forceSelectionChanged =
false;
1328 int oldCursorPos = cursor.position();
1330 cursor.beginEditBlock();
1331 if (isGettingInput && textEditable) {
1332 cursor.removeSelectedText();
1338 if (textEditable && (!e->commitString().isEmpty() || e->replacementLength())) {
1339 auto *mimeData = QInputControl::mimeDataForInputEvent(e);
1340 if (mimeData && q->canInsertFromMimeData(mimeData)) {
1341 q->insertFromMimeData(mimeData);
1343 if (e->commitString().endsWith(QChar::LineFeed))
1344 block = cursor.block();
1345 QTextCursor c = cursor;
1346 c.setPosition(c.position() + e->replacementStart());
1347 c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor);
1348 c.insertText(e->commitString());
1352 if (interactionFlags & (Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse)) {
1353 for (
int i = 0; i < e->attributes().size(); ++i) {
1354 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
1355 if (a.type == QInputMethodEvent::Selection) {
1357 imSelectionAfterPress =
true;
1358 QTextCursor oldCursor = cursor;
1359 int blockStart = a.start + cursor.block().position();
1360 cursor.setPosition(blockStart, QTextCursor::MoveAnchor);
1361 cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
1362 repaintOldAndNewSelection(oldCursor);
1363 forceSelectionChanged =
true;
1368 if (!block.isValid())
1369 block = cursor.block();
1371 const int oldPreeditCursor = preeditCursor;
1373 QTextLayout *layout = block.layout();
1374 if (isGettingInput) {
1375 layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
1376 emit q->preeditTextChanged();
1378 QVector<QTextLayout::FormatRange> overrides;
1379 preeditCursor = e->preeditString().size();
1380 hasImState = !e->preeditString().isEmpty();
1381 cursorVisible =
true;
1382 for (
int i = 0; i < e->attributes().size(); ++i) {
1383 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
1384 if (a.type == QInputMethodEvent::Cursor) {
1386 preeditCursor = a.start;
1387 cursorVisible = a.length != 0;
1388 }
else if (a.type == QInputMethodEvent::TextFormat) {
1390 QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
1392 QTextLayout::FormatRange o;
1393 o.start = a.start + cursor.position() - block.position();
1394 o.length = a.length;
1396 overrides.append(o);
1400 layout->setFormats(overrides);
1403 cursor.endEditBlock();
1405 QTextCursorPrivate *cursor_d = QTextCursorPrivate::getPrivate(&cursor);
1408 if (cursor.position() != oldCursorPos)
1409 emit q->cursorPositionChanged();
1410 q->updateCursorRectangle(oldPreeditCursor != preeditCursor || forceSelectionChanged || isGettingInput);
1411 selectionChanged(forceSelectionChanged);
1414QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property)
const
1416 return inputMethodQuery(property, QVariant());
1419QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property,
const QVariant &argument)
const
1421 Q_D(
const QQuickTextControl);
1422 QTextBlock block = d->cursor.block();
1424 case Qt::ImCursorRectangle:
1425 return cursorRect();
1426 case Qt::ImAnchorRectangle:
1427 return anchorRect();
1429 return QVariant(d->cursor.charFormat().font());
1430 case Qt::ImCursorPosition: {
1431 const QPointF pt = argument.toPointF();
1433 return QVariant(d->doc->documentLayout()->hitTest(pt, Qt::FuzzyHit) - block.position());
1434 return QVariant(d->cursor.position() - block.position());
1436 case Qt::ImSurroundingText:
1437 return QVariant(block.text());
1438 case Qt::ImCurrentSelection: {
1439 QMimeData *mimeData = createMimeDataFromSelection();
1440 mimeData->deleteLater();
1441 return QInputControl::selectionWrapper(mimeData);
1443 case Qt::ImMaximumTextLength:
1445 case Qt::ImAnchorPosition:
1446 return QVariant(d->cursor.anchor() - block.position());
1447 case Qt::ImAbsolutePosition:
1448 return QVariant(d->cursor.position());
1449 case Qt::ImTextAfterCursor:
1451 int maxLength = argument.isValid() ? argument.toInt() : 1024;
1452 QTextCursor tmpCursor = d->cursor;
1453 int localPos = d->cursor.position() - block.position();
1454 QString result = block.text().mid(localPos);
1455 while (result.size() < maxLength) {
1456 int currentBlock = tmpCursor.blockNumber();
1457 tmpCursor.movePosition(QTextCursor::NextBlock);
1458 if (tmpCursor.blockNumber() == currentBlock)
1460 result += QLatin1Char(
'\n') + tmpCursor.block().text();
1462 return QVariant(result);
1464 case Qt::ImTextBeforeCursor:
1466 int maxLength = argument.isValid() ? argument.toInt() : 1024;
1467 QTextCursor tmpCursor = d->cursor;
1468 int localPos = d->cursor.position() - block.position();
1470 int resultLen = localPos;
1471 while (resultLen < maxLength) {
1472 int currentBlock = tmpCursor.blockNumber();
1473 tmpCursor.movePosition(QTextCursor::PreviousBlock);
1474 if (tmpCursor.blockNumber() == currentBlock)
1477 resultLen += tmpCursor.block().length();
1481 result += tmpCursor.block().text() + QLatin1Char(
'\n');
1482 tmpCursor.movePosition(QTextCursor::NextBlock);
1485 result += QStringView{block.text()}.mid(0,localPos);
1486 return QVariant(result);
1488 case Qt::ImReadOnly:
1489 return QVariant(!d->interactionFlags.testFlag(Qt::TextEditable));
1498 Q_Q(QQuickTextControl);
1499 emit q->updateRequest();
1500 hasFocus = e->gotFocus();
1501 if (e->gotFocus()) {
1502 setBlinkingCursorEnabled(interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard));
1504 setBlinkingCursorEnabled(
false);
1506 if (cursorIsFocusIndicator
1507 && e->reason() != Qt::ActiveWindowFocusReason
1508 && e->reason() != Qt::PopupFocusReason
1509 && cursor.hasSelection()) {
1510 cursor.clearSelection();
1511 emit q->selectionChanged();
1518 Q_Q(QQuickTextControl);
1521 if (e->type() != QEvent::HoverLeave)
1522 link = q->anchorAt(pos);
1524 if (hoveredLink != link) {
1526 emit q->linkHovered(link);
1527 qCDebug(lcHoverTrace) << q << e->type() << pos <<
"hoveredLink" << hoveredLink;
1529 QTextBlock block = q->blockWithMarkerAt(pos);
1530 if (block.isValid() != hoveredMarker)
1531 emit q->markerHovered(block.isValid());
1532 hoveredMarker = block.isValid();
1534 qCDebug(lcHoverTrace) << q << e->type() << pos <<
"hovered marker" <<
int(block.blockFormat().marker()) << block.text();
1538bool QQuickTextControl::hasImState()
const
1540 Q_D(
const QQuickTextControl);
1541 return d->hasImState;
1544bool QQuickTextControl::overwriteMode()
const
1546 Q_D(
const QQuickTextControl);
1547 return d->overwriteMode;
1550void QQuickTextControl::setOverwriteMode(
bool overwrite)
1552 Q_D(QQuickTextControl);
1553 if (d->overwriteMode == overwrite)
1555 d->overwriteMode = overwrite;
1556 emit overwriteModeChanged(overwrite);
1559bool QQuickTextControl::cursorVisible()
const
1561 Q_D(
const QQuickTextControl);
1562 return d->cursorVisible;
1565void QQuickTextControl::setCursorVisible(
bool visible)
1567 Q_D(QQuickTextControl);
1568 d->cursorVisible = visible;
1569 d->setBlinkingCursorEnabled(d->cursorVisible
1570 && (d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard)));
1573QRectF QQuickTextControl::anchorRect()
const
1575 Q_D(
const QQuickTextControl);
1577 QTextCursor cursor = d->cursor;
1578 if (!cursor.isNull()) {
1579 rect = d->rectForPosition(cursor.anchor());
1584QRectF QQuickTextControl::cursorRect(
const QTextCursor &cursor)
const
1586 Q_D(
const QQuickTextControl);
1587 if (cursor.isNull())
1590 return d->rectForPosition(cursor.position());
1593QRectF QQuickTextControl::cursorRect()
const
1595 Q_D(
const QQuickTextControl);
1596 return cursorRect(d->cursor);
1599QString QQuickTextControl::hoveredLink()
const
1601 Q_D(
const QQuickTextControl);
1602 return d->hoveredLink;
1605QString QQuickTextControl::anchorAt(
const QPointF &pos)
const
1607 Q_D(
const QQuickTextControl);
1608 return d->doc->documentLayout()->anchorAt(pos);
1611QTextBlock QQuickTextControl::blockWithMarkerAt(
const QPointF &pos)
const
1613 Q_D(
const QQuickTextControl);
1614 return d->doc->documentLayout()->blockWithMarkerAt(pos);
1617void QQuickTextControl::setAcceptRichText(
bool accept)
1619 Q_D(QQuickTextControl);
1620 d->acceptRichText = accept;
1623void QQuickTextControl::moveCursor(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode)
1625 Q_D(QQuickTextControl);
1626 const QTextCursor oldSelection = d->cursor;
1627 const bool moved = d->cursor.movePosition(op, mode);
1628 d->_q_updateCurrentCharFormatAndSelection();
1629 updateCursorRectangle(
true);
1630 d->repaintOldAndNewSelection(oldSelection);
1632 emit cursorPositionChanged();
1635bool QQuickTextControl::canPaste()
const
1637#if QT_CONFIG(clipboard)
1638 Q_D(
const QQuickTextControl);
1639 if (d->interactionFlags & Qt::TextEditable) {
1640 const QMimeData *md = QGuiApplication::clipboard()->mimeData();
1641 return md && canInsertFromMimeData(md);
1647void QQuickTextControl::setCursorIsFocusIndicator(
bool b)
1649 Q_D(QQuickTextControl);
1650 d->cursorIsFocusIndicator = b;
1654void QQuickTextControl::setWordSelectionEnabled(
bool enabled)
1656 Q_D(QQuickTextControl);
1657 d->wordSelectionEnabled = enabled;
1660#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
1661void QQuickTextControl::setTouchDragSelectionEnabled(
bool enabled)
1663 Q_D(QQuickTextControl);
1664 d->selectByTouchDrag = enabled;
1668QMimeData *QQuickTextControl::createMimeDataFromSelection()
const
1670 Q_D(
const QQuickTextControl);
1671 const QTextDocumentFragment fragment(d->cursor);
1672 return new QQuickTextEditMimeData(fragment);
1675bool QQuickTextControl::canInsertFromMimeData(
const QMimeData *source)
const
1677 Q_D(
const QQuickTextControl);
1678 if (d->acceptRichText)
1679 return source->hasText()
1680 || source->hasHtml()
1681 || source->hasFormat(QLatin1String(
"application/x-qrichtext"))
1682 || source->hasFormat(QLatin1String(
"application/x-qt-richtext"));
1684 return source->hasText();
1687void QQuickTextControl::insertFromMimeData(
const QMimeData *source)
1689 Q_D(QQuickTextControl);
1690 if (!(d->interactionFlags & Qt::TextEditable) || !source)
1693 bool hasData =
false;
1694 QTextDocumentFragment fragment;
1695#if QT_CONFIG(texthtmlparser)
1696 if (source->hasFormat(QLatin1String(
"application/x-qrichtext")) && d->acceptRichText) {
1698 const QString richtext = QLatin1String(
"<meta name=\"qrichtext\" content=\"1\" />")
1699 + QString::fromUtf8(source->data(QLatin1String(
"application/x-qrichtext")));
1700 fragment = QTextDocumentFragment::fromHtml(richtext, d->doc);
1702 }
else if (source->hasHtml() && d->acceptRichText) {
1703 fragment = QTextDocumentFragment::fromHtml(source->html(), d->doc);
1706 QString text = source->text();
1707 if (!text.isNull()) {
1708 fragment = QTextDocumentFragment::fromPlainText(text);
1713 fragment = QTextDocumentFragment::fromPlainText(source->text());
1717 d->cursor.insertFragment(fragment);
1718 updateCursorRectangle(
true);
1723 QTextCursor oldCursor = cursor;
1725 if (href.isEmpty()) {
1726 QTextCursor tmp = cursor;
1727 if (tmp.selectionStart() != tmp.position())
1728 tmp.setPosition(tmp.selectionStart());
1729 tmp.movePosition(QTextCursor::NextCharacter);
1730 href = tmp.charFormat().anchorHref();
1735 if (!cursor.hasSelection()) {
1736 QTextBlock block = cursor.block();
1737 const int cursorPos = cursor.position();
1739 QTextBlock::Iterator it = block.begin();
1740 QTextBlock::Iterator linkFragment;
1742 for (; !it.atEnd(); ++it) {
1743 QTextFragment fragment = it.fragment();
1744 const int fragmentPos = fragment.position();
1745 if (fragmentPos <= cursorPos &&
1746 fragmentPos + fragment.length() > cursorPos) {
1752 if (!linkFragment.atEnd()) {
1754 cursor.setPosition(it.fragment().position());
1755 if (it != block.begin()) {
1758 QTextFragment fragment = it.fragment();
1759 if (fragment.charFormat().anchorHref() != href)
1761 cursor.setPosition(fragment.position());
1762 }
while (it != block.begin());
1765 for (it = linkFragment; !it.atEnd(); ++it) {
1766 QTextFragment fragment = it.fragment();
1767 if (fragment.charFormat().anchorHref() != href)
1769 cursor.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor);
1778 cursor.clearSelection();
1780 repaintOldAndNewSelection(oldCursor);
1782 emit q_func()->linkActivated(href);
1786bool QQuickTextControlPrivate::isPreediting()
const
1788 QTextLayout *layout = cursor.block().layout();
1789 if (layout && !layout->preeditAreaText().isEmpty())
1795void QQuickTextControlPrivate::commitPreedit()
1797 Q_Q(QQuickTextControl);
1802 QGuiApplication::inputMethod()->commit();
1807 QInputMethodEvent event;
1808 QCoreApplication::sendEvent(q->parent(), &event);
1811void QQuickTextControlPrivate::cancelPreedit()
1813 Q_Q(QQuickTextControl);
1818 QGuiApplication::inputMethod()->reset();
1820 QInputMethodEvent event;
1821 QCoreApplication::sendEvent(q->parent(), &event);
1825void QQuickTextControl::setTextInteractionFlags(Qt::TextInteractionFlags flags)
1827 Q_D(QQuickTextControl);
1828 if (flags == d->interactionFlags)
1830 d->interactionFlags = flags;
1833 d->setBlinkingCursorEnabled(flags & (Qt::TextEditable | Qt::TextSelectableByKeyboard));
1836Qt::TextInteractionFlags QQuickTextControl::textInteractionFlags()
const
1838 Q_D(
const QQuickTextControl);
1839 return d->interactionFlags;
1842QString QQuickTextControl::toPlainText()
const
1844 return document()->toPlainText();
1847#if QT_CONFIG(texthtmlparser)
1848QString QQuickTextControl::toHtml()
const
1850 return document()->toHtml();
1854#if QT_CONFIG(textmarkdownwriter)
1855QString QQuickTextControl::toMarkdown()
const
1857 return document()->toMarkdown();
1861bool QQuickTextControl::cursorOn()
const
1863 Q_D(
const QQuickTextControl);
1867int QQuickTextControl::hitTest(
const QPointF &point, Qt::HitTestAccuracy accuracy)
const
1869 Q_D(
const QQuickTextControl);
1870 return d->doc->documentLayout()->hitTest(point, accuracy);
1873QRectF QQuickTextControl::blockBoundingRect(
const QTextBlock &block)
const
1875 Q_D(
const QQuickTextControl);
1876 return d->doc->documentLayout()->blockBoundingRect(block);
1879QString QQuickTextControl::preeditText()
const
1882 Q_D(
const QQuickTextControl);
1883 QTextLayout *layout = d->cursor.block().layout();
1887 return layout->preeditAreaText();
1896 if (!fragment.isEmpty())
1897 return QStringList() << QString::fromLatin1(
"text/plain") << QString::fromLatin1(
"text/html")
1898#if QT_CONFIG(textodfwriter)
1899 << QString::fromLatin1(
"application/vnd.oasis.opendocument.text")
1903 return QMimeData::formats();
1908 if (!fragment.isEmpty())
1910 return QMimeData::retrieveData(mimeType, type);
1916#if QT_CONFIG(texthtmlparser)
1917 that->setData(QLatin1String(
"text/html"), fragment.toHtml().toUtf8());
1919#if QT_CONFIG(textodfwriter)
1922 QTextDocumentWriter writer(&buffer,
"ODF");
1923 writer.write(fragment);
1925 that->setData(QLatin1String(
"application/vnd.oasis.opendocument.text"), buffer.data());
1928 that->setText(fragment.toPlainText());
1929 fragment = QTextDocumentFragment();
1935#include "moc_qquicktextcontrol_p.cpp"
\inmodule QtCore\reentrant
void selectionChanged(bool forceEmitSelectionChanged=false)
void updateCursorFlashTime()
bool cursorIsFocusIndicator
bool cursorBlinkingEnabled
void extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition)
QRectF rectForPosition(int position) const
bool imSelectionAfterPress
void extendBlockwiseSelection(int suggestedNewPosition)
void setBlinkingCursorEnabled(bool enable)
bool hadSelectionOnMousePress
void setCursorPosition(int pos, QTextCursor::MoveMode mode=QTextCursor::MoveAnchor)
bool cursorRectangleChanged
void updateCurrentCharFormat()
bool ignoreAutomaticScrollbarAdjustement
void _q_updateCurrentCharFormatAndSelection()
bool wordSelectionEnabled
QStringList formats() const override
Returns a list of formats supported by the object.
const int textCursorWidth