Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquicktextcontrol.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6
7#ifndef QT_NO_TEXTCONTROL
8
9#include <qcoreapplication.h>
10#include <qfont.h>
11#include <qfontmetrics.h>
12#include <qevent.h>
13#include <qdebug.h>
14#include <qclipboard.h>
15#include <qtimer.h>
16#include <qinputmethod.h>
17#include "private/qtextdocumentlayout_p.h"
18#include "private/qabstracttextdocumentlayout_p.h"
19#include "qtextdocument.h"
20#include "private/qtextdocument_p.h"
21#include "qtextlist.h"
22#include "qtextdocumentwriter.h"
23#include "private/qtextcursor_p.h"
24#include <QtCore/qloggingcategory.h>
25
26#include <qtextformat.h>
27#include <qtransform.h>
28#include <qdatetime.h>
29#include <qbuffer.h>
30#include <qguiapplication.h>
31#include <limits.h>
32#include <qtexttable.h>
33#include <qvariant.h>
34#include <qurl.h>
35#include <qstylehints.h>
36#include <qmetaobject.h>
37
38#include <private/qqmlglobal_p.h>
39#include <private/qquickdeliveryagent_p_p.h>
40
41// ### these should come from QStyleHints
42const int textCursorWidth = 1;
43
46
47// could go into QTextCursor...
49{
50 const QTextBlock block = cursor.block();
51 if (!block.isValid())
52 return QTextLine();
53
54 const QTextLayout *layout = block.layout();
55 if (!layout)
56 return QTextLine();
57
58 const int relativePos = cursor.position() - block.position();
59 return layout->lineForTextPosition(relativePos);
60}
61
63 : doc(nullptr),
64#if QT_CONFIG(im)
65 preeditCursor(0),
66#endif
67 interactionFlags(Qt::TextEditorInteraction),
68 cursorOn(false),
69 cursorIsFocusIndicator(false),
70 mousePressed(false),
71 lastSelectionState(false),
72 ignoreAutomaticScrollbarAdjustement(false),
73 overwriteMode(false),
74 acceptRichText(true),
75 cursorVisible(false),
76 cursorBlinkingEnabled(false),
77 hasFocus(false),
78 hadSelectionOnMousePress(false),
79 wordSelectionEnabled(false),
80 hasImState(false),
81 cursorRectangleChanged(false),
82 hoveredMarker(false),
83 selectByTouchDrag(false),
84 imSelectionAfterPress(false),
85 lastSelectionStart(-1),
86 lastSelectionEnd(-1)
87{}
88
90{
91#if !QT_CONFIG(shortcut)
92 Q_UNUSED(e);
93#endif
94
96 if (cursor.isNull())
97 return false;
98
99 const QTextCursor oldSelection = cursor;
100 const int oldCursorPos = cursor.position();
101
104
105 if (false) {
106 }
107#if QT_CONFIG(shortcut)
110 }
111 else if (e == QKeySequence::MoveToPreviousChar) {
113 }
114 else if (e == QKeySequence::SelectNextChar) {
117 }
118 else if (e == QKeySequence::SelectPreviousChar) {
121 }
122 else if (e == QKeySequence::SelectNextWord) {
125 }
126 else if (e == QKeySequence::SelectPreviousWord) {
129 }
130 else if (e == QKeySequence::SelectStartOfLine) {
133 }
134 else if (e == QKeySequence::SelectEndOfLine) {
137 }
138 else if (e == QKeySequence::SelectStartOfBlock) {
141 }
142 else if (e == QKeySequence::SelectEndOfBlock) {
145 }
149 }
150 else if (e == QKeySequence::SelectEndOfDocument) {
151 op = QTextCursor::End;
153 }
154 else if (e == QKeySequence::SelectPreviousLine) {
155 op = QTextCursor::Up;
157 }
158 else if (e == QKeySequence::SelectNextLine) {
161 {
162 QTextBlock block = cursor.block();
164 if (!block.next().isValid()
165 && line.isValid()
166 && line.lineNumber() == block.layout()->lineCount() - 1)
167 op = QTextCursor::End;
168 }
169 }
170 else if (e == QKeySequence::MoveToNextWord) {
172 }
173 else if (e == QKeySequence::MoveToPreviousWord) {
175 }
176 else if (e == QKeySequence::MoveToEndOfBlock) {
178 }
179 else if (e == QKeySequence::MoveToStartOfBlock) {
181 }
182 else if (e == QKeySequence::MoveToNextLine) {
184 }
185 else if (e == QKeySequence::MoveToPreviousLine) {
186 op = QTextCursor::Up;
187 }
188 else if (e == QKeySequence::MoveToStartOfLine) {
190 }
191 else if (e == QKeySequence::MoveToEndOfLine) {
193 }
196 }
197 else if (e == QKeySequence::MoveToEndOfDocument) {
198 op = QTextCursor::End;
199 }
200#endif // shortcut
201 else {
202 return false;
203 }
204
205// Except for pageup and pagedown, OS X has very different behavior, we don't do it all, but
206// here's the breakdown:
207// Shift still works as an anchor, but only one of the other keys can be down Ctrl (Command),
208// Alt (Option), or Meta (Control).
209// Command/Control + Left/Right -- Move to left or right of the line
210// + Up/Down -- Move to top bottom of the file. (Control doesn't move the cursor)
211// Option + Left/Right -- Move one word Left/right.
212// + Up/Down -- Begin/End of Paragraph.
213// Home/End Top/Bottom of file. (usually don't move the cursor, but will select)
214
215 bool visualNavigation = cursor.visualNavigation();
217 const bool moved = cursor.movePosition(op, mode);
218 cursor.setVisualNavigation(visualNavigation);
219
220 bool isNavigationEvent
221 = e->key() == Qt::Key_Up
222 || e->key() == Qt::Key_Down
223 || e->key() == Qt::Key_Left
224 || e->key() == Qt::Key_Right;
225
226 if (moved) {
227 if (cursor.position() != oldCursorPos)
228 emit q->cursorPositionChanged();
229 q->updateCursorRectangle(true);
230 } else if (isNavigationEvent && oldSelection.anchor() == cursor.anchor()) {
231 return false;
232 }
233
234 selectionChanged(/*forceEmitSelectionChanged =*/(mode == QTextCursor::KeepAnchor));
235
236 repaintOldAndNewSelection(oldSelection);
237
238 return true;
239}
240
242{
244
246 if (fmt == lastCharFormat)
247 return;
249
250 emit q->currentCharFormatChanged(fmt);
252}
253
255{
257
258#if QT_CONFIG(im)
259 cancelPreedit();
260#endif
261
262 // for use when called from setPlainText. we may want to re-use the currently
263 // set char format then.
264 const QTextCharFormat charFormatForInsertion = cursor.charFormat();
265
266 bool previousUndoRedoState = doc->isUndoRedoEnabled();
267 doc->setUndoRedoEnabled(false);
268
269 const int oldCursorPos = cursor.position();
270
271 // avoid multiple textChanged() signals being emitted
273
274 if (!text.isEmpty()) {
275 // clear 'our' cursor for insertion to prevent
276 // the emission of the cursorPositionChanged() signal.
277 // instead we emit it only once at the end instead of
278 // at the end of the document after loading and when
279 // positioning the cursor again to the start of the
280 // document.
282 if (format == Qt::PlainText) {
283 QTextCursor formatCursor(doc);
284 // put the setPlainText and the setCharFormat into one edit block,
285 // so that the syntax highlight triggers only /once/ for the entire
286 // document, not twice.
287 formatCursor.beginEditBlock();
289 doc->setUndoRedoEnabled(false);
290 formatCursor.select(QTextCursor::Document);
291 formatCursor.setCharFormat(charFormatForInsertion);
292 formatCursor.endEditBlock();
293#if QT_CONFIG(textmarkdownreader)
294 } else if (format == Qt::MarkdownText) {
296 doc->setMarkdown(text);
297#endif
298 } else {
299#if QT_CONFIG(texthtmlparser)
300 doc->setHtml(text);
301#else
303#endif
304 doc->setUndoRedoEnabled(false);
305 }
307 } else {
308 doc->clear();
309 }
310 cursor.setCharFormat(charFormatForInsertion);
311
313 emit q->textChanged();
314 doc->setUndoRedoEnabled(previousUndoRedoState);
316 doc->setModified(false);
317
318 q->updateCursorRectangle(true);
319 if (cursor.position() != oldCursorPos)
320 emit q->cursorPositionChanged();
321}
322
324{
326 const int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
327 if (cursorPos == -1)
328 return;
329 cursor.setPosition(cursorPos);
330}
331
341
343{
345 emit q->updateCursorRequest();
346}
347
349{
351 if (cursor.hasSelection()
352 && oldSelection.hasSelection()
353 && cursor.currentFrame() == oldSelection.currentFrame()
355 && !oldSelection.hasComplexSelection()
356 && cursor.anchor() == oldSelection.anchor()
357 ) {
358 QTextCursor differenceSelection(doc);
359 differenceSelection.setPosition(oldSelection.position());
360 differenceSelection.setPosition(cursor.position(), QTextCursor::KeepAnchor);
361 emit q->updateRequest();
362 } else {
363 if (!oldSelection.hasSelection() && !cursor.hasSelection()) {
364 if (!oldSelection.isNull())
365 emit q->updateCursorRequest();
366 emit q->updateCursorRequest();
367
368 } else {
369 if (!oldSelection.isNull())
370 emit q->updateRequest();
371 emit q->updateRequest();
372 }
373 }
374}
375
376void QQuickTextControlPrivate::selectionChanged(bool forceEmitSelectionChanged /*=false*/)
377{
379 if (forceEmitSelectionChanged) {
380#if QT_CONFIG(im)
381 if (hasFocus)
382 qGuiApp->inputMethod()->update(Qt::ImCurrentSelection);
383#endif
384 emit q->selectionChanged();
385 }
386
387 bool current = cursor.hasSelection();
388 int selectionStart = cursor.selectionStart();
389 int selectionEnd = cursor.selectionEnd();
390 if (current == lastSelectionState && (!current || (selectionStart == lastSelectionStart && selectionEnd == lastSelectionEnd)))
391 return;
392
393 if (lastSelectionState != current) {
394 lastSelectionState = current;
395 emit q->copyAvailable(current);
396 }
397
398 lastSelectionStart = selectionStart;
399 lastSelectionEnd = selectionEnd;
400
401 if (!forceEmitSelectionChanged) {
402#if QT_CONFIG(im)
403 if (hasFocus)
404 qGuiApp->inputMethod()->update(Qt::ImCurrentSelection);
405#endif
406 emit q->selectionChanged();
407 }
408 q->updateCursorRectangle(true);
409}
410
416
417#if QT_CONFIG(clipboard)
418void QQuickTextControlPrivate::setClipboardSelection()
419{
421 if (!cursor.hasSelection() || !clipboard->supportsSelection())
422 return;
424 QMimeData *data = q->createMimeDataFromSelection();
426}
427#endif
428
430{
432 if (someCursor.isCopyOf(cursor)) {
433 emit q->cursorPositionChanged();
434 q->updateCursorRectangle(true);
435 }
436}
437
451
453{
454 // Note: cursorOn represents the current blinking state controlled by a timer, and
455 // should not be confused with cursorVisible or cursorBlinkingEnabled. However, we
456 // interpretate a cursorFlashTime of 0 to mean "always on, never blink".
457 cursorOn = true;
458 int flashTime = QGuiApplication::styleHints()->cursorFlashTime();
459
460 if (cursorBlinkingEnabled && flashTime >= 2)
461 cursorBlinkTimer.start(flashTime / 2, q_func());
462 else
464
466}
467
468void QQuickTextControlPrivate::extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition)
469{
471
472 // if inside the initial selected word keep that
473 if (suggestedNewPosition >= selectedWordOnDoubleClick.selectionStart()
474 && suggestedNewPosition <= selectedWordOnDoubleClick.selectionEnd()) {
475 q->setTextCursor(selectedWordOnDoubleClick);
476 return;
477 }
478
480 curs.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
481
483 return;
484 const int wordStartPos = curs.position();
485
486 const int blockPos = curs.block().position();
487 const QPointF blockCoordinates = q->blockBoundingRect(curs.block()).topLeft();
488
490 if (!line.isValid())
491 return;
492
493 const qreal wordStartX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x();
494
496 return;
497 const int wordEndPos = curs.position();
498
499 const QTextLine otherLine = currentTextLine(curs);
500 if (otherLine.textStart() != line.textStart()
501 || wordEndPos == wordStartPos)
502 return;
503
504 const qreal wordEndX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x();
505
506 if (!wordSelectionEnabled && (mouseXPosition < wordStartX || mouseXPosition > wordEndX))
507 return;
508
509 if (suggestedNewPosition < selectedWordOnDoubleClick.position()) {
512 } else {
515 }
516
518#if QT_CONFIG(clipboard)
519 setClipboardSelection();
520#endif
521 selectionChanged(true);
522 }
523}
524
526{
528
529 // if inside the initial selected line keep that
530 if (suggestedNewPosition >= selectedBlockOnTripleClick.selectionStart()
531 && suggestedNewPosition <= selectedBlockOnTripleClick.selectionEnd()) {
532 q->setTextCursor(selectedBlockOnTripleClick);
533 return;
534 }
535
536 if (suggestedNewPosition < selectedBlockOnTripleClick.position()) {
538 cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
540 } else {
542 cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
545 }
546
548#if QT_CONFIG(clipboard)
549 setClipboardSelection();
550#endif
551 selectionChanged(true);
552 }
553}
554
556{
558 d->repaintSelection();
559 const int oldCursorPos = d->cursor.position();
560 d->doc->undo(&d->cursor);
561 if (d->cursor.position() != oldCursorPos)
564}
565
567{
569 d->repaintSelection();
570 const int oldCursorPos = d->cursor.position();
571 d->doc->redo(&d->cursor);
572 if (d->cursor.position() != oldCursorPos)
575}
576
578{
580 d->cursor.select(QTextCursor::Document);
581 d->cursor.removeSelectedText();
582}
583
586{
588 Q_ASSERT(doc);
589
593 qmlobject_connect(doc, QTextDocument, SIGNAL(contentsChanged()), this, QQuickTextControl, SIGNAL(textChanged()));
594 qmlobject_connect(doc, QTextDocument, SIGNAL(contentsChanged()), this, QQuickTextControl, SLOT(_q_updateCurrentCharFormatAndSelection()));
597
598 layout->setProperty("cursorWidth", textCursorWidth);
599
600 d->doc = doc;
601 d->cursor = QTextCursor(doc);
602 d->lastCharFormat = d->cursor.charFormat();
603 doc->setPageSize(QSizeF(0, 0));
604 doc->setModified(false);
605 doc->setUndoRedoEnabled(true);
606}
607
611
613{
614 Q_D(const QQuickTextControl);
615 return d->doc;
616}
617
619{
621 d->doc = doc;
622}
623
625{
627 const bool update = d->cursorRectangleChanged || force;
628 d->cursorRectangleChanged = false;
629 if (update)
631}
632
634{
636#if QT_CONFIG(im)
637 d->commitPreedit();
638#endif
639 d->cursorIsFocusIndicator = false;
640 const bool posChanged = cursor.position() != d->cursor.position();
641 const QTextCursor oldSelection = d->cursor;
642 d->cursor = cursor;
643 d->cursorOn = d->hasFocus && (d->interactionFlags & Qt::TextEditable);
644 d->_q_updateCurrentCharFormatAndSelection();
646 d->repaintOldAndNewSelection(oldSelection);
647 if (posChanged)
649}
650
652{
653 Q_D(const QQuickTextControl);
654 return d->cursor;
655}
656
657#if QT_CONFIG(clipboard)
658
659void QQuickTextControl::cut()
660{
662 if (!(d->interactionFlags & Qt::TextEditable) || !d->cursor.hasSelection())
663 return;
664 copy();
665 d->cursor.removeSelectedText();
666}
667
668void QQuickTextControl::copy()
669{
671 if (!d->cursor.hasSelection())
672 return;
674 QGuiApplication::clipboard()->setMimeData(data);
675}
676
677void QQuickTextControl::paste(QClipboard::Mode mode)
678{
679 const QMimeData *md = QGuiApplication::clipboard()->mimeData(mode);
680 if (md)
682}
683#endif
684
686{
688 const int selectionLength = qAbs(d->cursor.position() - d->cursor.anchor());
689 d->cursor.select(QTextCursor::Document);
690 d->selectionChanged(selectionLength != qAbs(d->cursor.position() - d->cursor.anchor()));
691 d->cursorIsFocusIndicator = false;
693}
694
695void QQuickTextControl::processEvent(QEvent *e, const QPointF &coordinateOffset)
696{
698 t.translate(coordinateOffset.x(), coordinateOffset.y());
699 processEvent(e, t);
700}
701
703{
705 if (d->interactionFlags == Qt::NoTextInteraction) {
706 e->ignore();
707 return;
708 }
709
710 switch (e->type()) {
711 case QEvent::KeyPress:
712 d->keyPressEvent(static_cast<QKeyEvent *>(e));
713 break;
715 d->keyReleaseEvent(static_cast<QKeyEvent *>(e));
716 break;
718 QMouseEvent *ev = static_cast<QMouseEvent *>(e);
719 d->mousePressEvent(ev, transform.map(ev->position()));
720 break; }
721 case QEvent::MouseMove: {
722 QMouseEvent *ev = static_cast<QMouseEvent *>(e);
723 d->mouseMoveEvent(ev, transform.map(ev->position()));
724 break; }
726 QMouseEvent *ev = static_cast<QMouseEvent *>(e);
727 d->mouseReleaseEvent(ev, transform.map(ev->position()));
728 break; }
730 QMouseEvent *ev = static_cast<QMouseEvent *>(e);
731 d->mouseDoubleClickEvent(ev, transform.map(ev->position()));
732 break; }
735 case QEvent::HoverLeave: {
736 QHoverEvent *ev = static_cast<QHoverEvent *>(e);
737 d->hoverEvent(ev, transform.map(ev->position()));
738 break; }
739#if QT_CONFIG(im)
741 d->inputMethodEvent(static_cast<QInputMethodEvent *>(e));
742 break;
743#endif
744 case QEvent::FocusIn:
745 case QEvent::FocusOut:
746 d->focusEvent(static_cast<QFocusEvent *>(e));
747 break;
748
750 if (d->interactionFlags & Qt::TextEditable) {
751 QKeyEvent* ke = static_cast<QKeyEvent *>(e);
753 }
754 break;
755 default:
756 break;
757 }
758}
759
761{
762 return QObject::event(e);
763}
764
766{
768 if (e->timerId() == d->cursorBlinkTimer.timerId()) {
769 d->cursorOn = !d->cursorOn;
770
771 d->repaintCursor();
772 }
773}
774
776{
778 d->setContent(Qt::PlainText, text);
779}
780
782{
784 d->setContent(Qt::MarkdownText, text);
785}
786
788{
790 d->setContent(Qt::RichText, text);
791}
792
793
798
800{
802
803 if (e->key() == Qt::Key_Back) {
804 e->ignore();
805 return;
806 }
807
808#if QT_CONFIG(shortcut)
809 if (e == QKeySequence::SelectAll) {
810 e->accept();
811 q->selectAll();
812#if QT_CONFIG(clipboard)
813 setClipboardSelection();
814#endif
815 return;
816 }
817#if QT_CONFIG(clipboard)
818 else if (e == QKeySequence::Copy) {
819 e->accept();
820 q->copy();
821 return;
822 }
823#endif
824#endif // shortcut
825
827 && cursorMoveKeyEvent(e))
828 goto accept;
829
831 e->ignore();
832 return;
833 }
834
835 if (e->key() == Qt::Key_Direction_L || e->key() == Qt::Key_Direction_R) {
839 goto accept;
840 }
841
842 // schedule a repaint of the region of the cursor, as when we move it we
843 // want to make sure the old cursor disappears (not noticeable when moving
844 // only a few pixels but noticeable when jumping between cells in tables for
845 // example)
847
848 if (e->key() == Qt::Key_Backspace && !(e->modifiers() & ~Qt::ShiftModifier)) {
851 if (list && cursor.atBlockStart() && !cursor.hasSelection()) {
853 } else if (cursor.atBlockStart() && blockFmt.indent() > 0) {
854 blockFmt.setIndent(blockFmt.indent() - 1);
855 cursor.setBlockFormat(blockFmt);
856 } else {
857 QTextCursor localCursor = cursor;
858 localCursor.deletePreviousChar();
859 }
860 goto accept;
861 }
862#if QT_CONFIG(shortcut)
865 e->accept();
866 goto accept;
867 } else if (e == QKeySequence::InsertLineSeparator) {
868 cursor.insertText(QString(QChar::LineSeparator));
869 e->accept();
870 goto accept;
871 }
872#endif
873 if (false) {
874 }
875#if QT_CONFIG(shortcut)
876 else if (e == QKeySequence::Undo) {
877 q->undo();
878 }
879 else if (e == QKeySequence::Redo) {
880 q->redo();
881 }
882#if QT_CONFIG(clipboard)
883 else if (e == QKeySequence::Cut) {
884 q->cut();
885 }
886 else if (e == QKeySequence::Paste) {
888 q->paste(mode);
889 }
890#endif
891 else if (e == QKeySequence::Delete) {
892 QTextCursor localCursor = cursor;
893 localCursor.deleteChar();
894 }
895 else if (e == QKeySequence::DeleteEndOfWord) {
896 if (!cursor.hasSelection())
899 }
900 else if (e == QKeySequence::DeleteStartOfWord) {
901 if (!cursor.hasSelection())
904 }
905 else if (e == QKeySequence::DeleteEndOfLine) {
906 QTextBlock block = cursor.block();
907 if (cursor.position() == block.position() + block.length() - 2)
909 else
912 }
913#endif // shortcut
914 else {
915 goto process;
916 }
917 goto accept;
918
919process:
920 {
921 if (q->isAcceptableInput(e)) {
922#if QT_CONFIG(im)
923 // QTBUG-90362
924 // Before key press event will be handled, pre-editing part should be finished
925 if (isPreediting())
926 commitPreedit();
927#endif
928 if (overwriteMode
929 // no need to call deleteChar() if we have a selection, insertText
930 // does it already
931 && !cursor.hasSelection()
932 && !cursor.atBlockEnd()) {
934 }
935
936 cursor.insertText(e->text());
938 } else {
939 e->ignore();
940 return;
941 }
942 }
943
944 accept:
945
946#if QT_CONFIG(clipboard)
947 setClipboardSelection();
948#endif
949
950 e->accept();
951 cursorOn = true;
952
953 q->updateCursorRectangle(true);
955}
956
958{
959 Q_Q(const QQuickTextControl);
960 const QTextBlock block = doc->findBlock(position);
961 if (!block.isValid())
962 return QRectF();
963 const QTextLayout *layout = block.layout();
964 const QPointF layoutPos = q->blockBoundingRect(block).topLeft();
965 int relativePos = position - block.position();
966#if QT_CONFIG(im)
967 if (preeditCursor != 0) {
968 int preeditPos = layout->preeditAreaPosition();
969 if (relativePos == preeditPos)
970 relativePos += preeditCursor;
971 else if (relativePos > preeditPos)
972 relativePos += layout->preeditAreaText().size();
973 }
974#endif
975 QTextLine line = layout->lineForTextPosition(relativePos);
976
977 QRectF r;
978
979 if (line.isValid()) {
980 qreal x = line.cursorToX(relativePos);
981 qreal w = 0;
982 if (overwriteMode) {
983 if (relativePos < line.textLength() - line.textStart())
984 w = line.cursorToX(relativePos + 1) - x;
985 else
986 w = QFontMetrics(block.layout()->font()).horizontalAdvance(QLatin1Char(' ')); // in sync with QTextLine::draw()
987 }
988 r = QRectF(layoutPos.x() + x, layoutPos.y() + line.y(), textCursorWidth + w, line.height());
989 } else {
990 r = QRectF(layoutPos.x(), layoutPos.y(), textCursorWidth, 10); // #### correct height
991 }
992
993 return r;
994}
995
997{
999
1002 imSelectionAfterPress = false;
1003
1005 return;
1006
1008 anchorOnMousePress = q->anchorAt(pos);
1009
1011 cursorIsFocusIndicator = false;
1014 }
1015 }
1016
1018 return;
1020 blockWithMarkerUnderMousePress = q->blockWithMarkerAt(pos);
1021 if (e->button() & Qt::MiddleButton) {
1022 return;
1023 } else if (!(e->button() & Qt::LeftButton)) {
1024 e->ignore();
1025 return;
1028 e->ignore();
1029 return;
1030 }
1031
1032 cursorIsFocusIndicator = false;
1033 const QTextCursor oldSelection = cursor;
1034 const int oldCursorPos = cursor.position();
1035
1036#if QT_CONFIG(im)
1037 commitPreedit();
1038#endif
1039
1040 if ((e->timestamp() < (timestampAtLastDoubleClick + QGuiApplication::styleHints()->mouseDoubleClickInterval()))
1041 && ((pos - tripleClickPoint).toPoint().manhattanLength() < QGuiApplication::styleHints()->startDragDistance())) {
1042
1047
1049
1050 timestampAtLastDoubleClick = 0; // do not enter this condition in case of 4(!) rapid clicks
1051 } else {
1052 int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
1053 if (cursorPos == -1) {
1054 e->ignore();
1055 return;
1056 }
1057
1062 }
1063
1065 extendBlockwiseSelection(cursorPos);
1067 extendWordwiseSelection(cursorPos, pos.x());
1068 else if (!wordSelectionEnabled)
1070 } else {
1071 setCursorPosition(cursorPos);
1072 }
1073 }
1074
1075 if (cursor.position() != oldCursorPos) {
1076 q->updateCursorRectangle(true);
1077 emit q->cursorPositionChanged();
1078 }
1081 else
1083 repaintOldAndNewSelection(oldSelection);
1085}
1086
1088{
1090 return;
1091
1092 Q_Q(QQuickTextControl);
1093
1094 if ((e->buttons() & Qt::LeftButton)) {
1095 const bool editable = interactionFlags & Qt::TextEditable;
1096
1097 if (!(mousePressed
1098 || editable
1101 return;
1102
1103 const QTextCursor oldSelection = cursor;
1104 const int oldCursorPos = cursor.position();
1105
1106 if (!mousePressed)
1107 return;
1108
1109 const qreal mouseX = qreal(mousePos.x());
1110
1111 int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1112
1113#if QT_CONFIG(im)
1114 if (isPreediting()) {
1115 // note: oldCursorPos not including preedit
1116 int selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1117 if (newCursorPos != selectionStartPos) {
1118 commitPreedit();
1119 // commit invalidates positions
1120 newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1121 selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1122 setCursorPosition(selectionStartPos);
1123 }
1124 }
1125#endif
1126
1127 if (newCursorPos == -1)
1128 return;
1129
1133 }
1134
1136 extendBlockwiseSelection(newCursorPos);
1138 extendWordwiseSelection(newCursorPos, mouseX);
1139#if QT_CONFIG(im)
1140 else if (!isPreediting())
1142#endif
1143
1145 if (cursor.position() != oldCursorPos) {
1146 emit q->cursorPositionChanged();
1147 }
1149#if QT_CONFIG(im)
1150 if (qGuiApp)
1151 qGuiApp->inputMethod()->update(Qt::ImQueryInput);
1152#endif
1153 } else if (cursor.position() != oldCursorPos) {
1154 emit q->cursorPositionChanged();
1155 }
1156 selectionChanged(true);
1157 repaintOldAndNewSelection(oldSelection);
1158 }
1159
1160 sendMouseEventToInputContext(e, mousePos);
1161}
1162
1164{
1165 Q_Q(QQuickTextControl);
1166
1168 return;
1169
1170 const QTextCursor oldSelection = cursor;
1171 const int oldCursorPos = cursor.position();
1173
1174 if (mousePressed) {
1175 mousePressed = false;
1176#if QT_CONFIG(clipboard)
1177 setClipboardSelection();
1178 selectionChanged(true);
1179 } else if (e->button() == Qt::MiddleButton
1181 && QGuiApplication::clipboard()->supportsSelection()) {
1184 if (md)
1185 q->insertFromMimeData(md);
1186#endif
1187 }
1190
1191 repaintOldAndNewSelection(oldSelection);
1192
1193 if (cursor.position() != oldCursorPos) {
1194 emit q->cursorPositionChanged();
1195 q->updateCursorRectangle(true);
1196 }
1197
1198 if ((isMouse || selectByTouchDrag) && interactionFlags.testFlag(Qt::TextEditable) &&
1200 QTextBlock block = q->blockWithMarkerAt(pos);
1201 if (block == blockWithMarkerUnderMousePress) {
1202 auto fmt = block.blockFormat();
1206 }
1207 }
1208
1210 if (!(e->button() & Qt::LeftButton))
1211 return;
1212
1213 const QString anchor = q->anchorAt(pos);
1214
1215 if (anchor.isEmpty())
1216 return;
1217
1218 if (!cursor.hasSelection()
1219 || (anchor == anchorOnMousePress && hadSelectionOnMousePress)) {
1220
1221 const int anchorPos = q->hitTest(pos, Qt::ExactHit);
1222 if (anchorPos != -1) {
1223 cursor.setPosition(anchorPos);
1224
1225 QString anchor = anchorOnMousePress;
1228 }
1229 }
1230 }
1231}
1232
1234{
1235 Q_Q(QQuickTextControl);
1236
1239#if QT_CONFIG(im)
1240 commitPreedit();
1241#endif
1242
1243 const QTextCursor oldSelection = cursor;
1246 bool doEmit = false;
1247 if (line.isValid() && line.textLength()) {
1249 doEmit = true;
1250 }
1251 repaintOldAndNewSelection(oldSelection);
1252
1253 cursorIsFocusIndicator = false;
1255
1258 if (doEmit) {
1260#if QT_CONFIG(clipboard)
1261 setClipboardSelection();
1262#endif
1263 emit q->cursorPositionChanged();
1264 q->updateCursorRectangle(true);
1265 }
1266 } else if (!sendMouseEventToInputContext(e, pos)) {
1267 e->ignore();
1268 }
1269}
1270
1272{
1273#if QT_CONFIG(im)
1274 Q_Q(QQuickTextControl);
1275
1276 Q_UNUSED(e);
1277
1278 if (isPreediting()) {
1280 int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position();
1281
1282 if (cursorPos >= 0 && cursorPos <= layout->preeditAreaText().size()) {
1283 if (e->type() == QEvent::MouseButtonRelease) {
1284 QGuiApplication::inputMethod()->invokeAction(QInputMethod::Click, cursorPos);
1285 }
1286
1287 return true;
1288 }
1289 }
1290#else
1291 Q_UNUSED(e);
1292 Q_UNUSED(pos);
1293#endif
1294 return false;
1295}
1296
1297#if QT_CONFIG(im)
1298void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
1299{
1300 Q_Q(QQuickTextControl);
1301 if (cursor.isNull()) {
1302 e->ignore();
1303 return;
1304 }
1305 bool textEditable = interactionFlags.testFlag(Qt::TextEditable);
1306 bool isGettingInput = !e->commitString().isEmpty()
1308 || e->replacementLength() > 0;
1309 bool forceSelectionChanged = false;
1310 int oldCursorPos = cursor.position();
1311
1313 if (isGettingInput && textEditable) {
1315 }
1316
1317 QTextBlock block;
1318
1319 // insert commit string
1320 if (textEditable && (!e->commitString().isEmpty() || e->replacementLength())) {
1321 if (e->commitString().endsWith(QChar::LineFeed))
1322 block = cursor.block(); // Remember the block where the preedit text is
1324 c.setPosition(c.position() + e->replacementStart());
1325 c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor);
1326 c.insertText(e->commitString());
1327 }
1328
1330 for (int i = 0; i < e->attributes().size(); ++i) {
1331 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
1332 if (a.type == QInputMethodEvent::Selection) {
1333 if (mousePressed)
1334 imSelectionAfterPress = true;
1335 QTextCursor oldCursor = cursor;
1336 int blockStart = a.start + cursor.block().position();
1338 cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
1339 repaintOldAndNewSelection(oldCursor);
1340 forceSelectionChanged = true;
1341 }
1342 }
1343 }
1344
1345 if (!block.isValid())
1346 block = cursor.block();
1347
1348 const int oldPreeditCursor = preeditCursor;
1349 if (textEditable) {
1350 QTextLayout *layout = block.layout();
1351 if (isGettingInput) {
1352 layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
1353 emit q->preeditTextChanged();
1354 }
1355 QVector<QTextLayout::FormatRange> overrides;
1356 preeditCursor = e->preeditString().size();
1358 cursorVisible = true;
1359 for (int i = 0; i < e->attributes().size(); ++i) {
1360 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
1361 if (a.type == QInputMethodEvent::Cursor) {
1362 hasImState = true;
1363 preeditCursor = a.start;
1364 cursorVisible = a.length != 0;
1365 } else if (a.type == QInputMethodEvent::TextFormat) {
1366 hasImState = true;
1367 QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
1368 if (f.isValid()) {
1370 o.start = a.start + cursor.position() - block.position();
1371 o.length = a.length;
1372 o.format = f;
1373 overrides.append(o);
1374 }
1375 }
1376 }
1377 layout->setFormats(overrides);
1378 }
1379
1381
1383 if (cursor_d)
1384 cursor_d->setX();
1385 if (cursor.position() != oldCursorPos)
1386 emit q->cursorPositionChanged();
1387 q->updateCursorRectangle(oldPreeditCursor != preeditCursor || forceSelectionChanged || isGettingInput);
1388 selectionChanged(forceSelectionChanged);
1389}
1390
1391QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
1392{
1393 return inputMethodQuery(property, QVariant());
1394}
1395
1396QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property, const QVariant &argument) const
1397{
1398 Q_D(const QQuickTextControl);
1399 QTextBlock block = d->cursor.block();
1400 switch (property) {
1402 return cursorRect();
1404 return anchorRect();
1405 case Qt::ImFont:
1406 return QVariant(d->cursor.charFormat().font());
1407 case Qt::ImCursorPosition: {
1408 const QPointF pt = argument.toPointF();
1409 if (!pt.isNull())
1410 return QVariant(d->doc->documentLayout()->hitTest(pt, Qt::FuzzyHit) - block.position());
1411 return QVariant(d->cursor.position() - block.position());
1412 }
1414 return QVariant(block.text());
1416 return QVariant(d->cursor.selectedText());
1418 return QVariant(); // No limit.
1420 return QVariant(d->cursor.anchor() - block.position());
1422 return QVariant(d->cursor.position());
1424 {
1425 int maxLength = argument.isValid() ? argument.toInt() : 1024;
1426 QTextCursor tmpCursor = d->cursor;
1427 int localPos = d->cursor.position() - block.position();
1428 QString result = block.text().mid(localPos);
1429 while (result.size() < maxLength) {
1430 int currentBlock = tmpCursor.blockNumber();
1431 tmpCursor.movePosition(QTextCursor::NextBlock);
1432 if (tmpCursor.blockNumber() == currentBlock)
1433 break;
1434 result += QLatin1Char('\n') + tmpCursor.block().text();
1435 }
1436 return QVariant(result);
1437 }
1439 {
1440 int maxLength = argument.isValid() ? argument.toInt() : 1024;
1441 QTextCursor tmpCursor = d->cursor;
1442 int localPos = d->cursor.position() - block.position();
1443 int numBlocks = 0;
1444 int resultLen = localPos;
1445 while (resultLen < maxLength) {
1446 int currentBlock = tmpCursor.blockNumber();
1447 tmpCursor.movePosition(QTextCursor::PreviousBlock);
1448 if (tmpCursor.blockNumber() == currentBlock)
1449 break;
1450 numBlocks++;
1451 resultLen += tmpCursor.block().length();
1452 }
1454 while (numBlocks) {
1455 result += tmpCursor.block().text() + QLatin1Char('\n');
1456 tmpCursor.movePosition(QTextCursor::NextBlock);
1457 --numBlocks;
1458 }
1459 result += QStringView{block.text()}.mid(0,localPos);
1460 return QVariant(result);
1461 }
1462 case Qt::ImReadOnly:
1463 return QVariant(!d->interactionFlags.testFlag(Qt::TextEditable));
1464 default:
1465 return QVariant();
1466 }
1467}
1468#endif // im
1469
1471{
1472 Q_Q(QQuickTextControl);
1473 emit q->updateRequest();
1474 hasFocus = e->gotFocus();
1475 if (e->gotFocus()) {
1477 } else {
1479
1482 && e->reason() != Qt::PopupFocusReason
1483 && cursor.hasSelection()) {
1485 emit q->selectionChanged();
1486 }
1487 }
1488}
1489
1491{
1492 Q_Q(QQuickTextControl);
1493
1494 QString link;
1495 if (e->type() != QEvent::HoverLeave)
1496 link = q->anchorAt(pos);
1497
1498 if (hoveredLink != link) {
1499 hoveredLink = link;
1500 emit q->linkHovered(link);
1501 qCDebug(lcHoverTrace) << q << e->type() << pos << "hoveredLink" << hoveredLink;
1502 } else {
1503 QTextBlock block = q->blockWithMarkerAt(pos);
1504 if (block.isValid() != hoveredMarker)
1505 emit q->markerHovered(block.isValid());
1506 hoveredMarker = block.isValid();
1507 if (hoveredMarker)
1508 qCDebug(lcHoverTrace) << q << e->type() << pos << "hovered marker" << int(block.blockFormat().marker()) << block.text();
1509 }
1510}
1511
1513{
1514 Q_D(const QQuickTextControl);
1515 return d->hasImState;
1516}
1517
1519{
1520 Q_D(const QQuickTextControl);
1521 return d->overwriteMode;
1522}
1523
1525{
1526 Q_D(QQuickTextControl);
1527 if (d->overwriteMode == overwrite)
1528 return;
1529 d->overwriteMode = overwrite;
1530 emit overwriteModeChanged(overwrite);
1531}
1532
1534{
1535 Q_D(const QQuickTextControl);
1536 return d->cursorVisible;
1537}
1538
1540{
1541 Q_D(QQuickTextControl);
1542 d->cursorVisible = visible;
1543 d->setBlinkingCursorEnabled(d->cursorVisible
1544 && (d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard)));
1545}
1546
1548{
1549 Q_D(const QQuickTextControl);
1550 QRectF rect;
1551 QTextCursor cursor = d->cursor;
1552 if (!cursor.isNull()) {
1553 rect = d->rectForPosition(cursor.anchor());
1554 }
1555 return rect;
1556}
1557
1559{
1560 Q_D(const QQuickTextControl);
1561 if (cursor.isNull())
1562 return QRectF();
1563
1564 return d->rectForPosition(cursor.position());
1565}
1566
1568{
1569 Q_D(const QQuickTextControl);
1570 return cursorRect(d->cursor);
1571}
1572
1574{
1575 Q_D(const QQuickTextControl);
1576 return d->hoveredLink;
1577}
1578
1580{
1581 Q_D(const QQuickTextControl);
1582 return d->doc->documentLayout()->anchorAt(pos);
1583}
1584
1586{
1587 Q_D(const QQuickTextControl);
1588 return d->doc->documentLayout()->blockWithMarkerAt(pos);
1589}
1590
1592{
1593 Q_D(QQuickTextControl);
1594 d->acceptRichText = accept;
1595}
1596
1598{
1599 Q_D(QQuickTextControl);
1600 const QTextCursor oldSelection = d->cursor;
1601 const bool moved = d->cursor.movePosition(op, mode);
1602 d->_q_updateCurrentCharFormatAndSelection();
1604 d->repaintOldAndNewSelection(oldSelection);
1605 if (moved)
1607}
1608
1610{
1611#if QT_CONFIG(clipboard)
1612 Q_D(const QQuickTextControl);
1613 if (d->interactionFlags & Qt::TextEditable) {
1614 const QMimeData *md = QGuiApplication::clipboard()->mimeData();
1615 return md && canInsertFromMimeData(md);
1616 }
1617#endif
1618 return false;
1619}
1620
1622{
1623 Q_D(QQuickTextControl);
1624 d->cursorIsFocusIndicator = b;
1625 d->repaintCursor();
1626}
1627
1629{
1630 Q_D(QQuickTextControl);
1631 d->wordSelectionEnabled = enabled;
1632}
1633
1634#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
1635void QQuickTextControl::setTouchDragSelectionEnabled(bool enabled)
1636{
1637 Q_D(QQuickTextControl);
1638 d->selectByTouchDrag = enabled;
1639}
1640#endif
1641
1643{
1644 Q_D(const QQuickTextControl);
1645 const QTextDocumentFragment fragment(d->cursor);
1646 return new QQuickTextEditMimeData(fragment);
1647}
1648
1650{
1651 Q_D(const QQuickTextControl);
1652 if (d->acceptRichText)
1653 return source->hasText()
1654 || source->hasHtml()
1655 || source->hasFormat(QLatin1String("application/x-qrichtext"))
1656 || source->hasFormat(QLatin1String("application/x-qt-richtext"));
1657 else
1658 return source->hasText();
1659}
1660
1662{
1663 Q_D(QQuickTextControl);
1664 if (!(d->interactionFlags & Qt::TextEditable) || !source)
1665 return;
1666
1667 bool hasData = false;
1668 QTextDocumentFragment fragment;
1669#if QT_CONFIG(texthtmlparser)
1670 if (source->hasFormat(QLatin1String("application/x-qrichtext")) && d->acceptRichText) {
1671 // x-qrichtext is always UTF-8 (taken from Qt3 since we don't use it anymore).
1672 const QString richtext = QLatin1String("<meta name=\"qrichtext\" content=\"1\" />")
1673 + QString::fromUtf8(source->data(QLatin1String("application/x-qrichtext")));
1674 fragment = QTextDocumentFragment::fromHtml(richtext, d->doc);
1675 hasData = true;
1676 } else if (source->hasHtml() && d->acceptRichText) {
1677 fragment = QTextDocumentFragment::fromHtml(source->html(), d->doc);
1678 hasData = true;
1679 } else {
1680 QString text = source->text();
1681 if (!text.isNull()) {
1683 hasData = true;
1684 }
1685 }
1686#else
1687 fragment = QTextDocumentFragment::fromPlainText(source->text());
1688#endif // texthtmlparser
1689
1690 if (hasData)
1691 d->cursor.insertFragment(fragment);
1693}
1694
1696{
1697 QTextCursor oldCursor = cursor;
1698
1699 if (href.isEmpty()) {
1700 QTextCursor tmp = cursor;
1701 if (tmp.selectionStart() != tmp.position())
1702 tmp.setPosition(tmp.selectionStart());
1704 href = tmp.charFormat().anchorHref();
1705 }
1706 if (href.isEmpty())
1707 return;
1708
1709 if (!cursor.hasSelection()) {
1710 QTextBlock block = cursor.block();
1711 const int cursorPos = cursor.position();
1712
1713 QTextBlock::Iterator it = block.begin();
1714 QTextBlock::Iterator linkFragment;
1715
1716 for (; !it.atEnd(); ++it) {
1717 QTextFragment fragment = it.fragment();
1718 const int fragmentPos = fragment.position();
1719 if (fragmentPos <= cursorPos &&
1720 fragmentPos + fragment.length() > cursorPos) {
1721 linkFragment = it;
1722 break;
1723 }
1724 }
1725
1726 if (!linkFragment.atEnd()) {
1727 it = linkFragment;
1728 cursor.setPosition(it.fragment().position());
1729 if (it != block.begin()) {
1730 do {
1731 --it;
1732 QTextFragment fragment = it.fragment();
1733 if (fragment.charFormat().anchorHref() != href)
1734 break;
1735 cursor.setPosition(fragment.position());
1736 } while (it != block.begin());
1737 }
1738
1739 for (it = linkFragment; !it.atEnd(); ++it) {
1740 QTextFragment fragment = it.fragment();
1741 if (fragment.charFormat().anchorHref() != href)
1742 break;
1743 cursor.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor);
1744 }
1745 }
1746 }
1747
1748 if (hasFocus) {
1750 } else {
1751 cursorIsFocusIndicator = false;
1753 }
1754 repaintOldAndNewSelection(oldCursor);
1755
1756 emit q_func()->linkActivated(href);
1757}
1758
1759#if QT_CONFIG(im)
1760bool QQuickTextControlPrivate::isPreediting() const
1761{
1763 if (layout && !layout->preeditAreaText().isEmpty())
1764 return true;
1765
1766 return false;
1767}
1768
1769void QQuickTextControlPrivate::commitPreedit()
1770{
1771 Q_Q(QQuickTextControl);
1772
1773 if (!hasImState)
1774 return;
1775
1776 QGuiApplication::inputMethod()->commit();
1777
1778 if (!hasImState)
1779 return;
1780
1782 QCoreApplication::sendEvent(q->parent(), &event);
1783}
1784
1785void QQuickTextControlPrivate::cancelPreedit()
1786{
1787 Q_Q(QQuickTextControl);
1788
1789 if (!hasImState)
1790 return;
1791
1793
1795 QCoreApplication::sendEvent(q->parent(), &event);
1796}
1797#endif // im
1798
1800{
1801 Q_D(QQuickTextControl);
1802 if (flags == d->interactionFlags)
1803 return;
1804 d->interactionFlags = flags;
1805
1806 if (d->hasFocus)
1807 d->setBlinkingCursorEnabled(flags & (Qt::TextEditable | Qt::TextSelectableByKeyboard));
1808}
1809
1810Qt::TextInteractionFlags QQuickTextControl::textInteractionFlags() const
1811{
1812 Q_D(const QQuickTextControl);
1813 return d->interactionFlags;
1814}
1815
1817{
1818 return document()->toPlainText();
1819}
1820
1821#if QT_CONFIG(texthtmlparser)
1822QString QQuickTextControl::toHtml() const
1823{
1824 return document()->toHtml();
1825}
1826#endif
1827
1828#if QT_CONFIG(textmarkdownwriter)
1829QString QQuickTextControl::toMarkdown() const
1830{
1831 return document()->toMarkdown();
1832}
1833#endif
1834
1836{
1837 Q_D(const QQuickTextControl);
1838 return d->cursorOn;
1839}
1840
1842{
1843 Q_D(const QQuickTextControl);
1844 return d->doc->documentLayout()->hitTest(point, accuracy);
1845}
1846
1848{
1849 Q_D(const QQuickTextControl);
1850 return d->doc->documentLayout()->blockBoundingRect(block);
1851}
1852
1854{
1855#if QT_CONFIG(im)
1856 Q_D(const QQuickTextControl);
1857 QTextLayout *layout = d->cursor.block().layout();
1858 if (!layout)
1859 return QString();
1860
1861 return layout->preeditAreaText();
1862#else
1863 return QString();
1864#endif
1865}
1866
1867
1869{
1870 if (!fragment.isEmpty())
1871 return QStringList() << QString::fromLatin1("text/plain") << QString::fromLatin1("text/html")
1872#if QT_CONFIG(textodfwriter)
1873 << QString::fromLatin1("application/vnd.oasis.opendocument.text")
1874#endif
1875 ;
1876 else
1877 return QMimeData::formats();
1878}
1879
1881{
1882 if (!fragment.isEmpty())
1883 setup();
1885}
1886
1887void QQuickTextEditMimeData::setup() const
1888{
1889 QQuickTextEditMimeData *that = const_cast<QQuickTextEditMimeData *>(this);
1890#if QT_CONFIG(texthtmlparser)
1891 that->setData(QLatin1String("text/html"), fragment.toHtml().toUtf8());
1892#endif
1893#if QT_CONFIG(textodfwriter)
1894 {
1896 QTextDocumentWriter writer(&buffer, "ODF");
1897 writer.write(fragment);
1898 buffer.close();
1899 that->setData(QLatin1String("application/vnd.oasis.opendocument.text"), buffer.data());
1900 }
1901#endif
1902 that->setText(fragment.toPlainText());
1903 fragment = QTextDocumentFragment();
1904}
1905
1906
1908
1909#include "moc_qquicktextcontrol_p.cpp"
1910
1911#endif // QT_NO_TEXTCONTROL
void start(int msec, QObject *obj)
\obsolete Use chrono overload instead.
void stop()
Stops the timer.
\inmodule QtCore \reentrant
Definition qbuffer.h:16
The QClipboard class provides access to the window system clipboard.
Definition qclipboard.h:20
void setMimeData(QMimeData *data, Mode mode=Clipboard)
Sets the clipboard data to src.
bool supportsSelection() const
Returns true if the clipboard supports mouse selection; otherwise returns false.
Mode
\keyword clipboard mode
Definition qclipboard.h:27
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
\inmodule QtCore
Definition qcoreevent.h:45
virtual void setAccepted(bool accepted)
Definition qcoreevent.h:307
@ ShortcutOverride
Definition qcoreevent.h:158
@ FocusOut
Definition qcoreevent.h:67
@ InputMethod
Definition qcoreevent.h:120
@ KeyRelease
Definition qcoreevent.h:65
@ MouseMove
Definition qcoreevent.h:63
@ KeyPress
Definition qcoreevent.h:64
@ FocusIn
Definition qcoreevent.h:66
@ MouseButtonPress
Definition qcoreevent.h:60
@ HoverLeave
Definition qcoreevent.h:176
@ HoverEnter
Definition qcoreevent.h:175
@ HoverMove
Definition qcoreevent.h:177
@ MouseButtonDblClick
Definition qcoreevent.h:62
@ MouseButtonRelease
Definition qcoreevent.h:61
Type type() const
Returns the event type.
Definition qcoreevent.h:304
void ignore()
Clears the accept flag parameter of the event object, the equivalent of calling setAccepted(false).
Definition qcoreevent.h:311
void accept()
Sets the accept flag of the event object, the equivalent of calling setAccepted(true).
Definition qcoreevent.h:310
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:470
bool gotFocus() const
Returns true if type() is QEvent::FocusIn; otherwise returns false.
Definition qevent.h:475
Qt::FocusReason reason() const
Returns the reason for this focus event.
Definition qevent.cpp:1569
\reentrant \inmodule QtGui
int horizontalAdvance(const QString &, int len=-1) const
Returns the horizontal advance in pixels of the first len characters of text.
static QClipboard * clipboard()
Returns the object for interacting with the clipboard.
static QStyleHints * styleHints()
Returns the application's style hints.
static QInputMethod * inputMethod()
returns the input method.
\inmodule QtGui
Definition qevent.h:246
static bool isCommonTextEditShortcut(const QKeyEvent *ke)
quint64 timestamp() const
Returns the window system's timestamp for this event.
Definition qevent.h:58
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately before the event occurred.
Definition qevent.h:56
The QInputMethodEvent class provides parameters for input method events.
Definition qevent.h:625
const QString & preeditString() const
Returns the preedit text, i.e.
Definition qevent.h:650
int replacementLength() const
Returns the number of characters to be replaced in the preedit string.
Definition qevent.h:654
const QString & commitString() const
Returns the text that should get added to (or replace parts of) the text of the editor widget.
Definition qevent.h:652
int replacementStart() const
Returns the position at which characters are to be replaced relative from the start of the preedit st...
Definition qevent.h:653
const QList< Attribute > & attributes() const
Returns the list of attributes passed to the QInputMethodEvent constructor.
Definition qevent.h:649
The QKeyEvent class describes a key event.
Definition qevent.h:424
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately after the event occurred.
Definition qevent.cpp:1468
QString text() const
Returns the Unicode text that this key generated.
Definition qevent.h:443
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:434
constexpr const char * data() const noexcept
bool isEmpty() const override
\reimp
Definition qlayout.cpp:422
QLayout * layout() override
\reimp
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:794
\inmodule QtCore
Definition qmetatype.h:341
\inmodule QtCore
Definition qmimedata.h:16
void setData(const QString &mimetype, const QByteArray &data)
Sets the data associated with the MIME type given by mimeType to the specified data.
virtual QVariant retrieveData(const QString &mimetype, QMetaType preferredType) const
Returns a variant with the given type containing data for the MIME type specified by mimeType.
virtual QStringList formats() const
Returns a list of formats supported by the object.
\inmodule QtGui
Definition qevent.h:196
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:299
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition qobject.cpp:1389
bool setProperty(const char *name, const QVariant &value)
Sets the value of the object's name property to value.
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:404
bool isNull() const noexcept
Returns true if both the x and y coordinates are set to 0.0 (ignoring the sign); otherwise returns fa...
Definition qpoint.h:338
static bool isEventFromMouseOrTouchpad(const QPointerEvent *ev)
bool cursorMoveKeyEvent(QKeyEvent *e)
void selectionChanged(bool forceEmitSelectionChanged=false)
void setCursorPosition(const QPointF &pos)
void _q_updateCursorPosChanged(const QTextCursor &someCursor)
void mouseMoveEvent(QMouseEvent *event, const QPointF &pos)
void extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition)
void keyReleaseEvent(QKeyEvent *e)
void focusEvent(QFocusEvent *e)
QRectF rectForPosition(int position) const
void extendBlockwiseSelection(int suggestedNewPosition)
void setBlinkingCursorEnabled(bool enable)
void hoverEvent(QHoverEvent *e, const QPointF &pos)
void setContent(Qt::TextFormat format, const QString &text)
void repaintOldAndNewSelection(const QTextCursor &oldSelection)
void activateLinkUnderCursor(QString href=QString())
void mouseDoubleClickEvent(QMouseEvent *event, const QPointF &pos)
void mousePressEvent(QMouseEvent *event, const QPointF &pos)
Qt::TextInteractionFlags interactionFlags
void keyPressEvent(QKeyEvent *e)
bool sendMouseEventToInputContext(QMouseEvent *event, const QPointF &pos)
void mouseReleaseEvent(QMouseEvent *event, const QPointF &pos)
void setTextInteractionFlags(Qt::TextInteractionFlags flags)
QTextDocument * document() const
virtual QRectF blockBoundingRect(const QTextBlock &block) const
bool event(QEvent *e) override
This virtual function receives events to an object and should return true if the event e was recogniz...
void contentsChange(int from, int charsRemoved, int charsAdded)
virtual void processEvent(QEvent *e, const QTransform &transform)
virtual bool canInsertFromMimeData(const QMimeData *source) const
QString anchorAt(const QPointF &pos) const
void cursorPositionChanged()
QString hoveredLink() const
void setAcceptRichText(bool accept)
void setDocument(QTextDocument *doc)
Qt::TextInteractionFlags textInteractionFlags() const
QTextBlock blockWithMarkerAt(const QPointF &pos) const
void setHtml(const QString &text)
QString preeditText() const
virtual QMimeData * createMimeDataFromSelection() const
void cursorRectangleChanged()
void overwriteModeChanged(bool overwriteMode)
QTextCursor textCursor() const
void setCursorIsFocusIndicator(bool b)
void setCursorVisible(bool visible)
void moveCursor(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode=QTextCursor::MoveAnchor)
void timerEvent(QTimerEvent *e) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
void setPlainText(const QString &text)
virtual void insertFromMimeData(const QMimeData *source)
QString toPlainText() const
void setOverwriteMode(bool overwrite)
void setTextCursor(const QTextCursor &cursor)
QQuickTextControl(QTextDocument *doc, QObject *parent=nullptr)
void setWordSelectionEnabled(bool enabled)
void setMarkdownText(const QString &text)
virtual int hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const
void updateCursorRectangle(bool force)
QVariant retrieveData(const QString &mimeType, QMetaType type) const override
Returns a variant with the given type containing data for the MIME type specified by mimeType.
QStringList formats() const override
Returns a list of formats supported by the object.
\inmodule QtCore\reentrant
Definition qrect.h:484
Qt::MouseButton button() const
Returns the button that caused the event.
Definition qevent.h:116
Qt::MouseButtons buttons() const
Returns the button state when the event was generated.
Definition qevent.h:117
\inmodule QtCore
Definition qsize.h:208
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:994
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition qstring.cpp:5506
QByteArray toUtf8() const &
Definition qstring.h:634
void cursorFlashTimeChanged(int cursorFlashTime)
MarkerType marker() const
void setMarker(MarkerType marker)
\reentrant
iterator begin() const
Returns a text block iterator pointing to the beginning of the text block.
int length() const
Returns the length of the block in characters.
QTextBlockFormat blockFormat() const
Returns the QTextBlockFormat that describes block-specific properties.
bool isValid() const
Returns true if this text block is valid; otherwise returns false.
QTextBlock next() const
Returns the text block in the document after this block, or an empty text block if this is the last o...
QTextLayout * layout() const
Returns the QTextLayout that is used to lay out and display the block's contents.
int position() const
Returns the index of the block's first character within the document.
QString text() const
Returns the block's contents as plain text.
QString anchorHref() const
Returns the text format's hypertext link, or an empty string if none has been set.
static QTextCursorPrivate * getPrivate(QTextCursor *c)
\reentrant \inmodule QtGui
Definition qtextcursor.h:30
QTextBlockFormat blockFormat() const
Returns the block format of the block the cursor is in.
QTextCharFormat charFormat() const
Returns the format of the character immediately before the cursor position().
QTextBlock block() const
Returns the block that contains the cursor.
void beginEditBlock()
Indicates the start of a block of editing operations on the document that should appear as a single o...
bool atBlockStart() const
Returns true if the cursor is at the start of a block; otherwise returns false.
void setPosition(int pos, MoveMode mode=MoveAnchor)
Moves the cursor to the absolute position in the document specified by pos using a MoveMode specified...
int selectionStart() const
Returns the start of the selection or position() if the cursor doesn't have a selection.
bool movePosition(MoveOperation op, MoveMode=MoveAnchor, int n=1)
Moves the cursor by performing the given operation n times, using the specified mode,...
bool atBlockEnd() const
Returns true if the cursor is at the end of a block; otherwise returns false.
int anchor() const
Returns the anchor position; this is the same as position() unless there is a selection in which case...
void clearSelection()
Clears the current selection by setting the anchor to the cursor position.
bool isNull() const
Returns true if the cursor is null; otherwise returns false.
MoveMode
\value MoveAnchor Moves the anchor to the same position as the cursor itself.
Definition qtextcursor.h:47
void setBlockFormat(const QTextBlockFormat &format)
Sets the block format of the current block (or all blocks that are contained in the selection) to for...
void setCharFormat(const QTextCharFormat &format)
Sets the cursor's current character format to the given format.
bool visualNavigation() const
void removeSelectedText()
If there is a selection, its content is deleted; otherwise does nothing.
int selectionEnd() const
Returns the end of the selection or position() if the cursor doesn't have a selection.
void select(SelectionType selection)
Selects text in the document according to the given selection.
void insertText(const QString &text)
Inserts text at the current position, using the current character format.
QTextList * currentList() const
Returns the current list if the cursor position() is inside a block that is part of a list; otherwise...
void setVisualNavigation(bool b)
void insertBlock()
Inserts a new empty block at the cursor position() with the current blockFormat() and charFormat().
bool hasSelection() const
Returns true if the cursor contains a selection; otherwise returns false.
void endEditBlock()
Indicates the end of a block of editing operations on the document that should appear as a single ope...
MoveOperation
\value NoMove Keep the cursor where it is
Definition qtextcursor.h:61
void mergeBlockFormat(const QTextBlockFormat &modifier)
Modifies the block format of the current block (or all blocks that are contained in the selection) wi...
bool hasComplexSelection() const
Returns true if the cursor contains a selection that is not simply a range from selectionStart() to s...
void deletePreviousChar()
If there is no selected text, deletes the character before the current cursor position; otherwise del...
int position() const
Returns the absolute position of the cursor within the document.
void deleteChar()
If there is no selected text, deletes the character at the current cursor position; otherwise deletes...
QTextFrame * currentFrame() const
Returns a pointer to the current frame.
QString toPlainText() const
This function returns the same as toRawText(), but will replace some unicode characters with ASCII al...
bool isEmpty() const
Returns true if the fragment is empty; otherwise returns false.
static QTextDocumentFragment fromHtml(const QString &html, const QTextDocument *resourceProvider=nullptr)
static QTextDocumentFragment fromPlainText(const QString &plainText)
Returns a document fragment that contains the given plainText.
The QTextDocumentWriter class provides a format-independent interface for writing a QTextDocument to ...
\reentrant \inmodule QtGui
void setModified(bool m=true)
void contentsChange(int from, int charsRemoved, int charsAdded)
This signal is emitted whenever the document's content changes; for example, when text is inserted or...
void setHtml(const QString &html)
Replaces the entire contents of the document with the given HTML-formatted text in the html string.
QString toHtml() const
Returns a string containing an HTML representation of the document.
QAbstractTextDocumentLayout * documentLayout() const
Returns the document layout for this document.
virtual void clear()
Clears the document.
bool isUndoRedoEnabled() const
void setPageSize(const QSizeF &size)
void setUndoRedoEnabled(bool enable)
QUrl baseUrl
the base URL used to resolve relative resource URLs within the document.
QString toPlainText() const
Returns the plain text contained in the document.
QTextBlock findBlock(int pos) const
Returns the text block that contains the {pos}-th character.
void setPlainText(const QString &text)
Replaces the entire contents of the document with the given plain text.
void setBaseUrl(const QUrl &url)
QTextCharFormat toCharFormat() const
Returns this format as a character format.
void setLayoutDirection(Qt::LayoutDirection direction)
Sets the document's layout direction to the specified direction.
\reentrant
QTextCharFormat charFormat() const
Returns the text fragment's character format.
int length() const
Returns the number of characters in the text fragment.
int position() const
Returns the position of this text fragment in the document.
\reentrant
Definition qtextlayout.h:70
int lineCount() const
Returns the number of lines in this text layout.
QFont font() const
Returns the current font that is used for the layout, or a default font if none is set.
QString preeditAreaText() const
Returns the text that is inserted in the layout before editing occurs.
\reentrant
\reentrant
Definition qtextlist.h:18
\inmodule QtCore
Definition qcoreevent.h:366
int timerId() const
Returns the unique timer identifier, which is the same identifier as returned from QObject::startTime...
Definition qcoreevent.h:370
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
QTransform & translate(qreal dx, qreal dy)
Moves the coordinate system dx along the x axis and dy along the y axis, and returns a reference to t...
QUrl adjusted(FormattingOptions options) const
Definition qurl.cpp:2924
@ RemoveFilename
Definition qurl.h:116
\inmodule QtCore
Definition qvariant.h:65
QString text
QCursor cursor
void textChanged(const QString &newText)
QSet< QString >::iterator it
rect
[4]
Combined button and popup list for selecting options.
Definition qcompare.h:63
InputMethodQuery
@ ImMaximumTextLength
@ ImTextBeforeCursor
@ ImAnchorRectangle
@ ImSurroundingText
@ ImCursorPosition
@ ImCurrentSelection
@ ImAbsolutePosition
@ ImReadOnly
@ ImFont
@ ImAnchorPosition
@ ImCursorRectangle
@ ImQueryInput
@ ImTextAfterCursor
@ LeftButton
Definition qnamespace.h:58
@ MiddleButton
Definition qnamespace.h:60
@ TextSelectableByMouse
@ TextEditable
@ LinksAccessibleByMouse
@ TextSelectableByKeyboard
@ NoTextInteraction
TextFormat
@ RichText
@ MarkdownText
@ PlainText
@ LeftToRight
@ RightToLeft
HitTestAccuracy
Definition qnamespace.h:203
@ FuzzyHit
Definition qnamespace.h:203
@ ExactHit
Definition qnamespace.h:203
@ Key_Right
Definition qnamespace.h:679
@ Key_Backspace
Definition qnamespace.h:666
@ Key_Direction_L
Definition qnamespace.h:731
@ Key_Left
Definition qnamespace.h:677
@ Key_Up
Definition qnamespace.h:678
@ Key_Down
Definition qnamespace.h:680
@ Key_Direction_R
Definition qnamespace.h:732
@ Key_Back
Definition qnamespace.h:846
@ ShiftModifier
@ PopupFocusReason
@ ActiveWindowFocusReason
static jboolean copy(JNIEnv *, jobject)
QList< QString > QStringList
Constructs a string list that contains the given string, str.
#define qApp
const char * mimeType
#define qGuiApp
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLenum GLuint buffer
GLenum type
GLbitfield flags
GLboolean enable
GLint GLsizei GLsizei GLenum format
GLsizei GLsizei GLchar * source
struct _cl_event * event
GLuint GLenum GLenum transform
const GLubyte * c
GLsizei maxLength
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
#define qmlobject_disconnect(Sender, SenderType, Signal, Receiver, ReceiverType, Method)
Disconnect Signal of Sender from Method of Receiver.
#define qmlobject_connect(Sender, SenderType, Signal, Receiver, ReceiverType, Method)
Connect Signal of Sender to Method of Receiver.
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static QT_BEGIN_NAMESPACE QTextLine currentTextLine(const QTextCursor &cursor)
const int textCursorWidth
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QT_CONFIG(feature)
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
QVideoFrameFormat::PixelFormat fmt
static QTextLine currentTextLine(const QTextCursor &cursor)
#define enabled
const char property[13]
Definition qwizard.cpp:101
QList< int > list
[14]
if(qFloatDistance(a, b)<(1<< 7))
[0]
QObject::connect nullptr
QVBoxLayout * layout
myObject disconnect()
[26]
QDBusArgument argument
\inmodule QtCore \reentrant
Definition qchar.h:18