Qt 6.x
The Qt SDK
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 lastSelectionStart(-1),
85 lastSelectionEnd(-1)
86{}
87
89{
90#if !QT_CONFIG(shortcut)
91 Q_UNUSED(e);
92#endif
93
95 if (cursor.isNull())
96 return false;
97
98 const QTextCursor oldSelection = cursor;
99 const int oldCursorPos = cursor.position();
100
103
104 if (false) {
105 }
106#if QT_CONFIG(shortcut)
109 }
112 }
113 else if (e == QKeySequence::SelectNextChar) {
116 }
120 }
121 else if (e == QKeySequence::SelectNextWord) {
124 }
128 }
132 }
133 else if (e == QKeySequence::SelectEndOfLine) {
136 }
140 }
141 else if (e == QKeySequence::SelectEndOfBlock) {
144 }
148 }
150 op = QTextCursor::End;
152 }
154 op = QTextCursor::Up;
156 }
157 else if (e == QKeySequence::SelectNextLine) {
160 {
161 QTextBlock block = cursor.block();
163 if (!block.next().isValid()
164 && line.isValid()
165 && line.lineNumber() == block.layout()->lineCount() - 1)
166 op = QTextCursor::End;
167 }
168 }
169 else if (e == QKeySequence::MoveToNextWord) {
171 }
174 }
175 else if (e == QKeySequence::MoveToEndOfBlock) {
177 }
180 }
181 else if (e == QKeySequence::MoveToNextLine) {
183 }
185 op = QTextCursor::Up;
186 }
189 }
190 else if (e == QKeySequence::MoveToEndOfLine) {
192 }
195 }
197 op = QTextCursor::End;
198 }
199#endif // shortcut
200 else {
201 return false;
202 }
203
204// Except for pageup and pagedown, OS X has very different behavior, we don't do it all, but
205// here's the breakdown:
206// Shift still works as an anchor, but only one of the other keys can be down Ctrl (Command),
207// Alt (Option), or Meta (Control).
208// Command/Control + Left/Right -- Move to left or right of the line
209// + Up/Down -- Move to top bottom of the file. (Control doesn't move the cursor)
210// Option + Left/Right -- Move one word Left/right.
211// + Up/Down -- Begin/End of Paragraph.
212// Home/End Top/Bottom of file. (usually don't move the cursor, but will select)
213
214 bool visualNavigation = cursor.visualNavigation();
216 const bool moved = cursor.movePosition(op, mode);
217 cursor.setVisualNavigation(visualNavigation);
218
219 bool isNavigationEvent
220 = e->key() == Qt::Key_Up
221 || e->key() == Qt::Key_Down
222 || e->key() == Qt::Key_Left
223 || e->key() == Qt::Key_Right;
224
225 if (moved) {
226 if (cursor.position() != oldCursorPos)
227 emit q->cursorPositionChanged();
228 q->updateCursorRectangle(true);
229 } else if (isNavigationEvent && oldSelection.anchor() == cursor.anchor()) {
230 return false;
231 }
232
233 selectionChanged(/*forceEmitSelectionChanged =*/(mode == QTextCursor::KeepAnchor));
234
235 repaintOldAndNewSelection(oldSelection);
236
237 return true;
238}
239
241{
243
245 if (fmt == lastCharFormat)
246 return;
248
249 emit q->currentCharFormatChanged(fmt);
251}
252
254{
256
257#if QT_CONFIG(im)
258 cancelPreedit();
259#endif
260
261 // for use when called from setPlainText. we may want to re-use the currently
262 // set char format then.
263 const QTextCharFormat charFormatForInsertion = cursor.charFormat();
264
265 bool previousUndoRedoState = doc->isUndoRedoEnabled();
266 doc->setUndoRedoEnabled(false);
267
268 const int oldCursorPos = cursor.position();
269
270 // avoid multiple textChanged() signals being emitted
272
273 if (!text.isEmpty()) {
274 // clear 'our' cursor for insertion to prevent
275 // the emission of the cursorPositionChanged() signal.
276 // instead we emit it only once at the end instead of
277 // at the end of the document after loading and when
278 // positioning the cursor again to the start of the
279 // document.
281 if (format == Qt::PlainText) {
282 QTextCursor formatCursor(doc);
283 // put the setPlainText and the setCharFormat into one edit block,
284 // so that the syntax highlight triggers only /once/ for the entire
285 // document, not twice.
286 formatCursor.beginEditBlock();
288 doc->setUndoRedoEnabled(false);
289 formatCursor.select(QTextCursor::Document);
290 formatCursor.setCharFormat(charFormatForInsertion);
291 formatCursor.endEditBlock();
292#if QT_CONFIG(textmarkdownreader)
293 } else if (format == Qt::MarkdownText) {
295 doc->setMarkdown(text);
296#endif
297 } else {
298#if QT_CONFIG(texthtmlparser)
299 doc->setHtml(text);
300#else
302#endif
303 doc->setUndoRedoEnabled(false);
304 }
306 } else {
307 doc->clear();
308 }
309 cursor.setCharFormat(charFormatForInsertion);
310
312 emit q->textChanged();
313 doc->setUndoRedoEnabled(previousUndoRedoState);
315 doc->setModified(false);
316
317 q->updateCursorRectangle(true);
318 if (cursor.position() != oldCursorPos)
319 emit q->cursorPositionChanged();
320}
321
323{
325 const int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
326 if (cursorPos == -1)
327 return;
328 cursor.setPosition(cursorPos);
329}
330
332{
334
338 }
339}
340
342{
344 emit q->updateCursorRequest();
345}
346
348{
350 if (cursor.hasSelection()
351 && oldSelection.hasSelection()
352 && cursor.currentFrame() == oldSelection.currentFrame()
354 && !oldSelection.hasComplexSelection()
355 && cursor.anchor() == oldSelection.anchor()
356 ) {
357 QTextCursor differenceSelection(doc);
358 differenceSelection.setPosition(oldSelection.position());
359 differenceSelection.setPosition(cursor.position(), QTextCursor::KeepAnchor);
360 emit q->updateRequest();
361 } else {
362 if (!oldSelection.hasSelection() && !cursor.hasSelection()) {
363 if (!oldSelection.isNull())
364 emit q->updateCursorRequest();
365 emit q->updateCursorRequest();
366
367 } else {
368 if (!oldSelection.isNull())
369 emit q->updateRequest();
370 emit q->updateRequest();
371 }
372 }
373}
374
375void QQuickTextControlPrivate::selectionChanged(bool forceEmitSelectionChanged /*=false*/)
376{
378 if (forceEmitSelectionChanged) {
379#if QT_CONFIG(im)
380 if (hasFocus)
381 qGuiApp->inputMethod()->update(Qt::ImCurrentSelection);
382#endif
383 emit q->selectionChanged();
384 }
385
386 bool current = cursor.hasSelection();
387 int selectionStart = cursor.selectionStart();
388 int selectionEnd = cursor.selectionEnd();
389 if (current == lastSelectionState && (!current || (selectionStart == lastSelectionStart && selectionEnd == lastSelectionEnd)))
390 return;
391
392 if (lastSelectionState != current) {
393 lastSelectionState = current;
394 emit q->copyAvailable(current);
395 }
396
397 lastSelectionStart = selectionStart;
398 lastSelectionEnd = selectionEnd;
399
400 if (!forceEmitSelectionChanged) {
401#if QT_CONFIG(im)
402 if (hasFocus)
403 qGuiApp->inputMethod()->update(Qt::ImCurrentSelection);
404#endif
405 emit q->selectionChanged();
406 }
407 q->updateCursorRectangle(true);
408}
409
411{
414}
415
416#if QT_CONFIG(clipboard)
417void QQuickTextControlPrivate::setClipboardSelection()
418{
420 if (!cursor.hasSelection() || !clipboard->supportsSelection())
421 return;
423 QMimeData *data = q->createMimeDataFromSelection();
425}
426#endif
427
429{
431 if (someCursor.isCopyOf(cursor)) {
432 emit q->cursorPositionChanged();
433 q->updateCursorRectangle(true);
434 }
435}
436
438{
440 return;
441
444
445 if (enable)
447 else
449}
450
452{
453 // Note: cursorOn represents the current blinking state controlled by a timer, and
454 // should not be confused with cursorVisible or cursorBlinkingEnabled. However, we
455 // interpretate a cursorFlashTime of 0 to mean "always on, never blink".
456 cursorOn = true;
457 int flashTime = QGuiApplication::styleHints()->cursorFlashTime();
458
459 if (cursorBlinkingEnabled && flashTime >= 2)
460 cursorBlinkTimer.start(flashTime / 2, q_func());
461 else
463
465}
466
467void QQuickTextControlPrivate::extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition)
468{
470
471 // if inside the initial selected word keep that
472 if (suggestedNewPosition >= selectedWordOnDoubleClick.selectionStart()
473 && suggestedNewPosition <= selectedWordOnDoubleClick.selectionEnd()) {
474 q->setTextCursor(selectedWordOnDoubleClick);
475 return;
476 }
477
479 curs.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
480
482 return;
483 const int wordStartPos = curs.position();
484
485 const int blockPos = curs.block().position();
486 const QPointF blockCoordinates = q->blockBoundingRect(curs.block()).topLeft();
487
489 if (!line.isValid())
490 return;
491
492 const qreal wordStartX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x();
493
495 return;
496 const int wordEndPos = curs.position();
497
498 const QTextLine otherLine = currentTextLine(curs);
499 if (otherLine.textStart() != line.textStart()
500 || wordEndPos == wordStartPos)
501 return;
502
503 const qreal wordEndX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x();
504
505 if (!wordSelectionEnabled && (mouseXPosition < wordStartX || mouseXPosition > wordEndX))
506 return;
507
508 if (suggestedNewPosition < selectedWordOnDoubleClick.position()) {
511 } else {
514 }
515
517#if QT_CONFIG(clipboard)
518 setClipboardSelection();
519#endif
520 selectionChanged(true);
521 }
522}
523
525{
527
528 // if inside the initial selected line keep that
529 if (suggestedNewPosition >= selectedBlockOnTripleClick.selectionStart()
530 && suggestedNewPosition <= selectedBlockOnTripleClick.selectionEnd()) {
531 q->setTextCursor(selectedBlockOnTripleClick);
532 return;
533 }
534
535 if (suggestedNewPosition < selectedBlockOnTripleClick.position()) {
537 cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
539 } else {
541 cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor);
544 }
545
547#if QT_CONFIG(clipboard)
548 setClipboardSelection();
549#endif
550 selectionChanged(true);
551 }
552}
553
555{
557 d->repaintSelection();
558 const int oldCursorPos = d->cursor.position();
559 d->doc->undo(&d->cursor);
560 if (d->cursor.position() != oldCursorPos)
563}
564
566{
568 d->repaintSelection();
569 const int oldCursorPos = d->cursor.position();
570 d->doc->redo(&d->cursor);
571 if (d->cursor.position() != oldCursorPos)
574}
575
577{
579 d->cursor.select(QTextCursor::Document);
580 d->cursor.removeSelectedText();
581}
582
585{
587 Q_ASSERT(doc);
588
592 qmlobject_connect(doc, QTextDocument, SIGNAL(contentsChanged()), this, QQuickTextControl, SIGNAL(textChanged()));
593 qmlobject_connect(doc, QTextDocument, SIGNAL(contentsChanged()), this, QQuickTextControl, SLOT(_q_updateCurrentCharFormatAndSelection()));
596
597 layout->setProperty("cursorWidth", textCursorWidth);
598
599 d->doc = doc;
600 d->cursor = QTextCursor(doc);
601 d->lastCharFormat = d->cursor.charFormat();
602 doc->setPageSize(QSizeF(0, 0));
603 doc->setModified(false);
604 doc->setUndoRedoEnabled(true);
605}
606
608{
609}
610
612{
613 Q_D(const QQuickTextControl);
614 return d->doc;
615}
616
618{
620 const bool update = d->cursorRectangleChanged || force;
621 d->cursorRectangleChanged = false;
622 if (update)
624}
625
627{
629#if QT_CONFIG(im)
630 d->commitPreedit();
631#endif
632 d->cursorIsFocusIndicator = false;
633 const bool posChanged = cursor.position() != d->cursor.position();
634 const QTextCursor oldSelection = d->cursor;
635 d->cursor = cursor;
636 d->cursorOn = d->hasFocus && (d->interactionFlags & Qt::TextEditable);
637 d->_q_updateCurrentCharFormatAndSelection();
639 d->repaintOldAndNewSelection(oldSelection);
640 if (posChanged)
642}
643
645{
646 Q_D(const QQuickTextControl);
647 return d->cursor;
648}
649
650#if QT_CONFIG(clipboard)
651
652void QQuickTextControl::cut()
653{
655 if (!(d->interactionFlags & Qt::TextEditable) || !d->cursor.hasSelection())
656 return;
657 copy();
658 d->cursor.removeSelectedText();
659}
660
661void QQuickTextControl::copy()
662{
664 if (!d->cursor.hasSelection())
665 return;
668}
669
670void QQuickTextControl::paste(QClipboard::Mode mode)
671{
673 if (md)
675}
676#endif
677
679{
681 const int selectionLength = qAbs(d->cursor.position() - d->cursor.anchor());
682 d->cursor.select(QTextCursor::Document);
683 d->selectionChanged(selectionLength != qAbs(d->cursor.position() - d->cursor.anchor()));
684 d->cursorIsFocusIndicator = false;
686}
687
688void QQuickTextControl::processEvent(QEvent *e, const QPointF &coordinateOffset)
689{
691 t.translate(coordinateOffset.x(), coordinateOffset.y());
692 processEvent(e, t);
693}
694
696{
698 if (d->interactionFlags == Qt::NoTextInteraction) {
699 e->ignore();
700 return;
701 }
702
703 switch (e->type()) {
704 case QEvent::KeyPress:
705 d->keyPressEvent(static_cast<QKeyEvent *>(e));
706 break;
708 d->keyReleaseEvent(static_cast<QKeyEvent *>(e));
709 break;
711 QMouseEvent *ev = static_cast<QMouseEvent *>(e);
712 d->mousePressEvent(ev, transform.map(ev->position()));
713 break; }
714 case QEvent::MouseMove: {
715 QMouseEvent *ev = static_cast<QMouseEvent *>(e);
716 d->mouseMoveEvent(ev, transform.map(ev->position()));
717 break; }
719 QMouseEvent *ev = static_cast<QMouseEvent *>(e);
720 d->mouseReleaseEvent(ev, transform.map(ev->position()));
721 break; }
723 QMouseEvent *ev = static_cast<QMouseEvent *>(e);
724 d->mouseDoubleClickEvent(ev, transform.map(ev->position()));
725 break; }
728 case QEvent::HoverLeave: {
729 QHoverEvent *ev = static_cast<QHoverEvent *>(e);
730 d->hoverEvent(ev, transform.map(ev->position()));
731 break; }
732#if QT_CONFIG(im)
734 d->inputMethodEvent(static_cast<QInputMethodEvent *>(e));
735 break;
736#endif
737 case QEvent::FocusIn:
738 case QEvent::FocusOut:
739 d->focusEvent(static_cast<QFocusEvent *>(e));
740 break;
741
743 if (d->interactionFlags & Qt::TextEditable) {
744 QKeyEvent* ke = static_cast<QKeyEvent *>(e);
746 }
747 break;
748 default:
749 break;
750 }
751}
752
754{
755 return QObject::event(e);
756}
757
759{
761 if (e->timerId() == d->cursorBlinkTimer.timerId()) {
762 d->cursorOn = !d->cursorOn;
763
764 d->repaintCursor();
765 }
766}
767
769{
771 d->setContent(Qt::PlainText, text);
772}
773
775{
777 d->setContent(Qt::MarkdownText, text);
778}
779
781{
783 d->setContent(Qt::RichText, text);
784}
785
786
788{
789 e->ignore();
790}
791
793{
795
796 if (e->key() == Qt::Key_Back) {
797 e->ignore();
798 return;
799 }
800
801#if QT_CONFIG(shortcut)
802 if (e == QKeySequence::SelectAll) {
803 e->accept();
804 q->selectAll();
805#if QT_CONFIG(clipboard)
806 setClipboardSelection();
807#endif
808 return;
809 }
810#if QT_CONFIG(clipboard)
811 else if (e == QKeySequence::Copy) {
812 e->accept();
813 q->copy();
814 return;
815 }
816#endif
817#endif // shortcut
818
821 goto accept;
822
824 e->ignore();
825 return;
826 }
827
828 if (e->key() == Qt::Key_Direction_L || e->key() == Qt::Key_Direction_R) {
830 fmt.setLayoutDirection((e->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
832 goto accept;
833 }
834
835 // schedule a repaint of the region of the cursor, as when we move it we
836 // want to make sure the old cursor disappears (not noticeable when moving
837 // only a few pixels but noticeable when jumping between cells in tables for
838 // example)
840
841 if (e->key() == Qt::Key_Backspace && !(e->modifiers() & ~Qt::ShiftModifier)) {
844 if (list && cursor.atBlockStart() && !cursor.hasSelection()) {
846 } else if (cursor.atBlockStart() && blockFmt.indent() > 0) {
847 blockFmt.setIndent(blockFmt.indent() - 1);
848 cursor.setBlockFormat(blockFmt);
849 } else {
850 QTextCursor localCursor = cursor;
851 localCursor.deletePreviousChar();
852 }
853 goto accept;
854 }
855#if QT_CONFIG(shortcut)
858 e->accept();
859 goto accept;
860 } else if (e == QKeySequence::InsertLineSeparator) {
862 e->accept();
863 goto accept;
864 }
865#endif
866 if (false) {
867 }
868#if QT_CONFIG(shortcut)
869 else if (e == QKeySequence::Undo) {
870 q->undo();
871 }
872 else if (e == QKeySequence::Redo) {
873 q->redo();
874 }
875#if QT_CONFIG(clipboard)
876 else if (e == QKeySequence::Cut) {
877 q->cut();
878 }
879 else if (e == QKeySequence::Paste) {
881 q->paste(mode);
882 }
883#endif
884 else if (e == QKeySequence::Delete) {
885 QTextCursor localCursor = cursor;
886 localCursor.deleteChar();
887 }
888 else if (e == QKeySequence::DeleteEndOfWord) {
889 if (!cursor.hasSelection())
892 }
894 if (!cursor.hasSelection())
897 }
898 else if (e == QKeySequence::DeleteEndOfLine) {
899 QTextBlock block = cursor.block();
900 if (cursor.position() == block.position() + block.length() - 2)
902 else
905 }
906#endif // shortcut
907 else {
908 goto process;
909 }
910 goto accept;
911
912process:
913 {
914 if (q->isAcceptableInput(e)) {
915#if QT_CONFIG(im)
916 // QTBUG-90362
917 // Before key press event will be handled, pre-editing part should be finished
918 if (isPreediting())
919 commitPreedit();
920#endif
921 if (overwriteMode
922 // no need to call deleteChar() if we have a selection, insertText
923 // does it already
924 && !cursor.hasSelection()
925 && !cursor.atBlockEnd()) {
927 }
928
929 cursor.insertText(e->text());
931 } else {
932 e->ignore();
933 return;
934 }
935 }
936
937 accept:
938
939#if QT_CONFIG(clipboard)
940 setClipboardSelection();
941#endif
942
943 e->accept();
944 cursorOn = true;
945
946 q->updateCursorRectangle(true);
948}
949
951{
952 Q_Q(const QQuickTextControl);
953 const QTextBlock block = doc->findBlock(position);
954 if (!block.isValid())
955 return QRectF();
956 const QTextLayout *layout = block.layout();
957 const QPointF layoutPos = q->blockBoundingRect(block).topLeft();
958 int relativePos = position - block.position();
959#if QT_CONFIG(im)
960 if (preeditCursor != 0) {
961 int preeditPos = layout->preeditAreaPosition();
962 if (relativePos == preeditPos)
963 relativePos += preeditCursor;
964 else if (relativePos > preeditPos)
965 relativePos += layout->preeditAreaText().size();
966 }
967#endif
968 QTextLine line = layout->lineForTextPosition(relativePos);
969
970 QRectF r;
971
972 if (line.isValid()) {
973 qreal x = line.cursorToX(relativePos);
974 qreal w = 0;
975 if (overwriteMode) {
976 if (relativePos < line.textLength() - line.textStart())
977 w = line.cursorToX(relativePos + 1) - x;
978 else
979 w = QFontMetrics(block.layout()->font()).horizontalAdvance(QLatin1Char(' ')); // in sync with QTextLine::draw()
980 }
981 r = QRectF(layoutPos.x() + x, layoutPos.y() + line.y(), textCursorWidth + w, line.height());
982 } else {
983 r = QRectF(layoutPos.x(), layoutPos.y(), textCursorWidth, 10); // #### correct height
984 }
985
986 return r;
987}
988
990{
992
994 mousePressPos = pos.toPoint();
995
997 return;
998
1000 anchorOnMousePress = q->anchorAt(pos);
1001
1003 cursorIsFocusIndicator = false;
1006 }
1007 }
1008
1010 return;
1012 blockWithMarkerUnderMousePress = q->blockWithMarkerAt(pos);
1013 if (e->button() & Qt::MiddleButton) {
1014 return;
1015 } else if (!(e->button() & Qt::LeftButton)) {
1016 e->ignore();
1017 return;
1020 e->ignore();
1021 return;
1022 }
1023
1024 cursorIsFocusIndicator = false;
1025 const QTextCursor oldSelection = cursor;
1026 const int oldCursorPos = cursor.position();
1027
1028#if QT_CONFIG(im)
1029 commitPreedit();
1030#endif
1031
1033 && ((pos - tripleClickPoint).toPoint().manhattanLength() < QGuiApplication::styleHints()->startDragDistance())) {
1034
1039
1041
1042 timestampAtLastDoubleClick = 0; // do not enter this condition in case of 4(!) rapid clicks
1043 } else {
1044 int cursorPos = q->hitTest(pos, Qt::FuzzyHit);
1045 if (cursorPos == -1) {
1046 e->ignore();
1047 return;
1048 }
1049
1054 }
1055
1057 extendBlockwiseSelection(cursorPos);
1059 extendWordwiseSelection(cursorPos, pos.x());
1060 else if (!wordSelectionEnabled)
1062 } else {
1063 setCursorPosition(cursorPos);
1064 }
1065 }
1066
1067 if (cursor.position() != oldCursorPos) {
1068 q->updateCursorRectangle(true);
1069 emit q->cursorPositionChanged();
1070 }
1073 else
1075 repaintOldAndNewSelection(oldSelection);
1077}
1078
1080{
1082 return;
1083
1084 Q_Q(QQuickTextControl);
1085
1086 if ((e->buttons() & Qt::LeftButton)) {
1087 const bool editable = interactionFlags & Qt::TextEditable;
1088
1089 if (!(mousePressed
1090 || editable
1093 return;
1094
1095 const QTextCursor oldSelection = cursor;
1096 const int oldCursorPos = cursor.position();
1097
1098 if (!mousePressed)
1099 return;
1100
1101 const qreal mouseX = qreal(mousePos.x());
1102
1103 int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1104
1105#if QT_CONFIG(im)
1106 if (isPreediting()) {
1107 // note: oldCursorPos not including preedit
1108 int selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1109 if (newCursorPos != selectionStartPos) {
1110 commitPreedit();
1111 // commit invalidates positions
1112 newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit);
1113 selectionStartPos = q->hitTest(mousePressPos, Qt::FuzzyHit);
1114 setCursorPosition(selectionStartPos);
1115 }
1116 }
1117#endif
1118
1119 if (newCursorPos == -1)
1120 return;
1121
1125 }
1126
1128 extendBlockwiseSelection(newCursorPos);
1130 extendWordwiseSelection(newCursorPos, mouseX);
1131#if QT_CONFIG(im)
1132 else if (!isPreediting())
1134#endif
1135
1137 if (cursor.position() != oldCursorPos) {
1138 emit q->cursorPositionChanged();
1139 }
1141#if QT_CONFIG(im)
1142 if (qGuiApp)
1143 qGuiApp->inputMethod()->update(Qt::ImQueryInput);
1144#endif
1145 } else if (cursor.position() != oldCursorPos) {
1146 emit q->cursorPositionChanged();
1147 }
1148 selectionChanged(true);
1149 repaintOldAndNewSelection(oldSelection);
1150 }
1151
1153}
1154
1156{
1157 Q_Q(QQuickTextControl);
1158
1160 return;
1161
1162 const QTextCursor oldSelection = cursor;
1163 const int oldCursorPos = cursor.position();
1165
1166 if (mousePressed) {
1167 mousePressed = false;
1168#if QT_CONFIG(clipboard)
1169 setClipboardSelection();
1170 selectionChanged(true);
1171 } else if (e->button() == Qt::MiddleButton
1176 if (md)
1177 q->insertFromMimeData(md);
1178#endif
1179 }
1180 if (!isMouse && !selectByTouchDrag && interactionFlags.testFlag(Qt::TextEditable))
1182
1183 repaintOldAndNewSelection(oldSelection);
1184
1185 if (cursor.position() != oldCursorPos) {
1186 emit q->cursorPositionChanged();
1187 q->updateCursorRectangle(true);
1188 }
1189
1190 if ((isMouse || selectByTouchDrag) && interactionFlags.testFlag(Qt::TextEditable) &&
1192 QTextBlock block = q->blockWithMarkerAt(pos);
1193 if (block == blockWithMarkerUnderMousePress) {
1194 auto fmt = block.blockFormat();
1195 fmt.setMarker(fmt.marker() == QTextBlockFormat::MarkerType::Unchecked ?
1198 }
1199 }
1200
1202 if (!(e->button() & Qt::LeftButton))
1203 return;
1204
1205 const QString anchor = q->anchorAt(pos);
1206
1207 if (anchor.isEmpty())
1208 return;
1209
1210 if (!cursor.hasSelection()
1211 || (anchor == anchorOnMousePress && hadSelectionOnMousePress)) {
1212
1213 const int anchorPos = q->hitTest(pos, Qt::ExactHit);
1214 if (anchorPos != -1) {
1215 cursor.setPosition(anchorPos);
1216
1217 QString anchor = anchorOnMousePress;
1220 }
1221 }
1222 }
1223}
1224
1226{
1227 Q_Q(QQuickTextControl);
1228
1231#if QT_CONFIG(im)
1232 commitPreedit();
1233#endif
1234
1235 const QTextCursor oldSelection = cursor;
1238 bool doEmit = false;
1239 if (line.isValid() && line.textLength()) {
1241 doEmit = true;
1242 }
1243 repaintOldAndNewSelection(oldSelection);
1244
1245 cursorIsFocusIndicator = false;
1247
1249 timestampAtLastDoubleClick = e->timestamp();
1250 if (doEmit) {
1252#if QT_CONFIG(clipboard)
1253 setClipboardSelection();
1254#endif
1255 emit q->cursorPositionChanged();
1256 q->updateCursorRectangle(true);
1257 }
1258 } else if (!sendMouseEventToInputContext(e, pos)) {
1259 e->ignore();
1260 }
1261}
1262
1264{
1265#if QT_CONFIG(im)
1266 Q_Q(QQuickTextControl);
1267
1268 Q_UNUSED(e);
1269
1270 if (isPreediting()) {
1272 int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position();
1273
1274 if (cursorPos >= 0 && cursorPos <= layout->preeditAreaText().size()) {
1275 if (e->type() == QEvent::MouseButtonRelease) {
1277 }
1278
1279 return true;
1280 }
1281 }
1282#else
1283 Q_UNUSED(e);
1284 Q_UNUSED(pos);
1285#endif
1286 return false;
1287}
1288
1289#if QT_CONFIG(im)
1290void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
1291{
1292 Q_Q(QQuickTextControl);
1293 if (cursor.isNull()) {
1294 e->ignore();
1295 return;
1296 }
1297 bool textEditable = interactionFlags.testFlag(Qt::TextEditable);
1298 bool isGettingInput = !e->commitString().isEmpty()
1299 || e->preeditString() != cursor.block().layout()->preeditAreaText()
1300 || e->replacementLength() > 0;
1301 bool forceSelectionChanged = false;
1302 int oldCursorPos = cursor.position();
1303
1305 if (isGettingInput && textEditable) {
1307 }
1308
1309 QTextBlock block;
1310
1311 // insert commit string
1312 if (textEditable && (!e->commitString().isEmpty() || e->replacementLength())) {
1313 if (e->commitString().endsWith(QChar::LineFeed))
1314 block = cursor.block(); // Remember the block where the preedit text is
1316 c.setPosition(c.position() + e->replacementStart());
1317 c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor);
1318 c.insertText(e->commitString());
1319 }
1320
1322 for (int i = 0; i < e->attributes().size(); ++i) {
1323 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
1324 if (a.type == QInputMethodEvent::Selection) {
1325 QTextCursor oldCursor = cursor;
1326 int blockStart = a.start + cursor.block().position();
1328 cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
1329 repaintOldAndNewSelection(oldCursor);
1330 forceSelectionChanged = true;
1331 }
1332 }
1333 }
1334
1335 if (!block.isValid())
1336 block = cursor.block();
1337
1338 const int oldPreeditCursor = preeditCursor;
1339 if (textEditable) {
1340 QTextLayout *layout = block.layout();
1341 if (isGettingInput) {
1342 layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
1343 emit q->preeditTextChanged();
1344 }
1346 preeditCursor = e->preeditString().size();
1347 hasImState = !e->preeditString().isEmpty();
1348 cursorVisible = true;
1349 for (int i = 0; i < e->attributes().size(); ++i) {
1350 const QInputMethodEvent::Attribute &a = e->attributes().at(i);
1351 if (a.type == QInputMethodEvent::Cursor) {
1352 hasImState = true;
1353 preeditCursor = a.start;
1354 cursorVisible = a.length != 0;
1355 } else if (a.type == QInputMethodEvent::TextFormat) {
1356 hasImState = true;
1357 QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
1358 if (f.isValid()) {
1360 o.start = a.start + cursor.position() - block.position();
1361 o.length = a.length;
1362 o.format = f;
1363 overrides.append(o);
1364 }
1365 }
1366 }
1367 layout->setFormats(overrides);
1368 }
1369
1371
1373 if (cursor_d)
1374 cursor_d->setX();
1375 if (cursor.position() != oldCursorPos)
1376 emit q->cursorPositionChanged();
1377 q->updateCursorRectangle(oldPreeditCursor != preeditCursor || forceSelectionChanged || isGettingInput);
1378 selectionChanged(forceSelectionChanged);
1379}
1380
1381QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
1382{
1383 return inputMethodQuery(property, QVariant());
1384}
1385
1386QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property, const QVariant &argument) const
1387{
1388 Q_D(const QQuickTextControl);
1389 QTextBlock block = d->cursor.block();
1390 switch (property) {
1392 return cursorRect();
1394 return anchorRect();
1395 case Qt::ImFont:
1396 return QVariant(d->cursor.charFormat().font());
1397 case Qt::ImCursorPosition: {
1398 const QPointF pt = argument.toPointF();
1399 if (!pt.isNull())
1400 return QVariant(d->doc->documentLayout()->hitTest(pt, Qt::FuzzyHit) - block.position());
1401 return QVariant(d->cursor.position() - block.position());
1402 }
1404 return QVariant(block.text());
1406 return QVariant(d->cursor.selectedText());
1408 return QVariant(); // No limit.
1410 return QVariant(d->cursor.anchor() - block.position());
1412 return QVariant(d->cursor.position());
1414 {
1415 int maxLength = argument.isValid() ? argument.toInt() : 1024;
1416 QTextCursor tmpCursor = d->cursor;
1417 int localPos = d->cursor.position() - block.position();
1418 QString result = block.text().mid(localPos);
1419 while (result.size() < maxLength) {
1420 int currentBlock = tmpCursor.blockNumber();
1422 if (tmpCursor.blockNumber() == currentBlock)
1423 break;
1424 result += QLatin1Char('\n') + tmpCursor.block().text();
1425 }
1426 return QVariant(result);
1427 }
1429 {
1430 int maxLength = argument.isValid() ? argument.toInt() : 1024;
1431 QTextCursor tmpCursor = d->cursor;
1432 int localPos = d->cursor.position() - block.position();
1433 int numBlocks = 0;
1434 int resultLen = localPos;
1435 while (resultLen < maxLength) {
1436 int currentBlock = tmpCursor.blockNumber();
1438 if (tmpCursor.blockNumber() == currentBlock)
1439 break;
1440 numBlocks++;
1441 resultLen += tmpCursor.block().length();
1442 }
1444 while (numBlocks) {
1445 result += tmpCursor.block().text() + QLatin1Char('\n');
1447 --numBlocks;
1448 }
1449 result += QStringView{block.text()}.mid(0,localPos);
1450 return QVariant(result);
1451 }
1452 case Qt::ImReadOnly:
1453 return QVariant(!d->interactionFlags.testFlag(Qt::TextEditable));
1454 default:
1455 return QVariant();
1456 }
1457}
1458#endif // im
1459
1461{
1462 Q_Q(QQuickTextControl);
1463 emit q->updateRequest();
1464 hasFocus = e->gotFocus();
1465 if (e->gotFocus()) {
1467 } else {
1469
1471 && e->reason() != Qt::ActiveWindowFocusReason
1472 && e->reason() != Qt::PopupFocusReason
1473 && cursor.hasSelection()) {
1475 emit q->selectionChanged();
1476 }
1477 }
1478}
1479
1481{
1482 Q_Q(QQuickTextControl);
1483
1484 QString link;
1485 if (e->type() != QEvent::HoverLeave)
1486 link = q->anchorAt(pos);
1487
1488 if (hoveredLink != link) {
1489 hoveredLink = link;
1490 emit q->linkHovered(link);
1491 qCDebug(lcHoverTrace) << q << e->type() << pos << "hoveredLink" << hoveredLink;
1492 } else {
1493 QTextBlock block = q->blockWithMarkerAt(pos);
1494 if (block.isValid() != hoveredMarker)
1495 emit q->markerHovered(block.isValid());
1496 hoveredMarker = block.isValid();
1497 if (hoveredMarker)
1498 qCDebug(lcHoverTrace) << q << e->type() << pos << "hovered marker" << int(block.blockFormat().marker()) << block.text();
1499 }
1500}
1501
1503{
1504 Q_D(const QQuickTextControl);
1505 return d->hasImState;
1506}
1507
1509{
1510 Q_D(const QQuickTextControl);
1511 return d->overwriteMode;
1512}
1513
1515{
1516 Q_D(QQuickTextControl);
1517 if (d->overwriteMode == overwrite)
1518 return;
1519 d->overwriteMode = overwrite;
1520 emit overwriteModeChanged(overwrite);
1521}
1522
1524{
1525 Q_D(const QQuickTextControl);
1526 return d->cursorVisible;
1527}
1528
1530{
1531 Q_D(QQuickTextControl);
1532 d->cursorVisible = visible;
1533 d->setBlinkingCursorEnabled(d->cursorVisible
1534 && (d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard)));
1535}
1536
1538{
1539 Q_D(const QQuickTextControl);
1540 QRectF rect;
1541 QTextCursor cursor = d->cursor;
1542 if (!cursor.isNull()) {
1543 rect = d->rectForPosition(cursor.anchor());
1544 }
1545 return rect;
1546}
1547
1549{
1550 Q_D(const QQuickTextControl);
1551 if (cursor.isNull())
1552 return QRectF();
1553
1554 return d->rectForPosition(cursor.position());
1555}
1556
1558{
1559 Q_D(const QQuickTextControl);
1560 return cursorRect(d->cursor);
1561}
1562
1564{
1565 Q_D(const QQuickTextControl);
1566 return d->hoveredLink;
1567}
1568
1570{
1571 Q_D(const QQuickTextControl);
1572 return d->doc->documentLayout()->anchorAt(pos);
1573}
1574
1576{
1577 Q_D(const QQuickTextControl);
1578 return d->doc->documentLayout()->blockWithMarkerAt(pos);
1579}
1580
1582{
1583 Q_D(QQuickTextControl);
1584 d->acceptRichText = accept;
1585}
1586
1588{
1589 Q_D(QQuickTextControl);
1590 const QTextCursor oldSelection = d->cursor;
1591 const bool moved = d->cursor.movePosition(op, mode);
1592 d->_q_updateCurrentCharFormatAndSelection();
1594 d->repaintOldAndNewSelection(oldSelection);
1595 if (moved)
1597}
1598
1600{
1601#if QT_CONFIG(clipboard)
1602 Q_D(const QQuickTextControl);
1603 if (d->interactionFlags & Qt::TextEditable) {
1605 return md && canInsertFromMimeData(md);
1606 }
1607#endif
1608 return false;
1609}
1610
1612{
1613 Q_D(QQuickTextControl);
1614 d->cursorIsFocusIndicator = b;
1615 d->repaintCursor();
1616}
1617
1619{
1620 Q_D(QQuickTextControl);
1621 d->wordSelectionEnabled = enabled;
1622}
1623
1624#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
1625void QQuickTextControl::setTouchDragSelectionEnabled(bool enabled)
1626{
1627 Q_D(QQuickTextControl);
1628 d->selectByTouchDrag = enabled;
1629}
1630#endif
1631
1633{
1634 Q_D(const QQuickTextControl);
1635 const QTextDocumentFragment fragment(d->cursor);
1636 return new QQuickTextEditMimeData(fragment);
1637}
1638
1640{
1641 Q_D(const QQuickTextControl);
1642 if (d->acceptRichText)
1643 return source->hasText()
1644 || source->hasHtml()
1645 || source->hasFormat(QLatin1String("application/x-qrichtext"))
1646 || source->hasFormat(QLatin1String("application/x-qt-richtext"));
1647 else
1648 return source->hasText();
1649}
1650
1652{
1653 Q_D(QQuickTextControl);
1654 if (!(d->interactionFlags & Qt::TextEditable) || !source)
1655 return;
1656
1657 bool hasData = false;
1658 QTextDocumentFragment fragment;
1659#if QT_CONFIG(texthtmlparser)
1660 if (source->hasFormat(QLatin1String("application/x-qrichtext")) && d->acceptRichText) {
1661 // x-qrichtext is always UTF-8 (taken from Qt3 since we don't use it anymore).
1662 const QString richtext = QLatin1String("<meta name=\"qrichtext\" content=\"1\" />")
1663 + QString::fromUtf8(source->data(QLatin1String("application/x-qrichtext")));
1664 fragment = QTextDocumentFragment::fromHtml(richtext, d->doc);
1665 hasData = true;
1666 } else if (source->hasHtml() && d->acceptRichText) {
1667 fragment = QTextDocumentFragment::fromHtml(source->html(), d->doc);
1668 hasData = true;
1669 } else {
1670 QString text = source->text();
1671 if (!text.isNull()) {
1673 hasData = true;
1674 }
1675 }
1676#else
1677 fragment = QTextDocumentFragment::fromPlainText(source->text());
1678#endif // texthtmlparser
1679
1680 if (hasData)
1681 d->cursor.insertFragment(fragment);
1683}
1684
1686{
1687 QTextCursor oldCursor = cursor;
1688
1689 if (href.isEmpty()) {
1690 QTextCursor tmp = cursor;
1691 if (tmp.selectionStart() != tmp.position())
1692 tmp.setPosition(tmp.selectionStart());
1694 href = tmp.charFormat().anchorHref();
1695 }
1696 if (href.isEmpty())
1697 return;
1698
1699 if (!cursor.hasSelection()) {
1700 QTextBlock block = cursor.block();
1701 const int cursorPos = cursor.position();
1702
1703 QTextBlock::Iterator it = block.begin();
1704 QTextBlock::Iterator linkFragment;
1705
1706 for (; !it.atEnd(); ++it) {
1707 QTextFragment fragment = it.fragment();
1708 const int fragmentPos = fragment.position();
1709 if (fragmentPos <= cursorPos &&
1710 fragmentPos + fragment.length() > cursorPos) {
1711 linkFragment = it;
1712 break;
1713 }
1714 }
1715
1716 if (!linkFragment.atEnd()) {
1717 it = linkFragment;
1718 cursor.setPosition(it.fragment().position());
1719 if (it != block.begin()) {
1720 do {
1721 --it;
1722 QTextFragment fragment = it.fragment();
1723 if (fragment.charFormat().anchorHref() != href)
1724 break;
1725 cursor.setPosition(fragment.position());
1726 } while (it != block.begin());
1727 }
1728
1729 for (it = linkFragment; !it.atEnd(); ++it) {
1730 QTextFragment fragment = it.fragment();
1731 if (fragment.charFormat().anchorHref() != href)
1732 break;
1733 cursor.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor);
1734 }
1735 }
1736 }
1737
1738 if (hasFocus) {
1740 } else {
1741 cursorIsFocusIndicator = false;
1743 }
1744 repaintOldAndNewSelection(oldCursor);
1745
1746 emit q_func()->linkActivated(href);
1747}
1748
1749#if QT_CONFIG(im)
1750bool QQuickTextControlPrivate::isPreediting() const
1751{
1753 if (layout && !layout->preeditAreaText().isEmpty())
1754 return true;
1755
1756 return false;
1757}
1758
1759void QQuickTextControlPrivate::commitPreedit()
1760{
1761 Q_Q(QQuickTextControl);
1762
1763 if (!hasImState)
1764 return;
1765
1767
1768 if (!hasImState)
1769 return;
1770
1772 QCoreApplication::sendEvent(q->parent(), &event);
1773}
1774
1775void QQuickTextControlPrivate::cancelPreedit()
1776{
1777 Q_Q(QQuickTextControl);
1778
1779 if (!hasImState)
1780 return;
1781
1783
1785 QCoreApplication::sendEvent(q->parent(), &event);
1786}
1787#endif // im
1788
1790{
1791 Q_D(QQuickTextControl);
1792 if (flags == d->interactionFlags)
1793 return;
1794 d->interactionFlags = flags;
1795
1796 if (d->hasFocus)
1797 d->setBlinkingCursorEnabled(flags & (Qt::TextEditable | Qt::TextSelectableByKeyboard));
1798}
1799
1800Qt::TextInteractionFlags QQuickTextControl::textInteractionFlags() const
1801{
1802 Q_D(const QQuickTextControl);
1803 return d->interactionFlags;
1804}
1805
1807{
1808 return document()->toPlainText();
1809}
1810
1811#if QT_CONFIG(texthtmlparser)
1812QString QQuickTextControl::toHtml() const
1813{
1814 return document()->toHtml();
1815}
1816#endif
1817
1818#if QT_CONFIG(textmarkdownwriter)
1819QString QQuickTextControl::toMarkdown() const
1820{
1821 return document()->toMarkdown();
1822}
1823#endif
1824
1826{
1827 Q_D(const QQuickTextControl);
1828 return d->cursorOn;
1829}
1830
1832{
1833 Q_D(const QQuickTextControl);
1834 return d->doc->documentLayout()->hitTest(point, accuracy);
1835}
1836
1838{
1839 Q_D(const QQuickTextControl);
1840 return d->doc->documentLayout()->blockBoundingRect(block);
1841}
1842
1844{
1845#if QT_CONFIG(im)
1846 Q_D(const QQuickTextControl);
1847 QTextLayout *layout = d->cursor.block().layout();
1848 if (!layout)
1849 return QString();
1850
1851 return layout->preeditAreaText();
1852#else
1853 return QString();
1854#endif
1855}
1856
1857
1859{
1860 if (!fragment.isEmpty())
1861 return QStringList() << QString::fromLatin1("text/plain") << QString::fromLatin1("text/html")
1862#if QT_CONFIG(textodfwriter)
1863 << QString::fromLatin1("application/vnd.oasis.opendocument.text")
1864#endif
1865 ;
1866 else
1867 return QMimeData::formats();
1868}
1869
1871{
1872 if (!fragment.isEmpty())
1873 setup();
1875}
1876
1877void QQuickTextEditMimeData::setup() const
1878{
1879 QQuickTextEditMimeData *that = const_cast<QQuickTextEditMimeData *>(this);
1880#if QT_CONFIG(texthtmlparser)
1881 that->setData(QLatin1String("text/html"), fragment.toHtml().toUtf8());
1882#endif
1883#if QT_CONFIG(textodfwriter)
1884 {
1886 QTextDocumentWriter writer(&buffer, "ODF");
1887 writer.write(fragment);
1888 buffer.close();
1889 that->setData(QLatin1String("application/vnd.oasis.opendocument.text"), buffer.data());
1890 }
1891#endif
1892 that->setText(fragment.toPlainText());
1893 fragment = QTextDocumentFragment();
1894}
1895
1896
1898
1899#include "moc_qquicktextcontrol_p.cpp"
1900
1901#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
@ LineSeparator
Definition qchar.h:64
@ LineFeed
Definition qchar.h:53
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.
const QMimeData * mimeData(Mode mode=Clipboard) const
Returns a pointer to a QMimeData representation of the current clipboard data (can be \nullptr if the...
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:302
@ 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
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:469
\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:245
static bool isCommonTextEditShortcut(const QKeyEvent *ke)
The QInputMethodEvent class provides parameters for input method events.
Definition qevent.h:624
void commit()
Commits the word user is currently composing to the editor.
void invokeAction(Action a, int cursorPosition)
Called by the input item when the word currently being composed is tapped by the user,...
void reset()
Resets the input method state.
The QKeyEvent class describes a key event.
Definition qevent.h:423
constexpr const char * data() const noexcept
bool isEmpty() const override
\reimp
Definition qlayout.cpp:422
Definition qlist.h:74
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:787
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtCore
Definition qmetatype.h:320
\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.
void setText(const QString &text)
Sets text as the plain text (MIME type text/plain) used to represent the 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:195
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:298
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
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:1363
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:214
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:333
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:338
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:328
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)
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:483
QPointF position() const
Returns the position of the point in this event, relative to the widget or item that received the eve...
Definition qevent.h:118
\inmodule QtCore
Definition qsize.h:207
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:898
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QByteArray toUtf8() const &
Definition qstring.h:563
int startDragDistance
the distance, in pixels, that the mouse must be moved with a button held down before a drag and drop ...
Definition qstylehints.h:39
void cursorFlashTimeChanged(int cursorFlashTime)
int mouseDoubleClickInterval
the time limit in milliseconds that distinguishes a double click from two consecutive mouse clicks.
Definition qstylehints.h:29
int cursorFlashTime
the text cursor's flash (blink) time in milliseconds.
Definition qstylehints.h:20
MarkerType marker() const
void setIndent(int indent)
Sets the paragraph's indentation.
int indent() const
Returns the paragraph's indent.
bool atEnd() const
Returns true if the current item is the last item in the text block.
\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...
int blockNumber() const
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)
bool isCopyOf(const QTextCursor &other) const
Returns true if this cursor and other are copies of each other, i.e.
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.
\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
int textStart() const
Returns the start of the line from the beginning of the string passed to the QTextLayout.
\reentrant
Definition qtextlist.h:18
\inmodule QtCore
Definition qcoreevent.h:359
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
QUrl adjusted(FormattingOptions options) const
Definition qurl.cpp:2921
@ RemoveFilename
Definition qurl.h:116
\inmodule QtCore
Definition qvariant.h:64
QString text
QCursor cursor
void textChanged(const QString &newText)
double e
QSet< QString >::iterator it
rect
[4]
Combined button and popup list for selecting options.
InputMethodQuery
@ ImMaximumTextLength
@ ImTextBeforeCursor
@ ImAnchorRectangle
@ ImSurroundingText
@ ImCursorPosition
@ ImCurrentSelection
@ ImAbsolutePosition
@ ImReadOnly
@ ImFont
@ ImAnchorPosition
@ ImCursorRectangle
@ ImQueryInput
@ ImTextAfterCursor
@ LeftButton
Definition qnamespace.h:57
@ MiddleButton
Definition qnamespace.h:59
@ TextSelectableByMouse
@ TextEditable
@ LinksAccessibleByMouse
@ TextSelectableByKeyboard
@ NoTextInteraction
TextFormat
@ RichText
@ MarkdownText
@ PlainText
@ LeftToRight
@ RightToLeft
HitTestAccuracy
Definition qnamespace.h:202
@ FuzzyHit
Definition qnamespace.h:202
@ ExactHit
Definition qnamespace.h:202
@ Key_Right
Definition qnamespace.h:674
@ Key_Backspace
Definition qnamespace.h:661
@ Key_Direction_L
Definition qnamespace.h:726
@ Key_Left
Definition qnamespace.h:672
@ Key_Up
Definition qnamespace.h:673
@ Key_Down
Definition qnamespace.h:675
@ Key_Direction_R
Definition qnamespace.h:727
@ Key_Back
Definition qnamespace.h:841
@ ShiftModifier
@ PopupFocusReason
@ ActiveWindowFocusReason
static jboolean copy(JNIEnv *, jobject)
#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:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
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]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLenum GLuint buffer
GLenum type
GLbitfield flags
GLboolean enable
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
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:92
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:17
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent