Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquicktextedit.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
4#include "qquicktextedit_p.h"
8#include "qquickevents_p_p.h"
9#include "qquickwindow.h"
10#include "qquicktextnode_p.h"
12
13#include <QtCore/qmath.h>
14#include <QtGui/qguiapplication.h>
15#include <QtGui/qevent.h>
16#include <QtGui/qpainter.h>
17#include <QtGui/qtextobject.h>
18#include <QtGui/qtexttable.h>
19#include <QtQml/qqmlinfo.h>
20#include <QtQuick/qsgsimplerectnode.h>
21
22#include <private/qqmlglobal_p.h>
23#include <private/qqmlproperty_p.h>
24#include <private/qtextengine_p.h>
25#include <private/qsgadaptationlayer_p.h>
26
27#include "qquicktextdocument.h"
28
29#include <algorithm>
30
32
34Q_LOGGING_CATEGORY(lcTextEdit, "qt.quick.textedit")
35
36
93// This is a pretty arbitrary figure. The idea is that we don't want to break down the document
94// into text nodes corresponding to a text block each so that the glyph node grouping doesn't become pointless.
95static const int nodeBreakingSize = 300;
96
97#if !defined(QQUICKTEXT_LARGETEXT_THRESHOLD)
98 #define QQUICKTEXT_LARGETEXT_THRESHOLD 10000
99#endif
100// if QString::size() > largeTextSizeThreshold, we render more often, but only visible lines
102
103namespace {
104 class RootNode : public QSGTransformNode
105 {
106 public:
107 RootNode() : cursorNode(nullptr), frameDecorationsNode(nullptr)
108 { }
109
110 void resetFrameDecorations(QQuickTextNode* newNode)
111 {
112 if (frameDecorationsNode) {
113 removeChildNode(frameDecorationsNode);
114 delete frameDecorationsNode;
115 }
116 frameDecorationsNode = newNode;
118 }
119
120 void resetCursorNode(QSGInternalRectangleNode* newNode)
121 {
122 if (cursorNode)
123 removeChildNode(cursorNode);
124 delete cursorNode;
125 cursorNode = newNode;
126 if (cursorNode) {
127 appendChildNode(cursorNode);
128 cursorNode->setFlag(QSGNode::OwnedByParent);
129 }
130 }
131
132 QSGInternalRectangleNode *cursorNode;
133 QQuickTextNode* frameDecorationsNode;
134
135 };
136}
137
140{
141 Q_D(QQuickTextEdit);
142 d->init();
143}
144
147{
148 Q_D(QQuickTextEdit);
149 d->init();
150}
151
153{
154 Q_D(const QQuickTextEdit);
155 if (!d->textCached && isComponentComplete()) {
156 QQuickTextEditPrivate *d = const_cast<QQuickTextEditPrivate *>(d_func());
157#if QT_CONFIG(texthtmlparser)
158 if (d->richText)
159 d->text = d->control->toHtml();
160 else
161#endif
162#if QT_CONFIG(textmarkdownwriter)
163 if (d->markdownText)
164 d->text = d->control->toMarkdown();
165 else
166#endif
167 d->text = d->control->toPlainText();
168 d->textCached = true;
169 }
170 return d->text;
171}
172
381{
382 Q_D(QQuickTextEdit);
383 if (QQuickTextEdit::text() == text)
384 return;
385
386 d->document->clearResources();
387 d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text));
388 d->markdownText = d->format == MarkdownText;
389 if (!isComponentComplete()) {
390 d->text = text;
391 } else if (d->richText) {
392#if QT_CONFIG(texthtmlparser)
393 d->control->setHtml(text);
394#else
395 d->control->setPlainText(text);
396#endif
397 } else if (d->markdownText) {
398 d->control->setMarkdownText(text);
399 } else {
400 d->control->setPlainText(text);
401 }
403}
404
406{
407 QMetaObject::invokeMethod(this, &QQuickTextEdit::q_invalidate);
408}
409
410void QQuickTextEdit::q_invalidate()
411{
412 Q_D(QQuickTextEdit);
413 if (isComponentComplete()) {
414 if (d->document != nullptr)
415 d->document->markContentsDirty(0, d->document->characterCount());
416 invalidateFontCaches();
418 update();
419 }
420}
421
435{
436 Q_D(const QQuickTextEdit);
437 return d->control->preeditText();
438}
439
482{
483 Q_D(const QQuickTextEdit);
484 return d->format;
485}
486
488{
489 Q_D(QQuickTextEdit);
490 if (format == d->format)
491 return;
492
493 const bool wasRich = d->richText;
494 const bool wasMarkdown = d->markdownText;
495 d->richText = format == RichText || (format == AutoText && (wasRich || Qt::mightBeRichText(text())));
496 d->markdownText = format == MarkdownText;
497
498 if (isComponentComplete()) {
499#if QT_CONFIG(texthtmlparser)
500 if (wasRich && !d->richText && !d->markdownText) {
501 d->control->setPlainText(!d->textCached ? d->control->toHtml() : d->text);
502 updateSize();
503 } else if (!wasRich && d->richText) {
504 d->control->setHtml(!d->textCached ? d->control->toPlainText() : d->text);
505 updateSize();
506 }
507#endif
508#if QT_CONFIG(textmarkdownwriter) && QT_CONFIG(textmarkdownreader)
509 if (wasMarkdown && !d->markdownText && !d->richText) {
510 d->control->setPlainText(!d->textCached ? d->control->toMarkdown() : d->text);
511 updateSize();
512 } else if (!wasMarkdown && d->markdownText) {
513 d->control->setMarkdownText(!d->textCached ? d->control->toPlainText() : d->text);
514 updateSize();
515 }
516#endif
517 }
518
519 d->format = format;
520 d->control->setAcceptRichText(d->format != PlainText);
521 emit textFormatChanged(d->format);
522}
523
542{
543 Q_D(const QQuickTextEdit);
544 return d->renderType;
545}
546
548{
549 Q_D(QQuickTextEdit);
550 if (d->renderType == renderType)
551 return;
552
553 d->renderType = renderType;
555 d->updateDefaultTextOption();
556
558 updateSize();
559}
560
562{
563 Q_D(const QQuickTextEdit);
564 return d->sourceFont;
565}
566
568{
569 Q_D(QQuickTextEdit);
570 if (d->sourceFont == font)
571 return;
572
573 d->sourceFont = font;
574 QFont oldFont = d->font;
575 d->font = font;
576 if (d->font.pointSizeF() != -1) {
577 // 0.5pt resolution
578 qreal size = qRound(d->font.pointSizeF()*2.0);
579 d->font.setPointSizeF(size/2.0);
580 }
581
582 if (oldFont != d->font) {
583 d->document->setDefaultFont(d->font);
584 if (d->cursorItem) {
585 d->cursorItem->setHeight(QFontMetrics(d->font).height());
586 moveCursorDelegate();
587 }
588 updateSize();
589 updateWholeDocument();
590#if QT_CONFIG(im)
592#endif
593 }
594 emit fontChanged(d->sourceFont);
595}
596
613{
614 Q_D(const QQuickTextEdit);
615 return d->color;
616}
617
619{
620 Q_D(QQuickTextEdit);
621 if (d->color == color)
622 return;
623
624 d->color = color;
625 updateWholeDocument();
626 emit colorChanged(d->color);
627}
628
635{
636 Q_D(const QQuickTextEdit);
637 return d->selectionColor;
638}
639
641{
642 Q_D(QQuickTextEdit);
643 if (d->selectionColor == color)
644 return;
645
646 d->selectionColor = color;
647 updateWholeDocument();
648 emit selectionColorChanged(d->selectionColor);
649}
650
657{
658 Q_D(const QQuickTextEdit);
659 return d->selectedTextColor;
660}
661
663{
664 Q_D(QQuickTextEdit);
665 if (d->selectedTextColor == color)
666 return;
667
668 d->selectedTextColor = color;
669 updateWholeDocument();
670 emit selectedTextColorChanged(d->selectedTextColor);
671}
672
706{
707 Q_D(const QQuickTextEdit);
708 return d->hAlign;
709}
710
712{
713 Q_D(QQuickTextEdit);
714 bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
715 d->hAlignImplicit = false;
716 if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
717 d->updateDefaultTextOption();
718 updateSize();
719 }
720}
721
723{
724 Q_D(QQuickTextEdit);
725 d->hAlignImplicit = true;
726 if (d->determineHorizontalAlignment() && isComponentComplete()) {
727 d->updateDefaultTextOption();
728 updateSize();
729 }
730}
731
733{
734 Q_D(const QQuickTextEdit);
735 QQuickTextEdit::HAlignment effectiveAlignment = d->hAlign;
736 if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
737 switch (d->hAlign) {
739 effectiveAlignment = QQuickTextEdit::AlignRight;
740 break;
742 effectiveAlignment = QQuickTextEdit::AlignLeft;
743 break;
744 default:
745 break;
746 }
747 }
748 return effectiveAlignment;
749}
750
752{
753 Q_Q(QQuickTextEdit);
754 if (hAlign != alignment || forceAlign) {
755 QQuickTextEdit::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
757 emit q->horizontalAlignmentChanged(alignment);
758 if (oldEffectiveHAlign != q->effectiveHAlign())
759 emit q->effectiveHorizontalAlignmentChanged();
760 return true;
761 }
762 return false;
763}
764
765
767{
768 const QChar *character = text.constData();
769 while (!character->isNull()) {
770 switch (character->direction()) {
771 case QChar::DirL:
772 return Qt::LeftToRight;
773 case QChar::DirR:
774 case QChar::DirAL:
775 case QChar::DirAN:
776 return Qt::RightToLeft;
777 default:
778 break;
779 }
780 character++;
781 }
783}
784
786{
787 Q_Q(QQuickTextEdit);
788 if (hAlignImplicit && q->isComponentComplete()) {
790#if QT_CONFIG(im)
792 const QString preeditText = control->textCursor().block().layout()->preeditAreaText();
793 direction = textDirection(preeditText);
794 }
796 direction = qGuiApp->inputMethod()->inputDirection();
797#endif
798
800 }
801 return false;
802}
803
805{
806 Q_Q(QQuickTextEdit);
807 if (q->isComponentComplete()) {
810 q->updateSize();
811 emit q->effectiveHorizontalAlignmentChanged();
812 }
813 }
814}
815
817{
818 Q_Q(QQuickTextEdit);
819 qCDebug(lcVP) << q << "sees that" << transformedItem << "moved in VP" << q->clipRect();
820
821 // If there's a lot of text, and the TextEdit has been scrolled so that the viewport
822 // no longer completely covers the rendered region, we need QQuickTextEdit::updatePaintNode()
823 // to re-iterate blocks and populate a different range.
825 if (QQuickItem *viewport = q->viewportItem()) {
826 QRectF vp = q->mapRectFromItem(viewport, viewport->clipRect());
827 if (!(vp.top() > renderedRegion.top() && vp.bottom() < renderedRegion.bottom())) {
828 qCDebug(lcVP) << "viewport" << vp << "now goes beyond rendered region" << renderedRegion << "; updating";
829 q->updateWholeDocument();
830 }
831 const bool textCursorVisible = cursorVisible && q->cursorRectangle().intersects(vp);
832 if (cursorItem)
833 cursorItem->setVisible(textCursorVisible);
834 else
835 control->setCursorVisible(textCursorVisible);
836 }
837 }
839}
840
841#if QT_CONFIG(im)
842Qt::InputMethodHints QQuickTextEditPrivate::effectiveInputMethodHints() const
843{
844 return inputMethodHints | Qt::ImhMultiLine;
845}
846#endif
847
849{
850 Q_Q(QQuickTextEdit);
851 qreal oldPadding = q->topPadding();
852 if (!reset || extra.isAllocated()) {
853 extra.value().topPadding = value;
854 extra.value().explicitTopPadding = !reset;
855 }
856 if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
857 q->updateSize();
858 q->updateWholeDocument();
859 emit q->topPaddingChanged();
860 }
861}
862
864{
865 Q_Q(QQuickTextEdit);
866 qreal oldPadding = q->leftPadding();
867 if (!reset || extra.isAllocated()) {
868 extra.value().leftPadding = value;
869 extra.value().explicitLeftPadding = !reset;
870 }
871 if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
872 q->updateSize();
873 q->updateWholeDocument();
874 emit q->leftPaddingChanged();
875 }
876}
877
879{
880 Q_Q(QQuickTextEdit);
881 qreal oldPadding = q->rightPadding();
882 if (!reset || extra.isAllocated()) {
883 extra.value().rightPadding = value;
884 extra.value().explicitRightPadding = !reset;
885 }
886 if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
887 q->updateSize();
888 q->updateWholeDocument();
889 emit q->rightPaddingChanged();
890 }
891}
892
894{
895 Q_Q(QQuickTextEdit);
896 qreal oldPadding = q->bottomPadding();
897 if (!reset || extra.isAllocated()) {
898 extra.value().bottomPadding = value;
899 extra.value().explicitBottomPadding = !reset;
900 }
901 if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
902 q->updateSize();
903 q->updateWholeDocument();
904 emit q->bottomPaddingChanged();
905 }
906}
907
909{
910 return !extra.isAllocated() || extra->implicitResize;
911}
912
914{
915 if (!enabled)
916 extra.value().implicitResize = false;
917 else if (extra.isAllocated())
918 extra->implicitResize = true;
919}
920
922{
923 Q_D(const QQuickTextEdit);
924 return d->vAlign;
925}
926
928{
929 Q_D(QQuickTextEdit);
930 if (alignment == d->vAlign)
931 return;
932 d->vAlign = alignment;
933 d->updateDefaultTextOption();
934 updateSize();
935 moveCursorDelegate();
937}
938
960{
961 Q_D(const QQuickTextEdit);
962 return d->wrapMode;
963}
964
966{
967 Q_D(QQuickTextEdit);
968 if (mode == d->wrapMode)
969 return;
970 d->wrapMode = mode;
971 d->updateDefaultTextOption();
972 updateSize();
974}
975
982{
983 Q_D(const QQuickTextEdit);
984 return d->lineCount;
985}
986
1000{
1001 Q_D(const QQuickTextEdit);
1002 // QTextDocument::characterCount() includes the terminating null character.
1003 return qMax(0, d->document->characterCount() - 1);
1004}
1005
1013{
1014 Q_D(const QQuickTextEdit);
1015 return d->contentSize.width();
1016}
1017
1025{
1026 Q_D(const QQuickTextEdit);
1027 return d->contentSize.height();
1028}
1029
1040{
1041 Q_D(const QQuickTextEdit);
1042 if (d->baseUrl.isEmpty()) {
1043 if (QQmlContext *context = qmlContext(this))
1044 const_cast<QQuickTextEditPrivate *>(d)->baseUrl = context->baseUrl();
1045 }
1046 return d->baseUrl;
1047}
1048
1050{
1051 Q_D(QQuickTextEdit);
1052 if (baseUrl() != url) {
1053 d->baseUrl = url;
1054
1055 d->document->setBaseUrl(url);
1057 }
1058}
1059
1061{
1062 if (QQmlContext *context = qmlContext(this))
1063 setBaseUrl(context->baseUrl());
1064 else
1065 setBaseUrl(QUrl());
1066}
1067
1076{
1077 Q_D(const QQuickTextEdit);
1078 QTextCursor c(d->document);
1079 c.setPosition(pos);
1080 return d->control->cursorRect(c).translated(d->xoff, d->yoff);
1081
1082}
1083
1093{
1094 Q_D(const QQuickTextEdit);
1095 x -= d->xoff;
1096 y -= d->yoff;
1097
1098 int r = d->document->documentLayout()->hitTest(QPointF(x, y), Qt::FuzzyHit);
1099#if QT_CONFIG(im)
1100 QTextCursor cursor = d->control->textCursor();
1101 if (r > cursor.position()) {
1102 // The cursor position includes positions within the preedit text, but only positions in the
1103 // same text block are offset so it is possible to get a position that is either part of the
1104 // preedit or the next text block.
1105 QTextLayout *layout = cursor.block().layout();
1106 const int preeditLength = layout
1107 ? layout->preeditAreaText().size()
1108 : 0;
1109 if (preeditLength > 0
1110 && d->document->documentLayout()->blockBoundingRect(cursor.block()).contains(x, y)) {
1111 r = r > cursor.position() + preeditLength
1112 ? r - preeditLength
1113 : cursor.position();
1114 }
1115 }
1116#endif
1117 return r;
1118}
1119
1157{
1158 //Note that this is the same as setCursorPosition but with the KeepAnchor flag set
1159 Q_D(QQuickTextEdit);
1160 QTextCursor cursor = d->control->textCursor();
1161 if (cursor.position() == pos)
1162 return;
1163 cursor.setPosition(pos, QTextCursor::KeepAnchor);
1164 d->control->setTextCursor(cursor);
1165}
1166
1168{
1169 Q_D(QQuickTextEdit);
1170 QTextCursor cursor = d->control->textCursor();
1171 if (cursor.position() == pos)
1172 return;
1173 if (mode == SelectCharacters) {
1174 cursor.setPosition(pos, QTextCursor::KeepAnchor);
1175 } else if (cursor.anchor() < pos || (cursor.anchor() == pos && cursor.position() < pos)) {
1176 if (cursor.anchor() > cursor.position()) {
1177 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
1179 if (cursor.position() == cursor.anchor())
1181 else
1182 cursor.setPosition(cursor.position(), QTextCursor::MoveAnchor);
1183 } else {
1184 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
1186 }
1187
1188 cursor.setPosition(pos, QTextCursor::KeepAnchor);
1190 if (cursor.position() != pos)
1192 } else if (cursor.anchor() > pos || (cursor.anchor() == pos && cursor.position() > pos)) {
1193 if (cursor.anchor() < cursor.position()) {
1194 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
1196 } else {
1197 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
1200 if (cursor.position() != cursor.anchor()) {
1201 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
1203 }
1204 }
1205
1206 cursor.setPosition(pos, QTextCursor::KeepAnchor);
1208 if (cursor.position() != pos) {
1211 }
1212 }
1213 d->control->setTextCursor(cursor);
1214}
1215
1224{
1225 Q_D(const QQuickTextEdit);
1226 return d->cursorVisible;
1227}
1228
1230{
1231 Q_D(QQuickTextEdit);
1232 if (d->cursorVisible == on)
1233 return;
1234 d->cursorVisible = on;
1235 if (on && isComponentComplete())
1237 if (!on && !d->persistentSelection)
1238 d->control->setCursorIsFocusIndicator(true);
1239 d->control->setCursorVisible(on);
1240 emit cursorVisibleChanged(d->cursorVisible);
1241}
1242
1256{
1257 Q_D(const QQuickTextEdit);
1258 return d->control->textCursor().position();
1259}
1260
1262{
1263 Q_D(QQuickTextEdit);
1264 if (pos < 0 || pos >= d->document->characterCount()) // characterCount includes the terminating null.
1265 return;
1266 QTextCursor cursor = d->control->textCursor();
1267 if (cursor.position() == pos && cursor.anchor() == pos)
1268 return;
1269 cursor.setPosition(pos);
1270 d->control->setTextCursor(cursor);
1271 d->control->updateCursorRectangle(true);
1272}
1273
1288{
1289 Q_D(const QQuickTextEdit);
1290 return d->cursorComponent;
1291}
1292
1294{
1295 Q_D(QQuickTextEdit);
1297}
1298
1299void QQuickTextEdit::createCursor()
1300{
1301 Q_D(QQuickTextEdit);
1302 d->cursorPending = true;
1304}
1305
1317{
1318 Q_D(const QQuickTextEdit);
1319 return d->control->textCursor().selectionStart();
1320}
1321
1333{
1334 Q_D(const QQuickTextEdit);
1335 return d->control->textCursor().selectionEnd();
1336}
1337
1353{
1354 Q_D(const QQuickTextEdit);
1355#if QT_CONFIG(texthtmlparser)
1356 return d->richText || d->markdownText
1357 ? d->control->textCursor().selectedText()
1358 : d->control->textCursor().selection().toPlainText();
1359#else
1360 return d->control->textCursor().selection().toPlainText();
1361#endif
1362}
1363
1371{
1372 Q_D(const QQuickTextEdit);
1373 return d->focusOnPress;
1374}
1375
1377{
1378 Q_D(QQuickTextEdit);
1379 if (d->focusOnPress == on)
1380 return;
1381 d->focusOnPress = on;
1382 emit activeFocusOnPressChanged(d->focusOnPress);
1383}
1384
1392{
1393 Q_D(const QQuickTextEdit);
1394 return d->persistentSelection;
1395}
1396
1398{
1399 Q_D(QQuickTextEdit);
1400 if (d->persistentSelection == on)
1401 return;
1402 d->persistentSelection = on;
1403 emit persistentSelectionChanged(d->persistentSelection);
1404}
1405
1412{
1413 Q_D(const QQuickTextEdit);
1414 return d->textMargin;
1415}
1416
1418{
1419 Q_D(QQuickTextEdit);
1420 if (d->textMargin == margin)
1421 return;
1422 d->textMargin = margin;
1423 d->document->setDocumentMargin(d->textMargin);
1424 emit textMarginChanged(d->textMargin);
1425}
1426
1464Qt::InputMethodHints QQuickTextEdit::inputMethodHints() const
1465{
1466#if !QT_CONFIG(im)
1467 return Qt::ImhNone;
1468#else
1469 Q_D(const QQuickTextEdit);
1470 return d->inputMethodHints;
1471#endif // im
1472}
1473
1474void QQuickTextEdit::setInputMethodHints(Qt::InputMethodHints hints)
1475{
1476#if !QT_CONFIG(im)
1477 Q_UNUSED(hints);
1478#else
1479 Q_D(QQuickTextEdit);
1480
1481 if (hints == d->inputMethodHints)
1482 return;
1483
1484 d->inputMethodHints = hints;
1485 updateInputMethod(Qt::ImHints);
1487#endif // im
1488}
1489
1490void QQuickTextEdit::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
1491{
1492 Q_D(QQuickTextEdit);
1493 if (!d->inLayout && ((newGeometry.width() != oldGeometry.width() && widthValid())
1494 || (newGeometry.height() != oldGeometry.height() && heightValid()))) {
1495 updateSize();
1496 updateWholeDocument();
1497 moveCursorDelegate();
1498 }
1499 QQuickImplicitSizeItem::geometryChange(newGeometry, oldGeometry);
1500
1501}
1502
1508{
1509 Q_D(QQuickTextEdit);
1511
1512 const QUrl url = baseUrl();
1513 const QQmlContext *context = qmlContext(this);
1514 d->document->setBaseUrl(context ? context->resolvedUrl(url) : url);
1515#if QT_CONFIG(texthtmlparser)
1516 if (d->richText)
1517 d->control->setHtml(d->text);
1518 else
1519#endif
1520#if QT_CONFIG(textmarkdownreader)
1521 if (d->markdownText)
1522 d->control->setMarkdownText(d->text);
1523 else
1524#endif
1525 if (!d->text.isEmpty()) {
1526 if (d->markdownText)
1527 d->control->setMarkdownText(d->text);
1528 else
1529 d->control->setPlainText(d->text);
1530 }
1531
1532 if (d->dirty) {
1533 d->determineHorizontalAlignment();
1534 d->updateDefaultTextOption();
1535 updateSize();
1536 d->dirty = false;
1537 }
1538 if (d->cursorComponent && isCursorVisible())
1540 polish();
1541}
1542
1558{
1559 Q_D(const QQuickTextEdit);
1560 if (d->selectByKeyboardSet)
1561 return d->selectByKeyboard;
1562 return !isReadOnly();
1563}
1564
1566{
1567 Q_D(QQuickTextEdit);
1568 bool was = selectByKeyboard();
1569 if (!d->selectByKeyboardSet || was != on) {
1570 d->selectByKeyboardSet = true;
1571 d->selectByKeyboard = on;
1572 if (on)
1573 d->control->setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByKeyboard);
1574 else
1575 d->control->setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByKeyboard);
1576 emit selectByKeyboardChanged(on);
1577 }
1578}
1579
1604{
1605 Q_D(const QQuickTextEdit);
1606 return d->selectByMouse;
1607}
1608
1610{
1611 Q_D(QQuickTextEdit);
1612 if (d->selectByMouse == on)
1613 return;
1614
1615 d->selectByMouse = on;
1616 setKeepMouseGrab(on);
1617 if (on)
1618 d->control->setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByMouse);
1619 else
1620 d->control->setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse);
1621
1622#if QT_CONFIG(cursor)
1623 d->updateMouseCursorShape();
1624#endif
1626}
1627
1639{
1640 Q_D(const QQuickTextEdit);
1641 return d->mouseSelectionMode;
1642}
1643
1645{
1646 Q_D(QQuickTextEdit);
1647 if (d->mouseSelectionMode != mode) {
1648 d->mouseSelectionMode = mode;
1649 d->control->setWordSelectionEnabled(mode == SelectWords);
1651 }
1652}
1653
1663{
1664 Q_D(QQuickTextEdit);
1665 if (r == isReadOnly())
1666 return;
1667
1668#if QT_CONFIG(im)
1669 setFlag(QQuickItem::ItemAcceptsInputMethod, !r);
1670#endif
1671 Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse;
1672 if (d->selectByMouse)
1674 if (d->selectByKeyboardSet && d->selectByKeyboard)
1676 else if (!d->selectByKeyboardSet && !r)
1678 if (!r)
1680 d->control->setTextInteractionFlags(flags);
1681 d->control->moveCursor(QTextCursor::End);
1682
1683#if QT_CONFIG(im)
1684 updateInputMethod(Qt::ImEnabled);
1685#endif
1686#if QT_CONFIG(cursor)
1687 d->updateMouseCursorShape();
1688#endif
1689 q_canPasteChanged();
1691 if (!d->selectByKeyboardSet)
1692 emit selectByKeyboardChanged(!r);
1693 if (r) {
1694 setCursorVisible(false);
1695 } else if (hasActiveFocus()) {
1696 setCursorVisible(true);
1697 }
1698}
1699
1701{
1702 Q_D(const QQuickTextEdit);
1703 return !(d->control->textInteractionFlags() & Qt::TextEditable);
1704}
1705
1717{
1718 Q_D(const QQuickTextEdit);
1719 return d->control->cursorRect().translated(d->xoff, d->yoff);
1720}
1721
1723{
1724 Q_D(QQuickTextEdit);
1725 if (event->type() == QEvent::ShortcutOverride) {
1726 d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
1727 if (event->isAccepted())
1728 return true;
1729 }
1731}
1732
1748{
1749 Q_D(const QQuickTextEdit);
1750 return d->control->overwriteMode();
1751}
1752
1754{
1755 Q_D(QQuickTextEdit);
1756 d->control->setOverwriteMode(overwrite);
1757}
1758
1764{
1765 Q_D(QQuickTextEdit);
1766 d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
1767 if (!event->isAccepted())
1769}
1770
1776{
1777 Q_D(QQuickTextEdit);
1778 d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
1779 if (!event->isAccepted())
1781}
1782
1789{
1790 Q_D(QQuickTextEdit);
1791 QTextCursor c = d->control->textCursor();
1792 c.clearSelection();
1793 d->control->setTextCursor(c);
1794}
1795
1802{
1803 Q_D(QQuickTextEdit);
1804 d->control->selectAll();
1805}
1806
1813{
1814 Q_D(QQuickTextEdit);
1815 QTextCursor c = d->control->textCursor();
1817 d->control->setTextCursor(c);
1818}
1819
1834{
1835 Q_D(QQuickTextEdit);
1836 if (start < 0 || end < 0 || start >= d->document->characterCount() || end >= d->document->characterCount())
1837 return;
1838 QTextCursor cursor = d->control->textCursor();
1839 cursor.beginEditBlock();
1840 cursor.setPosition(start, QTextCursor::MoveAnchor);
1841 cursor.setPosition(end, QTextCursor::KeepAnchor);
1842 cursor.endEditBlock();
1843 d->control->setTextCursor(cursor);
1844
1845 // QTBUG-11100
1846 updateSelection();
1847#if QT_CONFIG(im)
1848 updateInputMethod();
1849#endif
1850}
1851
1859{
1860 if (start > end) {
1861 qmlWarning(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1862 return false;
1863 } else {
1864 return getText(start, end).isRightToLeft();
1865 }
1866}
1867
1868#if QT_CONFIG(clipboard)
1874void QQuickTextEdit::cut()
1875{
1876 Q_D(QQuickTextEdit);
1877 d->control->cut();
1878}
1879
1885void QQuickTextEdit::copy()
1886{
1887 Q_D(QQuickTextEdit);
1888 d->control->copy();
1889}
1890
1896void QQuickTextEdit::paste()
1897{
1898 Q_D(QQuickTextEdit);
1899 d->control->paste();
1900}
1901#endif // clipboard
1902
1903
1913{
1914 Q_D(QQuickTextEdit);
1915 d->control->undo();
1916}
1917
1925{
1926 Q_D(QQuickTextEdit);
1927 d->control->redo();
1928}
1929
1935{
1936 Q_D(QQuickTextEdit);
1938 setKeepMouseGrab(d->selectByMouse && isMouse);
1939 d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
1940 if (d->focusOnPress){
1941 bool hadActiveFocus = hasActiveFocus();
1943 // re-open input panel on press if already focused
1944#if QT_CONFIG(im)
1945 if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
1946 qGuiApp->inputMethod()->show();
1947#else
1948 Q_UNUSED(hadActiveFocus);
1949#endif
1950 }
1951 if (!event->isAccepted())
1953}
1954
1960{
1961 Q_D(QQuickTextEdit);
1962 d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
1963
1964 if (!event->isAccepted())
1966}
1967
1973{
1974 Q_D(QQuickTextEdit);
1975 d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
1976 if (!event->isAccepted())
1978}
1979
1985{
1986 Q_D(QQuickTextEdit);
1987 d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
1988 if (!event->isAccepted())
1990}
1991
1992#if QT_CONFIG(im)
1997void QQuickTextEdit::inputMethodEvent(QInputMethodEvent *event)
1998{
1999 Q_D(QQuickTextEdit);
2000 const bool wasComposing = isInputMethodComposing();
2001 d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
2002 setCursorVisible(d->control->cursorVisible());
2003 if (wasComposing != isInputMethodComposing())
2005}
2006
2011QVariant QQuickTextEdit::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const
2012{
2013 Q_D(const QQuickTextEdit);
2014
2015 QVariant v;
2016 switch (property) {
2017 case Qt::ImEnabled:
2018 v = (bool)(flags() & ItemAcceptsInputMethod);
2019 break;
2020 case Qt::ImHints:
2021 v = (int)d->effectiveInputMethodHints();
2022 break;
2024 v = QQuickItem::inputMethodQuery(property);
2025 break;
2026 case Qt::ImReadOnly:
2027 v = isReadOnly();
2028 break;
2029 default:
2030 if (property == Qt::ImCursorPosition && !argument.isNull())
2031 argument = QVariant(argument.toPointF() - QPointF(d->xoff, d->yoff));
2032 v = d->control->inputMethodQuery(property, argument);
2034 v = QVariant(v.toRectF().translated(d->xoff, d->yoff));
2035 break;
2036 }
2037 return v;
2038}
2039
2044QVariant QQuickTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
2045{
2046 return inputMethodQuery(property, QVariant());
2047}
2048#endif // im
2049
2050void QQuickTextEdit::triggerPreprocess()
2051{
2052 Q_D(QQuickTextEdit);
2053 if (d->updateType == QQuickTextEditPrivate::UpdateNone)
2055 polish();
2056 update();
2057}
2058
2061
2062static inline bool operator<(const TextNode &n1, const TextNode &n2)
2063{
2064 return n1.startPos() < n2.startPos();
2065}
2066
2067static inline void updateNodeTransform(QQuickTextNode* node, const QPointF &topLeft)
2068{
2069 QMatrix4x4 transformMatrix;
2070 transformMatrix.translate(topLeft.x(), topLeft.y());
2071 node->setMatrix(transformMatrix);
2072}
2073
2080void QQuickTextEdit::invalidateFontCaches()
2081{
2082 Q_D(QQuickTextEdit);
2083 if (d->document == nullptr)
2084 return;
2085
2086 QTextBlock block;
2087 for (block = d->document->firstBlock(); block.isValid(); block = block.next()) {
2088 if (block.layout() != nullptr && block.layout()->engine() != nullptr)
2089 block.layout()->engine()->resetFontEngineCache();
2090 }
2091}
2092
2093inline void resetEngine(QQuickTextNodeEngine *engine, const QColor& textColor, const QColor& selectedTextColor, const QColor& selectionColor)
2094{
2096 engine->setTextColor(textColor);
2097 engine->setSelectedTextColor(selectedTextColor);
2098 engine->setSelectionColor(selectionColor);
2099}
2100
2102{
2103 Q_UNUSED(updatePaintNodeData);
2104 Q_D(QQuickTextEdit);
2105
2106 if (d->updateType != QQuickTextEditPrivate::UpdatePaintNode
2107 && d->updateType != QQuickTextEditPrivate::UpdateAll
2108 && oldNode != nullptr) {
2109 // Update done in preprocess() in the nodes
2111 return oldNode;
2112 }
2113
2114 if (!oldNode || d->updateType == QQuickTextEditPrivate::UpdateAll) {
2115 delete oldNode;
2116 oldNode = nullptr;
2117
2118 // If we had any QQuickTextNode node references, they were deleted along with the root node
2119 // But here we must delete the Node structures in textNodeMap
2120 d->textNodeMap.clear();
2121 }
2122
2124
2125 RootNode *rootNode = static_cast<RootNode *>(oldNode);
2126 TextNodeIterator nodeIterator = d->textNodeMap.begin();
2127 std::optional<int> firstPosAcrossAllNodes;
2128 if (nodeIterator != d->textNodeMap.end())
2129 firstPosAcrossAllNodes = nodeIterator->startPos();
2130
2131 while (nodeIterator != d->textNodeMap.end() && !nodeIterator->dirty())
2132 ++nodeIterator;
2133
2135 QQuickTextNodeEngine frameDecorationsEngine;
2136
2137 if (!oldNode || nodeIterator < d->textNodeMap.end() || d->textNodeMap.isEmpty()) {
2138
2139 if (!oldNode)
2140 rootNode = new RootNode;
2141
2142 int firstDirtyPos = 0;
2143 if (nodeIterator != d->textNodeMap.end()) {
2144 firstDirtyPos = nodeIterator->startPos();
2145 // ### this could be optimized if the first and last dirty nodes are not connected
2146 // as the intermediate text nodes would usually only need to be transformed differently.
2147 QQuickTextNode *firstCleanNode = nullptr;
2148 auto it = d->textNodeMap.constEnd();
2149 while (it != nodeIterator) {
2150 --it;
2151 if (it->dirty())
2152 break;
2153 firstCleanNode = it->textNode();
2154 }
2155 do {
2156 rootNode->removeChildNode(nodeIterator->textNode());
2157 delete nodeIterator->textNode();
2158 nodeIterator = d->textNodeMap.erase(nodeIterator);
2159 } while (nodeIterator != d->textNodeMap.constEnd() && nodeIterator->textNode() != firstCleanNode);
2160 }
2161
2162 // If there's a lot of text, insert only the range of blocks that can possibly be visible within the viewport.
2164 if (flags().testFlag(QQuickItem::ItemObservesViewport)) {
2165 viewport = clipRect();
2166 qCDebug(lcVP) << "text viewport" << viewport;
2167 }
2168
2169 // FIXME: the text decorations could probably be handled separately (only updated for affected textFrames)
2170 rootNode->resetFrameDecorations(d->createTextNode());
2171 resetEngine(&frameDecorationsEngine, d->color, d->selectedTextColor, d->selectionColor);
2172
2173 QQuickTextNode *node = nullptr;
2174
2175 int currentNodeSize = 0;
2176 int nodeStart = firstDirtyPos;
2177 QPointF basePosition(d->xoff, d->yoff);
2178 QMatrix4x4 basePositionMatrix;
2179 basePositionMatrix.translate(basePosition.x(), basePosition.y());
2180 rootNode->setMatrix(basePositionMatrix);
2181
2182 QPointF nodeOffset;
2183 const TextNode firstCleanNode = (nodeIterator != d->textNodeMap.end()) ? *nodeIterator
2184 : TextNode();
2185
2186 QList<QTextFrame *> frames;
2187 frames.append(d->document->rootFrame());
2188
2189
2190 d->firstBlockInViewport = -1;
2191 d->firstBlockPastViewport = -1;
2192 while (!frames.isEmpty()) {
2193 QTextFrame *textFrame = frames.takeFirst();
2194 frames.append(textFrame->childFrames());
2195 frameDecorationsEngine.addFrameDecorations(d->document, textFrame);
2196
2197 if (textFrame->lastPosition() < firstDirtyPos
2198 || textFrame->firstPosition() >= firstCleanNode.startPos())
2199 continue;
2200 resetEngine(&engine, d->color, d->selectedTextColor, d->selectionColor);
2201
2202 if (textFrame->firstPosition() > textFrame->lastPosition()
2203 && textFrame->frameFormat().position() != QTextFrameFormat::InFlow) {
2204 node = d->createTextNode();
2205 updateNodeTransform(node, d->document->documentLayout()->frameBoundingRect(textFrame).topLeft());
2206 const int pos = textFrame->firstPosition() - 1;
2207 auto *a = static_cast<QtPrivate::ProtectedLayoutAccessor *>(d->document->documentLayout());
2208 QTextCharFormat format = a->formatAccessor(pos);
2209 QTextBlock block = textFrame->firstCursorPosition().block();
2210 nodeOffset = d->document->documentLayout()->blockBoundingRect(block).topLeft();
2211 bool inView = true;
2212 if (!viewport.isNull() && block.layout()) {
2213 QRectF coveredRegion = block.layout()->boundingRect().adjusted(nodeOffset.x(), nodeOffset.y(), nodeOffset.x(), nodeOffset.y());
2214 inView = coveredRegion.bottom() >= viewport.top() && coveredRegion.top() <= viewport.bottom();
2215 qCDebug(lcVP) << "non-flow frame" << coveredRegion << "in viewport?" << inView;
2216 }
2217 if (inView) {
2218 engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
2219 engine.addTextObject(block, QPointF(0, 0), format, QQuickTextNodeEngine::Unselected, d->document,
2220 pos, textFrame->frameFormat().position());
2221 }
2222 nodeStart = pos;
2223 } else {
2224 // Having nodes spanning across frame boundaries will break the current bookkeeping mechanism. We need to prevent that.
2225 QList<int> frameBoundaries;
2226 frameBoundaries.reserve(frames.size());
2227 for (QTextFrame *frame : std::as_const(frames))
2228 frameBoundaries.append(frame->firstPosition());
2229 std::sort(frameBoundaries.begin(), frameBoundaries.end());
2230
2231 QTextFrame::iterator it = textFrame->begin();
2232 while (!it.atEnd()) {
2233 QTextBlock block = it.currentBlock();
2234 if (block.position() < firstDirtyPos) {
2235 ++it;
2236 continue;
2237 }
2238
2239 if (!engine.hasContents())
2240 nodeOffset = d->document->documentLayout()->blockBoundingRect(block).topLeft();
2241
2242 bool inView = true;
2243 if (!viewport.isNull()) {
2244 QRectF coveredRegion;
2245 if (block.layout()) {
2246 coveredRegion = block.layout()->boundingRect().adjusted(nodeOffset.x(), nodeOffset.y(), nodeOffset.x(), nodeOffset.y());
2247 inView = coveredRegion.bottom() > viewport.top();
2248 }
2249 const bool potentiallyScrollingBackwards = firstPosAcrossAllNodes && *firstPosAcrossAllNodes == firstDirtyPos;
2250 if (d->firstBlockInViewport < 0 && inView && potentiallyScrollingBackwards) {
2251 // During backward scrolling, we need to iterate backwards from textNodeMap.begin() to fill the top of the viewport.
2252 if (coveredRegion.top() > viewport.top() + 1) {
2253 qCDebug(lcVP) << "checking backwards from block" << block.blockNumber() << "@" << nodeOffset.y() << coveredRegion;
2254 while (it != textFrame->begin() && it.currentBlock().layout() &&
2255 it.currentBlock().layout()->boundingRect().top() + nodeOffset.y() > viewport.top()) {
2256 nodeOffset = d->document->documentLayout()->blockBoundingRect(it.currentBlock()).topLeft();
2257 --it;
2258 }
2259 if (!it.currentBlock().layout())
2260 ++it;
2261 if (Q_LIKELY(it.currentBlock().layout())) {
2262 block = it.currentBlock();
2263 coveredRegion = block.layout()->boundingRect().adjusted(nodeOffset.x(), nodeOffset.y(), nodeOffset.x(), nodeOffset.y());
2264 firstDirtyPos = it.currentBlock().position();
2265 } else {
2266 qCWarning(lcVP) << "failed to find a text block with layout during back-scrolling";
2267 }
2268 }
2269 qCDebug(lcVP) << "first block in viewport" << block.blockNumber() << "@" << nodeOffset.y() << coveredRegion;
2270 d->firstBlockInViewport = block.blockNumber();
2271 if (block.layout())
2272 d->renderedRegion = coveredRegion;
2273 } else {
2274 if (nodeOffset.y() > viewport.bottom()) {
2275 inView = false;
2276 if (d->firstBlockInViewport >= 0 && d->firstBlockPastViewport < 0) {
2277 qCDebug(lcVP) << "first block past viewport" << viewport << block.blockNumber()
2278 << "@" << nodeOffset.y() << "total region rendered" << d->renderedRegion;
2279 d->firstBlockPastViewport = block.blockNumber();
2280 }
2281 break; // skip rest of blocks in this frame
2282 }
2283 if (inView && !block.text().isEmpty() && coveredRegion.isValid())
2284 d->renderedRegion = d->renderedRegion.united(coveredRegion);
2285 }
2286 }
2287
2288 bool createdNodeInView = false;
2289 if (inView) {
2290 if (!engine.hasContents()) {
2291 if (node && !node->parent())
2292 d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart);
2293 node = d->createTextNode();
2294 createdNodeInView = true;
2295 updateNodeTransform(node, nodeOffset);
2296 nodeStart = block.position();
2297 }
2298 engine.addTextBlock(d->document, block, -nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1);
2299 currentNodeSize += block.length();
2300 }
2301
2302 if ((it.atEnd()) || block.next().position() >= firstCleanNode.startPos())
2303 break; // last node that needed replacing or last block of the frame
2304 QList<int>::const_iterator lowerBound = std::lower_bound(frameBoundaries.constBegin(), frameBoundaries.constEnd(), block.next().position());
2305 if (node && (currentNodeSize > nodeBreakingSize || lowerBound == frameBoundaries.constEnd() || *lowerBound > nodeStart)) {
2306 currentNodeSize = 0;
2307 if (!node->parent())
2308 d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart);
2309 if (!createdNodeInView)
2310 node = d->createTextNode();
2311 resetEngine(&engine, d->color, d->selectedTextColor, d->selectionColor);
2312 nodeStart = block.next().position();
2313 }
2314 ++it;
2315 } // loop over blocks in frame
2316 }
2317 if (Q_LIKELY(node && !node->parent()))
2318 d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart);
2319 }
2320 frameDecorationsEngine.addToSceneGraph(rootNode->frameDecorationsNode, QQuickText::Normal, QColor());
2321 // Now prepend the frame decorations since we want them rendered first, with the text nodes and cursor in front.
2322 rootNode->prependChildNode(rootNode->frameDecorationsNode);
2323
2324 Q_ASSERT(nodeIterator == d->textNodeMap.end()
2325 || (nodeIterator->textNode() == firstCleanNode.textNode()
2326 && nodeIterator->startPos() == firstCleanNode.startPos()));
2327 // Update the position of the subsequent text blocks.
2328 if (firstCleanNode.textNode() != nullptr) {
2329 QPointF oldOffset = firstCleanNode.textNode()->matrix().map(QPointF(0,0));
2330 QPointF currentOffset = d->document->documentLayout()->blockBoundingRect(
2331 d->document->findBlock(firstCleanNode.startPos())).topLeft();
2332 QPointF delta = currentOffset - oldOffset;
2333 while (nodeIterator != d->textNodeMap.end()) {
2334 QMatrix4x4 transformMatrix = nodeIterator->textNode()->matrix();
2335 transformMatrix.translate(delta.x(), delta.y());
2336 nodeIterator->textNode()->setMatrix(transformMatrix);
2337 ++nodeIterator;
2338 }
2339
2340 }
2341
2342 // Since we iterate over blocks from different text frames that are potentially not sorted
2343 // we need to ensure that our list of nodes is sorted again:
2344 std::sort(d->textNodeMap.begin(), d->textNodeMap.end());
2345 }
2346
2347 if (d->cursorComponent == nullptr) {
2349 if (!isReadOnly() && d->cursorVisible && d->control->cursorOn() && d->control->cursorVisible())
2350 cursor = d->sceneGraphContext()->createInternalRectangleNode(d->control->cursorRect(), d->color);
2351 rootNode->resetCursorNode(cursor);
2352 }
2353
2354 invalidateFontCaches();
2355
2356 return rootNode;
2357}
2358
2360{
2361 invalidateFontCaches();
2362}
2363
2371{
2372 Q_D(const QQuickTextEdit);
2373 if (!d->canPasteValid) {
2374 const_cast<QQuickTextEditPrivate *>(d)->canPaste = d->control->canPaste();
2375 const_cast<QQuickTextEditPrivate *>(d)->canPasteValid = true;
2376 }
2377 return d->canPaste;
2378}
2379
2388{
2389 Q_D(const QQuickTextEdit);
2390 return d->document->isUndoAvailable();
2391}
2392
2401{
2402 Q_D(const QQuickTextEdit);
2403 return d->document->isRedoAvailable();
2404}
2405
2419{
2420#if !QT_CONFIG(im)
2421 return false;
2422#else
2423 Q_D(const QQuickTextEdit);
2424 return d->control->hasImState();
2425#endif // im
2426}
2427
2429 : padding(0)
2430 , topPadding(0)
2431 , leftPadding(0)
2432 , rightPadding(0)
2433 , bottomPadding(0)
2434 , explicitTopPadding(false)
2435 , explicitLeftPadding(false)
2436 , explicitRightPadding(false)
2437 , explicitBottomPadding(false)
2438 , implicitResize(true)
2439{
2440}
2441
2443{
2444 Q_Q(QQuickTextEdit);
2445
2446#if QT_CONFIG(clipboard)
2447 if (QGuiApplication::clipboard()->supportsSelection())
2448 q->setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton);
2449 else
2450#endif
2451 q->setAcceptedMouseButtons(Qt::LeftButton);
2452
2453#if QT_CONFIG(im)
2454 q->setFlag(QQuickItem::ItemAcceptsInputMethod);
2455#endif
2457
2458 q->setAcceptHoverEvents(true);
2459
2461
2464 control->setAcceptRichText(false);
2466 q->setKeepMouseGrab(true);
2467
2468 qmlobject_connect(control, QQuickTextControl, SIGNAL(updateCursorRequest()), q, QQuickTextEdit, SLOT(updateCursor()));
2469 qmlobject_connect(control, QQuickTextControl, SIGNAL(selectionChanged()), q, QQuickTextEdit, SIGNAL(selectedTextChanged()));
2470 qmlobject_connect(control, QQuickTextControl, SIGNAL(selectionChanged()), q, QQuickTextEdit, SLOT(updateSelection()));
2471 qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorPositionChanged()), q, QQuickTextEdit, SLOT(updateSelection()));
2472 qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorPositionChanged()), q, QQuickTextEdit, SIGNAL(cursorPositionChanged()));
2473 qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorRectangleChanged()), q, QQuickTextEdit, SLOT(moveCursorDelegate()));
2475 qmlobject_connect(control, QQuickTextControl, SIGNAL(overwriteModeChanged(bool)), q, QQuickTextEdit, SIGNAL(overwriteModeChanged(bool)));
2477 qmlobject_connect(control, QQuickTextControl, SIGNAL(preeditTextChanged()), q, QQuickTextEdit, SIGNAL(preeditTextChanged()));
2478#if QT_CONFIG(clipboard)
2479 qmlobject_connect(QGuiApplication::clipboard(), QClipboard, SIGNAL(dataChanged()), q, QQuickTextEdit, SLOT(q_canPasteChanged()));
2480#endif
2486 QObject::connect(control, &QQuickTextControl::linkHovered, q, &QQuickTextEdit::q_linkHovered);
2487 QObject::connect(control, &QQuickTextControl::markerHovered, q, &QQuickTextEdit::q_markerHovered);
2488
2491 document->setUndoRedoEnabled(false); // flush undo buffer.
2494 q->updateSize();
2495#if QT_CONFIG(cursor)
2496 updateMouseCursorShape();
2497#endif
2498}
2499
2501{
2502 Q_Q(QQuickTextEdit);
2503 if (!q->isReadOnly() && q->hasActiveFocus() && qGuiApp)
2505}
2506
2507void QQuickTextEdit::q_textChanged()
2508{
2509 Q_D(QQuickTextEdit);
2510 d->textCached = false;
2511 for (QTextBlock it = d->document->begin(); it != d->document->end(); it = it.next()) {
2512 d->contentDirection = d->textDirection(it.text());
2513 if (d->contentDirection != Qt::LayoutDirectionAuto)
2514 break;
2515 }
2516 d->determineHorizontalAlignment();
2517 d->updateDefaultTextOption();
2518 updateSize();
2519
2520 markDirtyNodesForRange(0, d->document->characterCount(), 0);
2521 if (isComponentComplete()) {
2522 polish();
2524 update();
2525 }
2526
2527 emit textChanged();
2528}
2529
2530void QQuickTextEdit::markDirtyNodesForRange(int start, int end, int charDelta)
2531{
2532 Q_D(QQuickTextEdit);
2533 if (start == end)
2534 return;
2535
2536 TextNode dummyNode(start);
2537
2538 const TextNodeIterator textNodeMapBegin = d->textNodeMap.begin();
2539 const TextNodeIterator textNodeMapEnd = d->textNodeMap.end();
2540
2541 TextNodeIterator it = std::lower_bound(textNodeMapBegin, textNodeMapEnd, dummyNode);
2542 // qLowerBound gives us the first node past the start of the affected portion, rewind to the first node
2543 // that starts at the last position before the edit position. (there might be several because of images)
2544 if (it != textNodeMapBegin) {
2545 --it;
2546 TextNode otherDummy(it->startPos());
2547 it = std::lower_bound(textNodeMapBegin, textNodeMapEnd, otherDummy);
2548 }
2549
2550 // mark the affected nodes as dirty
2551 while (it != textNodeMapEnd) {
2552 if (it->startPos() <= end)
2553 it->setDirty();
2554 else if (charDelta)
2555 it->moveStartPos(charDelta);
2556 else
2557 return;
2558 ++it;
2559 }
2560}
2561
2562void QQuickTextEdit::q_contentsChange(int pos, int charsRemoved, int charsAdded)
2563{
2564 Q_D(QQuickTextEdit);
2565
2566 const int editRange = pos + qMax(charsAdded, charsRemoved);
2567 const int delta = charsAdded - charsRemoved;
2568
2569 markDirtyNodesForRange(pos, editRange, delta);
2570
2571 if (isComponentComplete()) {
2572 polish();
2574 update();
2575 }
2576}
2577
2578void QQuickTextEdit::moveCursorDelegate()
2579{
2580 Q_D(QQuickTextEdit);
2581#if QT_CONFIG(im)
2582 updateInputMethod();
2583#endif
2584 emit cursorRectangleChanged();
2585 if (!d->cursorItem)
2586 return;
2587 QRectF cursorRect = cursorRectangle();
2588 d->cursorItem->setX(cursorRect.x());
2589 d->cursorItem->setY(cursorRect.y());
2590 d->cursorItem->setHeight(cursorRect.height());
2591}
2592
2593void QQuickTextEdit::updateSelection()
2594{
2595 Q_D(QQuickTextEdit);
2596
2597 // No need for node updates when we go from an empty selection to another empty selection
2598 if (d->control->textCursor().hasSelection() || d->hadSelection) {
2599 markDirtyNodesForRange(qMin(d->lastSelectionStart, d->control->textCursor().selectionStart()), qMax(d->control->textCursor().selectionEnd(), d->lastSelectionEnd), 0);
2600 if (isComponentComplete()) {
2601 polish();
2603 update();
2604 }
2605 }
2606
2607 d->hadSelection = d->control->textCursor().hasSelection();
2608
2609 if (d->lastSelectionStart != d->control->textCursor().selectionStart()) {
2610 d->lastSelectionStart = d->control->textCursor().selectionStart();
2611 emit selectionStartChanged();
2612 }
2613 if (d->lastSelectionEnd != d->control->textCursor().selectionEnd()) {
2614 d->lastSelectionEnd = d->control->textCursor().selectionEnd();
2615 emit selectionEndChanged();
2616 }
2617}
2618
2620{
2621 Q_D(const QQuickTextEdit);
2622 QRectF r(
2623 QQuickTextUtil::alignedX(d->contentSize.width(), width(), effectiveHAlign()),
2624 d->yoff,
2625 d->contentSize.width(),
2626 d->contentSize.height());
2627
2628 int cursorWidth = 1;
2629 if (d->cursorItem)
2630 cursorWidth = 0;
2631 else if (!d->document->isEmpty())
2632 cursorWidth += 3;// ### Need a better way of accounting for space between char and cursor
2633
2634 // Could include font max left/right bearings to either side of rectangle.
2635 r.setRight(r.right() + cursorWidth);
2636
2637 return r;
2638}
2639
2641{
2642 Q_D(const QQuickTextEdit);
2644 int cursorWidth = 1;
2645 if (d->cursorItem)
2646 cursorWidth = d->cursorItem->width();
2647 if (!d->document->isEmpty())
2648 cursorWidth += 3;// ### Need a better way of accounting for space between char and cursor
2649
2650 // Could include font max left/right bearings to either side of rectangle.
2651
2652 r.setRight(r.right() + cursorWidth);
2653 return r;
2654}
2655
2657{
2658 Q_Q(const QQuickTextEdit);
2659 if (!requireImplicitWidth) {
2660 // We don't calculate implicitWidth unless it is required.
2661 // We need to force a size update now to ensure implicitWidth is calculated
2662 const_cast<QQuickTextEditPrivate*>(this)->requireImplicitWidth = true;
2663 const_cast<QQuickTextEdit*>(q)->updateSize();
2664 }
2665 return implicitWidth;
2666}
2667
2668//### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't
2669// need to do all the calculations each time
2670void QQuickTextEdit::updateSize()
2671{
2672 Q_D(QQuickTextEdit);
2673 if (!isComponentComplete()) {
2674 d->dirty = true;
2675 return;
2676 }
2677
2678 // ### assumes that if the width is set, the text will fill to edges
2679 // ### (unless wrap is false, then clipping will occur)
2680 if (widthValid()) {
2681 if (!d->requireImplicitWidth) {
2683 // if the implicitWidth is used, then updateSize() has already been called (recursively)
2684 if (d->requireImplicitWidth)
2685 return;
2686 }
2687 if (d->requireImplicitWidth) {
2688 d->document->setTextWidth(-1);
2689 const qreal naturalWidth = d->document->idealWidth();
2690 const bool wasInLayout = d->inLayout;
2691 d->inLayout = true;
2692 if (d->isImplicitResizeEnabled())
2693 setImplicitWidth(naturalWidth + leftPadding() + rightPadding());
2694 d->inLayout = wasInLayout;
2695 if (d->inLayout) // probably the result of a binding loop, but by letting it
2696 return; // get this far we'll get a warning to that effect.
2697 }
2698 const qreal newTextWidth = width() - leftPadding() - rightPadding();
2699 if (d->document->textWidth() != newTextWidth)
2700 d->document->setTextWidth(newTextWidth);
2701 } else if (d->wrapMode == NoWrap) {
2702 // normally, if explicit width is not set, we should call setTextWidth(-1) here,
2703 // as we don't need to fit the text to any fixed width. But because of some bug
2704 // in QTextDocument it also breaks RTL text alignment, so we use "idealWidth" instead.
2705 const qreal newTextWidth = d->document->idealWidth();
2706 if (d->document->textWidth() != newTextWidth)
2707 d->document->setTextWidth(newTextWidth);
2708 } else {
2709 d->document->setTextWidth(-1);
2710 }
2711
2712 QFontMetricsF fm(d->font);
2713 const qreal newHeight = d->document->isEmpty() ? qCeil(fm.height()) : d->document->size().height();
2714 const qreal newWidth = d->document->idealWidth();
2715
2716 if (d->isImplicitResizeEnabled()) {
2717 // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
2718 if (!widthValid())
2719 setImplicitSize(newWidth + leftPadding() + rightPadding(), newHeight + topPadding() + bottomPadding());
2720 else
2721 setImplicitHeight(newHeight + topPadding() + bottomPadding());
2722 }
2723
2724 d->xoff = leftPadding() + qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width() - leftPadding() - rightPadding(), effectiveHAlign()));
2725 d->yoff = topPadding() + QQuickTextUtil::alignedY(d->document->size().height(), height() - topPadding() - bottomPadding(), d->vAlign);
2726 setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
2727
2728 QSizeF size(newWidth, newHeight);
2729 if (d->contentSize != size) {
2730 d->contentSize = size;
2731 // Note: inResize is a bitfield so QScopedValueRollback can't be used here
2732 const bool wasInResize = d->inResize;
2733 d->inResize = true;
2734 if (!wasInResize)
2735 emit contentSizeChanged();
2736 d->inResize = wasInResize;
2737 updateTotalLines();
2738 }
2739}
2740
2741void QQuickTextEdit::updateWholeDocument()
2742{
2743 Q_D(QQuickTextEdit);
2744 if (!d->textNodeMap.isEmpty()) {
2745 for (TextNode &node : d->textNodeMap)
2746 node.setDirty();
2747 }
2748
2749 if (isComponentComplete()) {
2750 polish();
2752 update();
2753 }
2754}
2755
2756void QQuickTextEdit::invalidateBlock(const QTextBlock &block)
2757{
2758 Q_D(QQuickTextEdit);
2759 markDirtyNodesForRange(block.position(), block.position() + block.length(), 0);
2760
2761 if (isComponentComplete()) {
2762 polish();
2764 update();
2765 }
2766}
2767
2768void QQuickTextEdit::updateCursor()
2769{
2770 Q_D(QQuickTextEdit);
2771 if (isComponentComplete() && isVisible()) {
2772 polish();
2774 update();
2775 }
2776}
2777
2778void QQuickTextEdit::q_linkHovered(const QString &link)
2779{
2780 Q_D(QQuickTextEdit);
2781 emit linkHovered(link);
2782#if QT_CONFIG(cursor)
2783 if (link.isEmpty()) {
2784 d->updateMouseCursorShape();
2785 } else if (cursor().shape() != Qt::PointingHandCursor) {
2787 }
2788#endif
2789}
2790
2791void QQuickTextEdit::q_markerHovered(bool hovered)
2792{
2793 Q_D(QQuickTextEdit);
2794#if QT_CONFIG(cursor)
2795 if (!hovered) {
2796 d->updateMouseCursorShape();
2797 } else if (cursor().shape() != Qt::PointingHandCursor) {
2799 }
2800#endif
2801}
2802
2803void QQuickTextEdit::q_updateAlignment()
2804{
2805 Q_D(QQuickTextEdit);
2806 if (d->determineHorizontalAlignment()) {
2807 d->updateDefaultTextOption();
2808 d->xoff = qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width(), effectiveHAlign()));
2809 moveCursorDelegate();
2810 }
2811}
2812
2813void QQuickTextEdit::updateTotalLines()
2814{
2815 Q_D(QQuickTextEdit);
2816
2817 int subLines = 0;
2818
2819 for (QTextBlock it = d->document->begin(); it != d->document->end(); it = it.next()) {
2820 QTextLayout *layout = it.layout();
2821 if (!layout)
2822 continue;
2823 subLines += layout->lineCount()-1;
2824 }
2825
2826 int newTotalLines = d->document->lineCount() + subLines;
2827 if (d->lineCount != newTotalLines) {
2828 d->lineCount = newTotalLines;
2829 emit lineCountChanged();
2830 }
2831}
2832
2834{
2835 Q_Q(QQuickTextEdit);
2837 const Qt::Alignment oldAlignment = opt.alignment();
2838 Qt::LayoutDirection oldTextDirection = opt.textDirection();
2839
2840 QQuickTextEdit::HAlignment horizontalAlignment = q->effectiveHAlign();
2842 if (horizontalAlignment == QQuickTextEdit::AlignLeft)
2843 horizontalAlignment = QQuickTextEdit::AlignRight;
2844 else if (horizontalAlignment == QQuickTextEdit::AlignRight)
2845 horizontalAlignment = QQuickTextEdit::AlignLeft;
2846 }
2847 if (!hAlignImplicit)
2848 opt.setAlignment((Qt::Alignment)(int)(horizontalAlignment | vAlign));
2849 else
2850 opt.setAlignment(Qt::Alignment(vAlign));
2851
2852#if QT_CONFIG(im)
2854 opt.setTextDirection(qGuiApp->inputMethod()->inputDirection());
2855 } else
2856#endif
2857 {
2858 opt.setTextDirection(contentDirection);
2859 }
2860
2861 QTextOption::WrapMode oldWrapMode = opt.wrapMode();
2862 opt.setWrapMode(QTextOption::WrapMode(wrapMode));
2863
2864 bool oldUseDesignMetrics = opt.useDesignMetrics();
2865 opt.setUseDesignMetrics(renderType != QQuickTextEdit::NativeRendering);
2866
2867 if (oldWrapMode != opt.wrapMode() || oldAlignment != opt.alignment()
2868 || oldTextDirection != opt.textDirection()
2869 || oldUseDesignMetrics != opt.useDesignMetrics()) {
2871 }
2872}
2873
2875{
2876 Q_D(QQuickTextEdit);
2877 d->handleFocusEvent(event);
2879}
2880
2882{
2883 Q_D(QQuickTextEdit);
2884 d->handleFocusEvent(event);
2886}
2887
2889{
2890 Q_Q(QQuickTextEdit);
2891 bool focus = event->type() == QEvent::FocusIn;
2892 if (!q->isReadOnly())
2893 q->setCursorVisible(focus);
2895 if (focus) {
2896 q->q_updateAlignment();
2897#if QT_CONFIG(im)
2898 if (focusOnPress && !q->isReadOnly())
2899 qGuiApp->inputMethod()->show();
2900 q->connect(QGuiApplication::inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
2901 q, SLOT(q_updateAlignment()));
2902#endif
2903 } else {
2904#if QT_CONFIG(im)
2905 q->disconnect(QGuiApplication::inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
2906 q, SLOT(q_updateAlignment()));
2907#endif
2908 if (event->reason() != Qt::ActiveWindowFocusReason
2909 && event->reason() != Qt::PopupFocusReason
2912 q->deselect();
2913
2914 emit q->editingFinished();
2915 }
2916}
2917
2919{
2920 engine->addToSceneGraph(node, QQuickText::Normal, QColor());
2921 it = textNodeMap.insert(it, TextNode(startPos, node));
2922 ++it;
2923 root->appendChildNode(node);
2924}
2925
2927{
2928 Q_Q(QQuickTextEdit);
2929 QQuickTextNode* node = new QQuickTextNode(q);
2931 return node;
2932}
2933
2934void QQuickTextEdit::q_canPasteChanged()
2935{
2936 Q_D(QQuickTextEdit);
2937 bool old = d->canPaste;
2938 d->canPaste = d->control->canPaste();
2939 bool changed = old!=d->canPaste || !d->canPasteValid;
2940 d->canPasteValid = true;
2941 if (changed)
2942 emit canPasteChanged();
2943}
2944
2954{
2955 Q_D(const QQuickTextEdit);
2956 start = qBound(0, start, d->document->characterCount() - 1);
2957 end = qBound(0, end, d->document->characterCount() - 1);
2958 QTextCursor cursor(d->document);
2959 cursor.setPosition(start, QTextCursor::MoveAnchor);
2960 cursor.setPosition(end, QTextCursor::KeepAnchor);
2961#if QT_CONFIG(texthtmlparser)
2962 return d->richText || d->markdownText
2963 ? cursor.selectedText()
2964 : cursor.selection().toPlainText();
2965#else
2966 return cursor.selection().toPlainText();
2967#endif
2968}
2969
2979{
2980 Q_D(const QQuickTextEdit);
2981
2982 start = qBound(0, start, d->document->characterCount() - 1);
2983 end = qBound(0, end, d->document->characterCount() - 1);
2984
2985 QTextCursor cursor(d->document);
2986 cursor.setPosition(start, QTextCursor::MoveAnchor);
2987 cursor.setPosition(end, QTextCursor::KeepAnchor);
2988
2989 if (d->richText) {
2990#if QT_CONFIG(texthtmlparser)
2991 return cursor.selection().toHtml();
2992#else
2993 return cursor.selection().toPlainText();
2994#endif
2995 } else if (d->markdownText) {
2996#if QT_CONFIG(textmarkdownwriter)
2997 return cursor.selection().toMarkdown();
2998#else
2999 return cursor.selection().toPlainText();
3000#endif
3001 } else {
3002 return cursor.selection().toPlainText();
3003 }
3004}
3005
3012{
3013 Q_D(QQuickTextEdit);
3014 if (position < 0 || position >= d->document->characterCount())
3015 return;
3016 QTextCursor cursor(d->document);
3017 cursor.setPosition(position);
3018 d->richText = d->richText || (d->format == AutoText && Qt::mightBeRichText(text));
3019 if (d->richText) {
3020#if QT_CONFIG(texthtmlparser)
3021 cursor.insertHtml(text);
3022#else
3023 cursor.insertText(text);
3024#endif
3025 } else if (d->markdownText) {
3026#if QT_CONFIG(textmarkdownreader)
3027 cursor.insertMarkdown(text);
3028#else
3029 cursor.insertText(text);
3030#endif
3031 } else {
3032 cursor.insertText(text);
3033 }
3034 d->control->updateCursorRectangle(false);
3035}
3036
3044{
3045 Q_D(QQuickTextEdit);
3046 start = qBound(0, start, d->document->characterCount() - 1);
3047 end = qBound(0, end, d->document->characterCount() - 1);
3048 QTextCursor cursor(d->document);
3049 cursor.setPosition(start, QTextCursor::MoveAnchor);
3050 cursor.setPosition(end, QTextCursor::KeepAnchor);
3051 cursor.removeSelectedText();
3052 d->control->updateCursorRectangle(false);
3053}
3054
3067{
3068 Q_D(QQuickTextEdit);
3069 if (!d->quickDocument)
3070 d->quickDocument = new QQuickTextDocument(this);
3071 return d->quickDocument;
3072}
3073
3075{
3076 Q_Q(QQuickTextEdit);
3077 IS_SIGNAL_CONNECTED(q, QQuickTextEdit, linkHovered, (const QString &));
3078}
3079
3080#if QT_CONFIG(cursor)
3081void QQuickTextEditPrivate::updateMouseCursorShape()
3082{
3083 Q_Q(QQuickTextEdit);
3084 q->setCursor(q->isReadOnly() && !q->selectByMouse() ? Qt::ArrowCursor : Qt::IBeamCursor);
3085}
3086#endif
3087
3118{
3119 Q_D(const QQuickTextEdit);
3120 if (const_cast<QQuickTextEditPrivate *>(d)->isLinkHoveredConnected()) {
3121 return d->control->hoveredLink();
3122 } else {
3123#if QT_CONFIG(cursor)
3124 if (QQuickWindow *wnd = window()) {
3125 QPointF pos = QCursor::pos(wnd->screen()) - wnd->position() - mapToScene(QPointF(0, 0));
3126 return d->control->anchorAt(pos);
3127 }
3128#endif // cursor
3129 }
3130 return QString();
3131}
3132
3134{
3135 Q_D(QQuickTextEdit);
3136 if (d->isLinkHoveredConnected())
3137 d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
3138 event->ignore();
3139}
3140
3142{
3143 Q_D(QQuickTextEdit);
3144 if (d->isLinkHoveredConnected())
3145 d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
3146 event->ignore();
3147}
3148
3150{
3151 Q_D(QQuickTextEdit);
3152 if (d->isLinkHoveredConnected())
3153 d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
3154 event->ignore();
3155}
3156
3166void QQuickTextEdit::append(const QString &text)
3167{
3168 Q_D(QQuickTextEdit);
3169 QTextCursor cursor(d->document);
3170 cursor.beginEditBlock();
3171 cursor.movePosition(QTextCursor::End);
3172
3173 if (!d->document->isEmpty())
3174 cursor.insertBlock();
3175
3176 if (d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text))) {
3177#if QT_CONFIG(texthtmlparser)
3178 cursor.insertHtml(text);
3179#else
3180 cursor.insertText(text);
3181#endif
3182 } else if (d->format == MarkdownText) {
3183#if QT_CONFIG(textmarkdownreader)
3184 cursor.insertMarkdown(text);
3185#else
3186 cursor.insertText(text);
3187#endif
3188 } else {
3189 cursor.insertText(text);
3190 }
3191
3192 cursor.endEditBlock();
3193 d->control->updateCursorRectangle(false);
3194}
3195
3205QString QQuickTextEdit::linkAt(qreal x, qreal y) const
3206{
3207 Q_D(const QQuickTextEdit);
3208 return d->control->anchorAt(QPointF(x + topPadding(), y + leftPadding()));
3209}
3210
3223{
3224 Q_D(const QQuickTextEdit);
3225 return d->padding();
3226}
3227
3229{
3230 Q_D(QQuickTextEdit);
3231 if (qFuzzyCompare(d->padding(), padding))
3232 return;
3233
3234 d->extra.value().padding = padding;
3235 updateSize();
3236 if (isComponentComplete()) {
3238 update();
3239 }
3240 emit paddingChanged();
3241 if (!d->extra.isAllocated() || !d->extra->explicitTopPadding)
3242 emit topPaddingChanged();
3243 if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding)
3244 emit leftPaddingChanged();
3245 if (!d->extra.isAllocated() || !d->extra->explicitRightPadding)
3246 emit rightPaddingChanged();
3247 if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding)
3248 emit bottomPaddingChanged();
3249}
3250
3252{
3253 setPadding(0);
3254}
3255
3257{
3258 Q_D(const QQuickTextEdit);
3259 if (d->extra.isAllocated() && d->extra->explicitTopPadding)
3260 return d->extra->topPadding;
3261 return d->padding();
3262}
3263
3265{
3266 Q_D(QQuickTextEdit);
3267 d->setTopPadding(padding);
3268}
3269
3271{
3272 Q_D(QQuickTextEdit);
3273 d->setTopPadding(0, true);
3274}
3275
3277{
3278 Q_D(const QQuickTextEdit);
3279 if (d->extra.isAllocated() && d->extra->explicitLeftPadding)
3280 return d->extra->leftPadding;
3281 return d->padding();
3282}
3283
3285{
3286 Q_D(QQuickTextEdit);
3287 d->setLeftPadding(padding);
3288}
3289
3291{
3292 Q_D(QQuickTextEdit);
3293 d->setLeftPadding(0, true);
3294}
3295
3297{
3298 Q_D(const QQuickTextEdit);
3299 if (d->extra.isAllocated() && d->extra->explicitRightPadding)
3300 return d->extra->rightPadding;
3301 return d->padding();
3302}
3303
3305{
3306 Q_D(QQuickTextEdit);
3307 d->setRightPadding(padding);
3308}
3309
3311{
3312 Q_D(QQuickTextEdit);
3313 d->setRightPadding(0, true);
3314}
3315
3317{
3318 Q_D(const QQuickTextEdit);
3319 if (d->extra.isAllocated() && d->extra->explicitBottomPadding)
3320 return d->extra->bottomPadding;
3321 return d->padding();
3322}
3323
3325{
3326 Q_D(QQuickTextEdit);
3327 d->setBottomPadding(padding);
3328}
3329
3331{
3332 Q_D(QQuickTextEdit);
3333 d->setBottomPadding(0, true);
3334}
3335
3345{
3346 Q_D(const QQuickTextEdit);
3347 return d->document->defaultTextOption().tabStopDistance();
3348}
3349
3351{
3352 Q_D(QQuickTextEdit);
3353 QTextOption textOptions = d->document->defaultTextOption();
3354 if (textOptions.tabStopDistance() == distance)
3355 return;
3356
3357 textOptions.setTabStopDistance(distance);
3358 d->document->setDefaultTextOption(textOptions);
3359 emit tabStopDistanceChanged(distance);
3360}
3361
3373void QQuickTextEdit::clear()
3374{
3375 Q_D(QQuickTextEdit);
3376 d->resetInputMethod();
3377 d->control->clear();
3378}
3379
3380#ifndef QT_NO_DEBUG_STREAM
3382{
3383 QDebugStateSaver saver(debug);
3384 debug.space();
3385 debug << "Node(startPos:" << n.m_startPos << "dirty:" << n.m_dirty << n.m_node << ')';
3386 return debug;
3387}
3388#endif
3389
3390#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
3391void QQuickTextEdit::setOldSelectionDefault()
3392{
3393 Q_D(QQuickTextEdit);
3394 d->selectByMouse = false;
3395 setKeepMouseGrab(false);
3396 d->control->setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse);
3397 d->control->setTouchDragSelectionEnabled(true);
3398 qCDebug(lcTextEdit, "pre-6.4 behavior chosen: selectByMouse defaults false; if enabled, touchscreen acts like a mouse");
3399}
3400
3401// TODO in 6.7.0: remove the note about versions prior to 6.4 in selectByMouse() documentation
3402QQuickPre64TextEdit::QQuickPre64TextEdit(QQuickItem *parent)
3404{
3405 setOldSelectionDefault();
3406}
3407#endif
3408
3410
3411#include "moc_qquicktextedit_p.cpp"
3412
void updateBlock(const QTextBlock &block)
\inmodule QtCore
Definition qchar.h:48
Direction direction() const noexcept
Returns the character's direction.
Definition qchar.h:437
@ DirL
Definition qchar.h:346
@ DirAN
Definition qchar.h:346
@ DirAL
Definition qchar.h:347
@ DirR
Definition qchar.h:346
constexpr bool isNull() const noexcept
Returns true if the character is the Unicode character 0x0000 ('\0'); otherwise returns false.
Definition qchar.h:463
The QClipboard class provides access to the window system clipboard.
Definition qclipboard.h:20
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
static QPoint pos()
Returns the position of the cursor (hot spot) of the primary screen in global screen coordinates.
Definition qcursor.cpp:188
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qcoreevent.h:45
@ ShortcutOverride
Definition qcoreevent.h:158
@ FocusIn
Definition qcoreevent.h:66
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:469
\reentrant \inmodule QtGui
\reentrant \inmodule QtGui
int height() const
Returns the height of the font.
\reentrant
Definition qfont.h:20
static QClipboard * clipboard()
Returns the object for interacting with the clipboard.
static QInputMethod * inputMethod()
returns the input method.
\inmodule QtGui
Definition qevent.h:245
The QInputMethodEvent class provides parameters for input method events.
Definition qevent.h:624
void reset()
Resets the input method state.
The QKeyEvent class describes a key event.
Definition qevent.h:423
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
iterator end()
Definition qlist.h:609
value_type takeFirst()
Definition qlist.h:549
const_iterator constBegin() const noexcept
Definition qlist.h:615
iterator begin()
Definition qlist.h:608
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
const_iterator constEnd() const noexcept
Definition qlist.h:616
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
QPoint map(const QPoint &point) const
Maps point by multiplying this matrix by point.
Definition qmatrix4x4.h:908
void translate(const QVector3D &vector)
Multiplies this matrix by another that translates coordinates by the components of vector.
\inmodule QtGui
Definition qevent.h:195
QObject * parent
Definition qobject.h:61
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
\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
The QQmlComponent class encapsulates a QML component definition.
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
virtual void componentComplete()=0
Invoked after the root component that caused this instantiation has completed construction.
static bool isEventFromMouseOrTouchpad(const QPointerEvent *ev)
virtual bool transformChanged(QQuickItem *transformedItem)
bool widthValid() const
QQuickWindow * window
virtual void implicitWidthChanged()
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
virtual void focusOutEvent(QFocusEvent *)
This event handler can be reimplemented in a subclass to receive focus-out events for an item.
virtual void mouseReleaseEvent(QMouseEvent *event)
This event handler can be reimplemented in a subclass to receive mouse release events for an item.
Flags flags() const
Returns the item flags for this item.
virtual void mouseDoubleClickEvent(QMouseEvent *event)
This event handler can be reimplemented in a subclass to receive mouse double-click events for an ite...
void setFlag(Flag flag, bool enabled=true)
Enables the specified flag for this item if enabled is true; if enabled is false, the flag is disable...
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
virtual void keyPressEvent(QKeyEvent *event)
This event handler can be reimplemented in a subclass to receive key press events for an item.
bool hasActiveFocus() const
virtual void mousePressEvent(QMouseEvent *event)
This event handler can be reimplemented in a subclass to receive mouse press events for an item.
void setVisible(bool)
bool isComponentComplete() const
Returns true if construction of the QML component is complete; otherwise returns false.
bool heightValid() const
Returns whether the height property has been set explicitly.
void setKeepMouseGrab(bool)
Sets whether the mouse input should remain exclusively with this item.
Q_INVOKABLE void forceActiveFocus()
\qmlmethod point QtQuick::Item::mapToItem(Item item, real x, real y) \qmlmethod point QtQuick::Item::...
bool widthValid() const
Returns whether the width property has been set explicitly.
virtual void keyReleaseEvent(QKeyEvent *event)
This event handler can be reimplemented in a subclass to receive key release events for an item.
virtual QRectF clipRect() const
Returns the rectangular area within this item that is currently visible in \l viewportItem(),...
virtual void focusInEvent(QFocusEvent *)
This event handler can be reimplemented in a subclass to receive focus-in events for an item.
@ ItemObservesViewport
Definition qquickitem.h:137
void update()
Schedules a call to updatePaintNode() for this item.
void polish()
Schedules a polish event for this item.
virtual void mouseMoveEvent(QMouseEvent *event)
This event handler can be reimplemented in a subclass to receive mouse move events for an item.
void setTextInteractionFlags(Qt::TextInteractionFlags flags)
void linkHovered(const QString &link)
virtual void processEvent(QEvent *e, const QTransform &transform)
void setAcceptRichText(bool accept)
void markerHovered(bool marker)
QTextCursor textCursor() const
void setCursorIsFocusIndicator(bool b)
void setCursorVisible(bool visible)
The QQuickTextDocument class provides access to the QTextDocument of QQuickTextEdit....
QList< Node >::iterator TextNodeIterator
QQuickTextEdit::HAlignment hAlign
void addCurrentTextNodeToRoot(QQuickTextNodeEngine *, QSGTransformNode *, QQuickTextNode *, TextNodeIterator &, int startPos)
void setImplicitResizeEnabled(bool enabled)
bool isImplicitResizeEnabled() const
void setRightPadding(qreal value, bool reset=false)
QLazilyAllocated< ExtraData > extra
Qt::LayoutDirection textDirection(const QString &text) const
Qt::LayoutDirection contentDirection
bool setHAlign(QQuickTextEdit::HAlignment, bool forceAlign=false)
static const int largeTextSizeThreshold
QQuickTextControl * control
QQuickTextDocumentWithImageResources * document
qreal getImplicitWidth() const override
void setLeftPadding(qreal value, bool reset=false)
QQuickTextEdit::WrapMode wrapMode
bool transformChanged(QQuickItem *transformedItem) override
QQuickTextEdit::VAlignment vAlign
void handleFocusEvent(QFocusEvent *event)
QQuickTextEdit::RenderType renderType
QQuickTextNode * createTextNode()
void setBottomPadding(qreal value, bool reset=false)
void setTopPadding(qreal value, bool reset=false)
void mirrorChange() override
void setFont(const QFont &font)
void setRenderType(RenderType renderType)
void selectWord()
\qmlmethod QtQuick::TextEdit::selectWord()
void keyReleaseEvent(QKeyEvent *) override
This is an overloaded member function, provided for convenience. It differs from the above function o...
void setInputMethodHints(Qt::InputMethodHints hints)
void setWrapMode(WrapMode w)
bool isReadOnly() const
bool isInputMethodComposing() const
\qmlproperty bool QtQuick::TextEdit::inputMethodComposing
void inputMethodComposingChanged()
void setCursorDelegate(QQmlComponent *)
void focusInEvent(QFocusEvent *event) override
This event handler can be reimplemented in a subclass to receive focus-in events for an item.
void hoverMoveEvent(QHoverEvent *event) override
This event handler can be reimplemented in a subclass to receive hover-move events for an item.
void setPersistentSelection(bool on)
void setSelectionColor(const QColor &c)
void setFocusOnPress(bool on)
SelectionMode mouseSelectionMode
void invalidate() override
void keyPressEvent(QKeyEvent *) override
This is an overloaded member function, provided for convenience. It differs from the above function o...
TextFormat textFormat
QQuickTextDocument * textDocument
\qmlproperty TextDocument QtQuick::TextEdit::textDocument
HAlignment hAlign() const
\qmlproperty enumeration QtQuick::TextEdit::horizontalAlignment \qmlproperty enumeration QtQuick::Tex...
void mouseMoveEvent(QMouseEvent *event) override
This is an overloaded member function, provided for convenience. It differs from the above function o...
void remove(int start, int end)
\qmlmethod string QtQuick::TextEdit::remove(int start, int end)
void setSelectByMouse(bool)
void setColor(const QColor &c)
void setMouseSelectionMode(SelectionMode mode)
void colorChanged(const QColor &color)
QRectF clipRect() const override
Returns the rectangular area within this item that is currently visible in \l viewportItem(),...
bool event(QEvent *) override
\reimp
void componentComplete() override
Ensures any delayed caching or data loading the class needs to performed is complete.
void setRightPadding(qreal padding)
Qt::InputMethodHints inputMethodHints
void hoverLeaveEvent(QHoverEvent *event) override
This event handler can be reimplemented in a subclass to receive hover-leave events for an item.
FINALqreal leftPadding
Q_INVOKABLE int positionAt(qreal x, qreal y) const
\qmlmethod int QtQuick::TextEdit::positionAt(int x, int y)
bool focusOnPress() const
\qmlproperty bool QtQuick::TextEdit::activeFocusOnPress
void select(int start, int end)
\qmlmethod QtQuick::TextEdit::select(int start, int end)
void setLeftPadding(qreal padding)
void selectAll()
\qmlmethod QtQuick::TextEdit::selectAll()
void activeFocusOnPressChanged(bool activeFocusOnPressed)
void setOverwriteMode(bool overwrite)
void setHAlign(HAlignment align)
void selectedTextColorChanged(const QColor &color)
void setTopPadding(qreal padding)
FINALqreal bottomPadding
void setCursorPosition(int pos)
QSGNode * updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) override
Called on the render thread when it is time to sync the state of the item with the scene graph.
void mouseReleaseEvent(QMouseEvent *event) override
This is an overloaded member function, provided for convenience. It differs from the above function o...
void setPadding(qreal padding)
void insert(int position, const QString &text)
\qmlmethod QtQuick::TextEdit::insert(int position, string text)
void setTextFormat(TextFormat format)
void mouseDoubleClickEvent(QMouseEvent *event) override
This is an overloaded member function, provided for convenience. It differs from the above function o...
void textMarginChanged(qreal textMargin)
void inputMethodHintsChanged()
void updatePolish() override
This function should perform any layout as required for this item.
FINALbool selectByMouse
void renderTypeChanged()
FINALqreal tabStopDistance
void readOnlyChanged(bool isReadOnly)
Q_INVOKABLE QString getFormattedText(int start, int end) const
\qmlmethod string QtQuick::TextEdit::getFormattedText(int start, int end)
QQmlComponent * cursorDelegate
void setTabStopDistance(qreal distance)
VAlignment vAlign() const
void verticalAlignmentChanged(QQuickTextEdit::VAlignment alignment)
void setSelectedTextColor(const QColor &c)
void cursorVisibleChanged(bool isCursorVisible)
void mousePressEvent(QMouseEvent *event) override
This is an overloaded member function, provided for convenience. It differs from the above function o...
void hoverEnterEvent(QHoverEvent *event) override
This event handler can be reimplemented in a subclass to receive hover-enter events for an item.
FINALqreal topPadding
FINALqreal rightPadding
Q_INVOKABLE QString getText(int start, int end) const
\qmlmethod string QtQuick::TextEdit::getText(int start, int end)
void setBottomPadding(qreal padding)
bool isRightToLeft(int start, int end)
\qmlmethod QtQuick::TextEdit::isRightToLeft(int start, int end)
void selectByMouseChanged(bool selectByMouse)
void setReadOnly(bool)
\qmlproperty bool QtQuick::TextEdit::readOnly
void setSelectByKeyboard(bool)
void deselect()
\qmlmethod QtQuick::TextEdit::deselect()
void fontChanged(const QFont &font)
bool isCursorVisible() const
\qmlproperty bool QtQuick::TextEdit::cursorVisible If true the text edit shows a cursor.
void selectionColorChanged(const QColor &color)
void undo()
\qmlmethod QtQuick::TextEdit::undo()
QQuickTextEdit(QQuickItem *parent=nullptr)
void mouseSelectionModeChanged(QQuickTextEdit::SelectionMode mode)
void focusOutEvent(QFocusEvent *event) override
This event handler can be reimplemented in a subclass to receive focus-out events for an item.
void textFormatChanged(QQuickTextEdit::TextFormat textFormat)
void setVAlign(VAlignment align)
QRectF boundingRect() const override
Returns the extents of the item in its own coordinate system: a rectangle from {0,...
void setBaseUrl(const QUrl &url)
FINALQString preeditText
\qmlproperty string QtQuick::TextEdit::preeditText \readonly
void setTextMargin(qreal margin)
Q_INVOKABLE QRectF positionToRectangle(int) const
\qmlmethod rectangle QtQuick::TextEdit::positionToRectangle(position)
HAlignment effectiveHAlign() const
void wrapModeChanged()
void baseUrlChanged()
void redo()
\qmlmethod QtQuick::TextEdit::redo()
void setCursorVisible(bool on)
Q_INVOKABLE void moveCursorSelection(int pos)
\qmlmethod QtQuick::TextEdit::moveCursorSelection(int position, SelectionMode mode)
void persistentSelectionChanged(bool isPersistentSelection)
RenderType renderType
void setText(const QString &)
\qmlproperty string QtQuick::TextEdit::font.family
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
void addToSceneGraph(QQuickTextNode *parent, QQuickText::TextStyle style=QQuickText::Normal, const QColor &styleColor=QColor())
void addFrameDecorations(QTextDocument *document, QTextFrame *frame)
void setUseNativeRenderer(bool on)
static qreal alignedX(qreal textWidth, qreal itemWidth, int alignment)
static void createCursor(Private *d)
static qreal alignedY(qreal textHeight, qreal itemHeight, int alignment)
static void setCursorDelegate(Private *d, QQmlComponent *delegate)
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr qreal bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:499
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:658
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:718
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:715
constexpr qreal x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:655
constexpr QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:799
constexpr qreal top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:497
constexpr bool isValid() const noexcept
Returns true if the rectangle is valid, otherwise returns false.
Definition qrect.h:652
\group qtquick-scenegraph-nodes \title Qt Quick Scene Graph Node classes
Definition qsgnode.h:37
void removeChildNode(QSGNode *node)
Removes node from this node's list of children.
Definition qsgnode.cpp:498
@ OwnedByParent
Definition qsgnode.h:51
void appendChildNode(QSGNode *node)
Appends node to this node's list of children.
Definition qsgnode.cpp:396
QSGNode * parent() const
Returns the parent node of this node.
Definition qsgnode.h:93
void setFlag(Flag, bool=true)
Sets the flag f on this node if enabled is true; otherwise clears the flag.
Definition qsgnode.cpp:584
The QSGTransformNode class implements transformations in the scene graph.
Definition qsgnode.h:244
void setMatrix(const QMatrix4x4 &matrix)
Sets this transform node's matrix to matrix.
Definition qsgnode.cpp:1160
const QMatrix4x4 & matrix() const
Returns this transform node's matrix.
Definition qsgnode.h:250
\inmodule QtCore
Definition qsize.h:207
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
const QChar * constData() const
Returns a pointer to the data stored in the QString.
Definition qstring.h:1101
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
bool isRightToLeft() const
Returns true if the string is read right to left.
Definition qstring.cpp:9068
\reentrant
int length() const
Returns the length of the block in characters.
int blockNumber() const
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.
\reentrant \inmodule QtGui
Definition qtextcursor.h:30
QTextBlock block() const
Returns the block that contains the cursor.
bool hasSelection() const
Returns true if the cursor contains a selection; otherwise returns false.
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 setDefaultTextOption(const QTextOption &option)
QAbstractTextDocumentLayout * documentLayout() const
Returns the document layout for this document.
QTextOption defaultTextOption() const
the default text option will be set on all \l{QTextLayout}s in the document.
void setDefaultFont(const QFont &font)
Sets the default font to use in the document layout.
void setUndoRedoEnabled(bool enable)
void setDocumentMargin(qreal margin)
void resetFontEngineCache()
Position position() const
Returns the positioning policy for frames with this frame format.
\reentrant
Definition qtextobject.h:81
int lastPosition() const
Returns the last document position inside the frame.
QList< QTextFrame * > childFrames() const
Returns a (possibly empty) list of the frame's child frames.
QTextFrameFormat frameFormat() const
Returns the frame's format.
Definition qtextobject.h:89
iterator begin() const
Returns an iterator pointing to the first document element inside the frame.
int firstPosition() const
Returns the first document position inside the frame.
QTextCursor firstCursorPosition() const
Returns the first cursor position inside the frame.
\reentrant
Definition qtextlayout.h:70
QTextLine lineForTextPosition(int pos) const
Returns the line that contains the cursor position specified by pos.
QTextEngine * engine() const
QString preeditAreaText() const
Returns the text that is inserted in the layout before editing occurs.
QRectF boundingRect() const
The smallest rectangle that contains all the lines in the layout.
\reentrant
Definition qtextoption.h:18
qreal tabStopDistance() const
Definition qtextoption.h:83
WrapMode
This enum describes how text is wrapped in a document.
Definition qtextoption.h:60
void setTabStopDistance(qreal tabStopDistance)
\inmodule QtCore
Definition qurl.h:94
\inmodule QtCore
Definition qvariant.h:64
QString text
QCursor cursor
void textChanged(const QString &newText)
QSet< QString >::iterator it
uint alignment
direction
QStyleOptionButton opt
Combined button and popup list for selecting options.
InputMethodQuery
@ ImAnchorRectangle
@ ImInputItemClipRectangle
@ ImCursorPosition
@ ImReadOnly
@ ImFont
@ ImCursorRectangle
@ ImHints
@ ImEnabled
@ LeftButton
Definition qnamespace.h:57
@ MiddleButton
Definition qnamespace.h:59
@ TextSelectableByMouse
@ TextEditable
@ LinksAccessibleByMouse
@ TextSelectableByKeyboard
LayoutDirection
@ LeftToRight
@ LayoutDirectionAuto
@ RightToLeft
@ PointingHandCursor
@ ArrowCursor
@ ImhNone
@ ImhMultiLine
@ FuzzyHit
Definition qnamespace.h:202
Q_GUI_EXPORT bool mightBeRichText(const QString &)
Returns true if the string text is likely to be rich text; otherwise returns false.
@ PopupFocusReason
@ MouseFocusReason
@ ActiveWindowFocusReason
static void * context
#define Q_LIKELY(x)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:287
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
#define qGuiApp
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
int qCeil(T v)
Definition qmath.h:36
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLuint GLuint end
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLsizei GLsizei GLfloat distance
GLint GLsizei width
GLbitfield flags
GLuint start
GLfloat n
GLint GLsizei GLsizei GLenum format
GLint y
struct _cl_event * event
GLboolean reset
const GLubyte * c
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:71
#define qmlobject_connect(Sender, SenderType, Signal, Receiver, ReceiverType, Method)
Connect Signal of Sender to Method of Receiver.
#define IS_SIGNAL_CONNECTED(Sender, SenderType, Name, Arguments)
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static void updateNodeTransform(QQuickTextNode *node, const QPointF &topLeft)
#define QQUICKTEXT_LARGETEXT_THRESHOLD
static bool operator<(const TextNode &n1, const TextNode &n2)
static QT_BEGIN_NAMESPACE const int nodeBreakingSize
\qmlsignal QtQuick::TextEdit::linkActivated(string link)
QQuickTextEditPrivate::Node TextNode
void resetEngine(QQuickTextNodeEngine *engine, const QColor &textColor, const QColor &selectedTextColor, const QColor &selectionColor)
QDebug Q_QUICK_PRIVATE_EXPORT operator<<(QDebug debug, const QQuickTextEditPrivate::Node &)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:92
const char property[13]
Definition qwizard.cpp:101
QUrl url("example.com")
[constructor-url-reference]
QVBoxLayout * layout
item setCursor(Qt::IBeamCursor)
[1]
view viewport() -> scroll(dx, dy, deviceRect)
edit isVisible()
QFrame frame
[0]
QDBusArgument argument
QJSEngine engine
[0]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
QQuickTextNode * textNode() const
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent