12#if QT_CONFIG(draganddrop)
15#include <qclipboard.h>
21#include "private/qapplication_p.h"
22#include "private/qtextdocumentlayout_p.h"
23#include "private/qabstracttextdocumentlayout_p.h"
25#include "private/qtextdocument_p.h"
29#include <qtextformat.h>
31#include <qapplication.h>
33#include <qtexttable.h>
40#if defined(Q_OS_ANDROID)
42 return !control->isReadOnly() || (control->textInteractionFlags() & Qt::TextSelectableByMouse);
44 return !control->isReadOnly();
50 Q_DECLARE_PUBLIC(QPlainTextDocumentLayout)
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
106
107
108QPlainTextDocumentLayout::QPlainTextDocumentLayout(QTextDocument *document)
109 :QAbstractTextDocumentLayout(*
new QPlainTextDocumentLayoutPrivate, document) {
112
113
114QPlainTextDocumentLayout::~QPlainTextDocumentLayout() {}
118
119
120void QPlainTextDocumentLayout::draw(QPainter *,
const PaintContext &)
125
126
127int QPlainTextDocumentLayout::hitTest(
const QPointF &, Qt::HitTestAccuracy )
const
138
139
140int QPlainTextDocumentLayout::pageCount()
const
144
145
146QSizeF QPlainTextDocumentLayout::documentSize()
const
148 Q_D(
const QPlainTextDocumentLayout);
149 return QSizeF(d->maximumWidth, document()->lineCount());
153
154
155QRectF QPlainTextDocumentLayout::frameBoundingRect(QTextFrame *)
const
157 Q_D(
const QPlainTextDocumentLayout);
158 return QRectF(0, 0, qMax(d->width, d->maximumWidth), qreal(INT_MAX));
162
163
164QRectF QPlainTextDocumentLayout::blockBoundingRect(
const QTextBlock &block)
const
166 if (!block.isValid()) {
return QRectF(); }
167 QTextLayout *tl = block.layout();
168 if (!tl->lineCount())
169 const_cast<QPlainTextDocumentLayout*>(
this)->layoutBlock(block);
171 if (block.isVisible()) {
172 br = QRectF(QPointF(0, 0), tl->boundingRect().bottomRight());
173 if (tl->lineCount() == 1)
174 br.setWidth(qMax(br.width(), tl->lineAt(0).naturalTextWidth()));
175 qreal margin = document()->documentMargin();
176 br.adjust(0, 0, margin, 0);
177 if (!block.next().isValid())
178 br.adjust(0, 0, 0, margin);
185
186
187void QPlainTextDocumentLayout::ensureBlockLayout(
const QTextBlock &block)
const
189 if (!block.isValid())
191 QTextLayout *tl = block.layout();
192 if (!tl->lineCount())
193 const_cast<QPlainTextDocumentLayout*>(
this)->layoutBlock(block);
198
199
200
201void QPlainTextDocumentLayout::setCursorWidth(
int width)
203 Q_D(QPlainTextDocumentLayout);
204 d->cursorWidth = width;
207int QPlainTextDocumentLayout::cursorWidth()
const
209 Q_D(
const QPlainTextDocumentLayout);
210 return d->cursorWidth;
213QPlainTextDocumentLayoutPrivate *QPlainTextDocumentLayout::priv()
const
215 Q_D(
const QPlainTextDocumentLayout);
216 return const_cast<QPlainTextDocumentLayoutPrivate*>(d);
221
222
223
224void QPlainTextDocumentLayout::requestUpdate()
226 emit update(QRectF(0., -document()->documentMargin(), 1000000000., 1000000000.));
230void QPlainTextDocumentLayout::setTextWidth(qreal newWidth)
232 Q_D(QPlainTextDocumentLayout);
233 d->width = d->maximumWidth = newWidth;
237qreal QPlainTextDocumentLayout::textWidth()
const
239 Q_D(
const QPlainTextDocumentLayout);
245 Q_Q(QPlainTextDocumentLayout);
246 QTextBlock block = q->document()->firstBlock();
247 while (block.isValid()) {
248 block.layout()->clearLayout();
249 block.setLineCount(block.isVisible() ? 1 : 0);
250 block = block.next();
257
258void QPlainTextDocumentLayout::documentChanged(
int from,
int charsRemoved,
int charsAdded)
260 Q_D(QPlainTextDocumentLayout);
261 QTextDocument *doc = document();
262 int newBlockCount = doc->blockCount();
263 int charsChanged = charsRemoved + charsAdded;
265 QTextBlock changeStartBlock = doc->findBlock(from);
266 QTextBlock changeEndBlock = doc->findBlock(qMax(0, from + charsChanged - 1));
267 bool blockVisibilityChanged =
false;
269 if (changeStartBlock == changeEndBlock && newBlockCount == d->blockCount) {
270 QTextBlock block = changeStartBlock;
271 if (block.isValid() && block.length()) {
272 QRectF oldBr = blockBoundingRect(block);
274 QRectF newBr = blockBoundingRect(block);
275 if (newBr.height() == oldBr.height()) {
277 emit updateBlock(block);
282 QTextBlock block = changeStartBlock;
285 if (block.isVisible()
286 ? (block.lineCount() == 0)
287 : (block.lineCount() > 0)) {
288 blockVisibilityChanged =
true;
289 block.setLineCount(block.isVisible() ? 1 : 0);
291 if (block == changeEndBlock)
293 block = block.next();
294 }
while(block.isValid());
297 if (newBlockCount != d->blockCount || blockVisibilityChanged) {
298 int changeEnd = changeEndBlock.blockNumber();
299 int blockDiff = newBlockCount - d->blockCount;
300 int oldChangeEnd = changeEnd - blockDiff;
302 if (d->maximumWidthBlockNumber > oldChangeEnd)
303 d->maximumWidthBlockNumber += blockDiff;
305 d->blockCount = newBlockCount;
306 if (d->blockCount == 1)
307 d->maximumWidth = blockWidth(doc->firstBlock());
309 if (!d->blockDocumentSizeChanged)
310 emit documentSizeChanged(documentSize());
312 if (blockDiff == 1 && changeEnd == newBlockCount -1 ) {
313 if (!d->blockUpdate) {
314 QTextBlock b = changeStartBlock;
317 if (b == changeEndBlock)
327 emit update(QRectF(0., -doc->documentMargin(), 1000000000., 1000000000.));
331void QPlainTextDocumentLayout::layoutBlock(
const QTextBlock &block)
333 Q_D(QPlainTextDocumentLayout);
334 QTextDocument *doc = document();
335 qreal margin = doc->documentMargin();
336 qreal blockMaximumWidth = 0;
339 QTextLayout *tl = block.layout();
340 QTextOption option = doc->defaultTextOption();
341 tl->setTextOption(option);
344 if (option.flags() & QTextOption::AddSpaceForLineAndParagraphSeparators) {
345 QFontMetrics fm(block.charFormat().font());
346 extraMargin += fm.horizontalAdvance(QChar(0x21B5));
349 qreal availableWidth = d->width;
350 if (availableWidth <= 0) {
351 availableWidth = qreal(INT_MAX);
353 availableWidth -= 2*margin + extraMargin;
355 QTextLine line = tl->createLine();
358 line.setLeadingIncluded(
true);
359 line.setLineWidth(availableWidth);
360 line.setPosition(QPointF(margin, height));
361 height += line.height();
362 if (line.leading() < 0)
363 height += qCeil(line.leading());
364 blockMaximumWidth = qMax(blockMaximumWidth, line.naturalTextWidth() + 2*margin);
368 int previousLineCount = doc->lineCount();
369 const_cast<QTextBlock&>(block).setLineCount(block.isVisible() ? tl->lineCount() : 0);
370 int lineCount = doc->lineCount();
372 bool emitDocumentSizeChanged = previousLineCount != lineCount;
373 if (blockMaximumWidth > d->maximumWidth) {
375 d->maximumWidth = blockMaximumWidth;
376 d->maximumWidthBlockNumber = block.blockNumber();
377 emitDocumentSizeChanged =
true;
378 }
else if (block.blockNumber() == d->maximumWidthBlockNumber && blockMaximumWidth < d->maximumWidth) {
380 QTextBlock b = doc->firstBlock();
382 QTextBlock maximumBlock;
383 while (b.isValid()) {
384 qreal blockMaximumWidth = blockWidth(b);
385 if (blockMaximumWidth > d->maximumWidth) {
386 d->maximumWidth = blockMaximumWidth;
391 if (maximumBlock.isValid()) {
392 d->maximumWidthBlockNumber = maximumBlock.blockNumber();
393 emitDocumentSizeChanged =
true;
396 if (emitDocumentSizeChanged && !d->blockDocumentSizeChanged)
397 emit documentSizeChanged(documentSize());
400qreal QPlainTextDocumentLayout::blockWidth(
const QTextBlock &block)
402 QTextLayout *layout = block.layout();
403 if (!layout->lineCount())
405 qreal blockWidth = 0;
406 for (
int i = 0; i < layout->lineCount(); ++i) {
407 QTextLine line = layout->lineAt(i);
408 blockWidth = qMax(line.naturalTextWidth() + 8, blockWidth);
415 : QWidgetTextControl(parent),
textEdit(parent),
418 setAcceptRichText(
false);
423 pageUpDownLastCursorYIsValid =
false;
425#if QT_CONFIG(accessibility)
426 QAccessibleTextCursorEvent ev(q, q->textCursor().position());
427 QAccessible::updateAccessibility(&ev);
429 emit q->cursorPositionChanged();
434 const auto a =
static_cast<QAbstractSlider::SliderAction>(action);
436 case QAbstractSlider::SliderPageStepAdd:
437 pageUpDown(QTextCursor::Down, QTextCursor::MoveAnchor,
false);
439 case QAbstractSlider::SliderPageStepSub:
440 pageUpDown(QTextCursor::Up, QTextCursor::MoveAnchor,
false);
448 QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(parent());
450 return QWidgetTextControl::createMimeDataFromSelection();
451 return ed->createMimeDataFromSelection();
454 QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(parent());
456 return QWidgetTextControl::canInsertFromMimeData(source);
457 return ed->canInsertFromMimeData(source);
460 QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(parent());
462 QWidgetTextControl::insertFromMimeData(source);
464 ed->insertFromMimeData(source);
470 QTextDocument *doc =
control->document();
473 QTextBlock currentBlock = doc->findBlockByNumber(topBlock);
474 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
475 Q_ASSERT(documentLayout);
476 QRectF r = documentLayout->blockBoundingRect(currentBlock);
478 QTextLayout *layout = currentBlock.layout();
479 if (layout && topLine <= layout->lineCount()) {
480 QTextLine line = layout->lineAt(topLine - 1);
481 const QRectF lr = line.naturalTextRect();
482 offset = lr.bottom();
485 if (topBlock == 0 && topLine == 0)
486 offset -= doc->documentMargin();
492 return verticalOffset(control->topBlock, topLine) + topLineFracture;
498 return document()->findBlockByNumber(
topBlock);
505 QTextBlock currentBlock = document()->findBlockByNumber(currentBlockNumber);
506 if (!currentBlock.isValid())
509 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout());
510 Q_ASSERT(documentLayout);
513 QRectF r = documentLayout->blockBoundingRect(currentBlock);
514 while (currentBlock.next().isValid() && r.bottom() + offset.y() <= point.y()) {
515 offset.ry() += r.height();
516 currentBlock = currentBlock.next();
517 ++currentBlockNumber;
518 r = documentLayout->blockBoundingRect(currentBlock);
520 while (currentBlock.previous().isValid() && r.top() + offset.y() > point.y()) {
521 offset.ry() -= r.height();
522 currentBlock = currentBlock.previous();
523 --currentBlockNumber;
524 r = documentLayout->blockBoundingRect(currentBlock);
528 if (!currentBlock.isValid())
530 QTextLayout *layout = currentBlock.layout();
533 for (
int i = 0; i < layout->lineCount(); ++i) {
534 QTextLine line = layout->lineAt(i);
535 const QRectF lr = line.naturalTextRect();
536 if (lr.top() > pos.y()) {
537 off = qMin(off, line.textStart());
538 }
else if (lr.bottom() <= pos.y()) {
539 off = qMax(off, line.textStart() + line.textLength());
541 off = line.xToCursor(pos.x(), overwriteMode() ?
542 QTextLine::CursorOnCharacter : QTextLine::CursorBetweenCharacters);
547 return currentBlock.position() + off;
552 int blockNumber = block.blockNumber();
553 QTextBlock currentBlock = document()->findBlockByNumber(currentBlockNumber);
554 if (!currentBlock.isValid())
556 Q_ASSERT(currentBlock.blockNumber() == currentBlockNumber);
557 QTextDocument *doc = document();
558 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
559 Q_ASSERT(documentLayout);
562 if (!block.isValid())
564 QRectF r = documentLayout->blockBoundingRect(currentBlock);
565 int maxVerticalOffset = r.height();
566 while (currentBlockNumber < blockNumber && offset.y() - maxVerticalOffset <= 2*
textEdit->viewport()->height()) {
567 offset.ry() += r.height();
568 currentBlock = currentBlock.next();
569 ++currentBlockNumber;
570 if (!currentBlock.isVisible()) {
571 currentBlock = doc->findBlockByLineNumber(currentBlock.firstLineNumber());
572 currentBlockNumber = currentBlock.blockNumber();
574 r = documentLayout->blockBoundingRect(currentBlock);
576 while (currentBlockNumber > blockNumber && offset.y() + maxVerticalOffset >= -
textEdit->viewport()->height()) {
577 currentBlock = currentBlock.previous();
578 --currentBlockNumber;
579 while (!currentBlock.isVisible()) {
580 currentBlock = currentBlock.previous();
581 --currentBlockNumber;
583 if (!currentBlock.isValid())
586 r = documentLayout->blockBoundingRect(currentBlock);
587 offset.ry() -= r.height();
590 if (currentBlockNumber != blockNumber) {
593 r = documentLayout->blockBoundingRect(block);
594 if (currentBlockNumber > blockNumber)
595 offset.ry() -= r.height();
603 return textEdit->anchorAt(pos.toPoint());
608 QTextDocument *doc =
control->document();
609 QTextBlock block = doc->findBlockByLineNumber(visualTopLine);
610 int blockNumber = block.blockNumber();
611 int lineNumber = visualTopLine - block.firstLineNumber();
618 blockNumber = qMax(0, blockNumber);
619 lineNumber = qMax(0, lineNumber);
620 QTextDocument *doc =
control->document();
621 QTextBlock block = doc->findBlockByNumber(blockNumber);
623 int newTopLine = block.firstLineNumber() + lineNumber;
624 int maxTopLine = vbar->maximum();
626 if (newTopLine > maxTopLine) {
627 block = doc->findBlockByLineNumber(maxTopLine);
628 blockNumber = block.blockNumber();
629 lineNumber = maxTopLine - block.firstLineNumber();
632 vbar->setValue(newTopLine);
637 if (
viewport->updatesEnabled() && viewport->isVisible()) {
640 qreal realdy = -q->blockBoundingGeometry(block).y()
641 + verticalOffset() - verticalOffset(blockNumber, lineNumber);
643 topLineFracture = realdy - dy;
648 vbar->setValue(block.firstLineNumber() + lineNumber);
651 viewport->scroll(q->isRightToLeft() ? -dx : dx, dy);
652 QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle | Qt::ImAnchorRectangle);
657 emit q->updateRequest(viewport->rect(), dy);
670 QRectF visible = QRectF(viewport->rect()).translated(-q->contentOffset());
671 QTextBlock block = control->document()->findBlock(position);
672 if (!block.isValid())
674 QRectF br = control->blockBoundingRect(block);
677 QTextLine line = block.layout()->lineForTextPosition(position - block.position());
678 Q_ASSERT(line.isValid());
679 QRectF lr = line.naturalTextRect().translated(br.topLeft());
681 if (lr.bottom() >= visible.bottom() || (center && lr.top() < visible.top()) || forceCenter){
683 qreal height = visible.height();
687 qreal h = center ? line.naturalTextRect().center().y() : line.naturalTextRect().bottom();
689 QTextBlock previousVisibleBlock = block;
690 while (h < height && block.previous().isValid()) {
691 previousVisibleBlock = block;
693 block = block.previous();
694 }
while (!block.isVisible() && block.previous().isValid());
695 h += q->blockBoundingRect(block).height();
699 int lineCount = block.layout()->lineCount();
700 qreal voffset = verticalOffset(block.blockNumber(), 0);
701 while (l < lineCount) {
702 QRectF lineRect = block.layout()->lineAt(l).naturalTextRect();
703 if (h - voffset - lineRect.top() <= height)
708 if (l >= lineCount) {
709 block = previousVisibleBlock;
713 }
else if (lr.top() < visible.top()) {
724 emit q->updateRequest(viewport->rect(), 0);
728 : tabChangesFocus(
false)
729 , showCursorOnInitialShow(
false)
730 , backgroundVisible(
false)
731 , centerOnScroll(
false)
733 , clickCausedFocus(
false)
734 , pageUpDownLastCursorYIsValid(
false)
735 , placeholderTextShown(
false)
742 control =
new QPlainTextEditControl(q);
744 QTextDocument *doc =
new QTextDocument(control);
745 QAbstractTextDocumentLayout *layout =
new QPlainTextDocumentLayout(doc);
746 doc->setDocumentLayout(layout);
749 control->setPalette(q->palette());
751 QObjectPrivate::connect(vbar, &QAbstractSlider::actionTriggered,
752 this, &QPlainTextEditPrivate::verticalScrollbarActionTriggered);
753 QObject::connect(control, &QWidgetTextControl::microFocusChanged, q,
754 [q](){q->updateMicroFocus(); });
755 QObjectPrivate::connect(control, &QWidgetTextControl::documentSizeChanged,
756 this, &QPlainTextEditPrivate::adjustScrollbars);
757 QObject::connect(control, &QWidgetTextControl::blockCountChanged,
758 q, &QPlainTextEdit::blockCountChanged);
759 QObjectPrivate::connect(control, &QWidgetTextControl::updateRequest,
760 this, &QPlainTextEditPrivate::repaintContents);
761 QObject::connect(control, &QWidgetTextControl::modificationChanged,
762 q, &QPlainTextEdit::modificationChanged);
763 QObject::connect(control, &QWidgetTextControl::textChanged, q, &QPlainTextEdit::textChanged);
764 QObject::connect(control, &QWidgetTextControl::undoAvailable, q, &QPlainTextEdit::undoAvailable);
765 QObject::connect(control, &QWidgetTextControl::redoAvailable, q, &QPlainTextEdit::redoAvailable);
766 QObject::connect(control, &QWidgetTextControl::copyAvailable, q, &QPlainTextEdit::copyAvailable);
767 QObject::connect(control, &QWidgetTextControl::selectionChanged, q, &QPlainTextEdit::selectionChanged);
768 QObjectPrivate::connect(control, &QWidgetTextControl::cursorPositionChanged,
769 this, &QPlainTextEditPrivate::cursorPositionChanged);
770 QObjectPrivate::connect(control, &QWidgetTextControl::textChanged,
771 this, &QPlainTextEditPrivate::updatePlaceholderVisibility);
772 QObject::connect(control, &QWidgetTextControl::textChanged, q, [q](){q->updateMicroFocus(); });
777 doc->setTextWidth(-1);
778 doc->documentLayout()->setPaintDevice(viewport);
779 doc->setDefaultFont(q->font());
785 hbar->setSingleStep(defaultSingleStep());
786 vbar->setSingleStep(1);
788 viewport->setBackgroundRole(QPalette::Base);
789 q->setAcceptDrops(
true);
790 q->setFocusPolicy(Qt::StrongFocus);
791 q->setAttribute(Qt::WA_KeyCompression);
792 q->setAttribute(Qt::WA_InputMethodEnabled);
793 q->setInputMethodHints(Qt::ImhMultiLine);
796 viewport->setCursor(Qt::IBeamCursor);
806 if (placeholderTextShown != placeHolderTextToBeShown()) {
808 placeholderTextShown = placeHolderTextToBeShown();
815 if (!contentsRect.isValid()) {
820 const int yOffset = (
int)verticalOffset();
821 const QRect visibleRect(xOffset, yOffset, viewport->width(), viewport->height());
823 QRect r = contentsRect.adjusted(-1, -1, 1, 1).intersected(visibleRect).toAlignedRect();
827 r.translate(-xOffset, -yOffset);
829 emit q->updateRequest(r, 0);
837 QTextCursor cursor = control->textCursor();
840 if (!pageUpDownLastCursorYIsValid)
841 pageUpDownLastCursorY = control->cursorRect(cursor).top() - verticalOffset();
844 qreal lastY = pageUpDownLastCursorY;
847 if (op == QTextCursor::Down) {
848 QRectF visible = QRectF(viewport->rect()).translated(-q->contentOffset());
849 QTextBlock firstVisibleBlock = q->firstVisibleBlock();
850 QTextBlock block = firstVisibleBlock;
851 QRectF br = q->blockBoundingRect(block);
854 while (h + br.height() <= visible.bottom()) {
855 if (!block.next().isValid()) {
857 lastY = visible.bottom();
861 block = block.next();
862 br = q->blockBoundingRect(block);
867 qreal diff = visible.bottom() - h;
868 int lineCount = block.layout()->lineCount();
869 while (line < lineCount - 1) {
870 if (block.layout()->lineAt(line).naturalTextRect().bottom() > diff) {
881 lastY += verticalOffset();
884 moved = cursor.movePosition(op, moveMode);
885 }
while (moved &&
control->cursorRect(cursor).top() < lastY);
888 }
else if (op == QTextCursor::Up) {
890 QRectF visible = QRectF(viewport->rect()).translated(-q->contentOffset());
891 visible.translate(0, -visible.height());
892 QTextBlock block = q->firstVisibleBlock();
894 while (h >= visible.top()) {
895 if (!block.previous().isValid()) {
901 block = block.previous();
902 QRectF br = q->blockBoundingRect(block);
907 if (block.isValid()) {
908 qreal diff = visible.top() - h;
909 int lineCount = block.layout()->lineCount();
910 while (line < lineCount) {
911 if (block.layout()->lineAt(line).naturalTextRect().top() >= diff)
915 if (line == lineCount) {
916 if (block.next().isValid() && block.next() != q->firstVisibleBlock()) {
917 block = block.next();
927 cursor.setVisualNavigation(
true);
929 lastY += verticalOffset();
932 moved = cursor.movePosition(op, moveMode);
933 }
while (moved &&
control->cursorRect(cursor).top() > lastY);
938 control->setTextCursor(cursor, moveMode == QTextCursor::KeepAnchor);
939 pageUpDownLastCursorYIsValid =
true;
943#if QT_CONFIG(scrollbar)
945void QPlainTextEditPrivate::adjustScrollbars()
948 QTextDocument *doc = control->document();
949 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
950 Q_ASSERT(documentLayout);
951 bool documentSizeChangedBlocked = documentLayout->priv()->blockDocumentSizeChanged;
952 documentLayout->priv()->blockDocumentSizeChanged =
true;
953 qreal margin = doc->documentMargin();
957 int vSliderLength = 0;
958 if (!centerOnScroll && q->isVisible()) {
959 QTextBlock block = doc->lastBlock();
960 const qreal visible = viewport->rect().height() - margin - 1;
962 int visibleFromBottom = 0;
964 while (block.isValid()) {
965 if (!block.isVisible()) {
966 block = block.previous();
969 y += documentLayout->blockBoundingRect(block).height();
971 QTextLayout *layout = block.layout();
972 int layoutLineCount = layout->lineCount();
975 while (lineNumber < layoutLineCount) {
976 QTextLine line = layout->lineAt(lineNumber);
977 const QRectF lr = line.naturalTextRect();
978 if (lr.top() >= y - visible)
982 if (lineNumber < layoutLineCount)
983 visibleFromBottom += (layoutLineCount - lineNumber);
987 visibleFromBottom += layoutLineCount;
988 block = block.previous();
990 vmax = qMax(0, doc->lineCount() - visibleFromBottom);
991 vSliderLength = visibleFromBottom;
994 vmax = qMax(0, doc->lineCount() - 1);
995 int lineSpacing = q->fontMetrics().lineSpacing();
996 vSliderLength = lineSpacing != 0 ? viewport->height() / lineSpacing : 0;
999 QSizeF documentSize = documentLayout->documentSize();
1000 vbar->setRange(0, qMax(0, vmax));
1001 vbar->setPageStep(vSliderLength);
1002 int visualTopLine = vmax;
1003 QTextBlock firstVisibleBlock = q->firstVisibleBlock();
1004 if (firstVisibleBlock.isValid())
1005 visualTopLine = firstVisibleBlock.firstLineNumber() + topLine;
1007 vbar->setValue(visualTopLine);
1009 hbar->setRange(0, (
int)documentSize.width() - viewport->width());
1010 hbar->setPageStep(viewport->width());
1011 documentLayout->priv()->blockDocumentSizeChanged = documentSizeChangedBlocked;
1012 setTopLine(vbar->value());
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1191
1192
1193
1194
1195
1196
1197
1198
1199
1202
1203
1204
1205
1206
1207
1208
1209
1212
1213
1214
1215
1216
1220
1221
1222
1223QPlainTextEdit::QPlainTextEdit(QWidget *parent)
1224 : QAbstractScrollArea(*
new QPlainTextEditPrivate, parent)
1226 Q_D(QPlainTextEdit);
1231
1232
1233QPlainTextEdit::QPlainTextEdit(QPlainTextEditPrivate &dd, QWidget *parent)
1234 : QAbstractScrollArea(dd, parent)
1236 Q_D(QPlainTextEdit);
1241
1242
1243
1244QPlainTextEdit::QPlainTextEdit(
const QString &text, QWidget *parent)
1245 : QAbstractScrollArea(*
new QPlainTextEditPrivate, parent)
1247 Q_D(QPlainTextEdit);
1253
1254
1255QPlainTextEdit::~QPlainTextEdit()
1257 Q_D(QPlainTextEdit);
1258 if (d->documentLayoutPtr) {
1259 if (d->documentLayoutPtr->priv()->mainViewPrivate == d)
1260 d->documentLayoutPtr->priv()->mainViewPrivate =
nullptr;
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276void QPlainTextEdit::setDocument(QTextDocument *document)
1278 Q_D(QPlainTextEdit);
1279 QPlainTextDocumentLayout *documentLayout =
nullptr;
1282 document =
new QTextDocument(d->control);
1283 documentLayout =
new QPlainTextDocumentLayout(document);
1284 document->setDocumentLayout(documentLayout);
1286 documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document->documentLayout());
1287 if (Q_UNLIKELY(!documentLayout)) {
1288 qWarning(
"QPlainTextEdit::setDocument: Document set does not support QPlainTextDocumentLayout");
1292 d->control->setDocument(document);
1293 if (!documentLayout->priv()->mainViewPrivate)
1294 documentLayout->priv()->mainViewPrivate = d;
1295 d->documentLayoutPtr = documentLayout;
1296 d->updateDefaultTextOption();
1297 d->relayoutDocument();
1298 d->adjustScrollbars();
1302
1303
1304
1305
1306QTextDocument *QPlainTextEdit::document()
const
1308 Q_D(
const QPlainTextEdit);
1309 return d->control->document();
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325void QPlainTextEdit::setPlaceholderText(
const QString &placeholderText)
1327 Q_D(QPlainTextEdit);
1328 if (d->placeholderText != placeholderText) {
1329 d->placeholderText = placeholderText;
1330 d->updatePlaceholderVisibility();
1334QString QPlainTextEdit::placeholderText()
const
1336 Q_D(
const QPlainTextEdit);
1337 return d->placeholderText;
1341
1342
1343void QPlainTextEdit::setTextCursor(
const QTextCursor &cursor)
1345 doSetTextCursor(cursor);
1349
1350
1351
1352
1354void QPlainTextEdit::doSetTextCursor(
const QTextCursor &cursor)
1356 Q_D(QPlainTextEdit);
1357 d->control->setTextCursor(cursor);
1361
1362
1363
1364
1365QTextCursor QPlainTextEdit::textCursor()
const
1367 Q_D(
const QPlainTextEdit);
1368 return d->control->textCursor();
1372
1373
1374
1375
1376
1377QString QPlainTextEdit::anchorAt(
const QPoint &pos)
const
1379 Q_D(
const QPlainTextEdit);
1380 int cursorPos = d->control->hitTest(pos + QPointF(d->horizontalOffset(),
1381 d->verticalOffset()),
1386 QTextDocumentPrivate *pieceTable = QTextDocumentPrivate::get(document());
1387 QTextDocumentPrivate::FragmentIterator it = pieceTable->find(cursorPos);
1388 QTextCharFormat fmt = pieceTable->formatCollection()->charFormat(it->format);
1389 return fmt.anchorHref();
1393
1394
1395
1396
1397
1398
1399
1400void QPlainTextEdit::undo()
1402 Q_D(QPlainTextEdit);
1406void QPlainTextEdit::redo()
1408 Q_D(QPlainTextEdit);
1413
1414
1415
1416
1417
1418
1419
1420
1421
1423#ifndef QT_NO_CLIPBOARD
1425
1426
1427
1428
1429
1430
1431
1433void QPlainTextEdit::cut()
1435 Q_D(QPlainTextEdit);
1440
1441
1442
1443
1445void QPlainTextEdit::copy()
1447 Q_D(QPlainTextEdit);
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1465void QPlainTextEdit::paste()
1467 Q_D(QPlainTextEdit);
1468 d->control->paste();
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484void QPlainTextEdit::clear()
1486 Q_D(QPlainTextEdit);
1488 d->control->topBlock = d->topLine = d->topLineFracture = 0;
1489 d->control->clear();
1494
1495
1496
1497
1498void QPlainTextEdit::selectAll()
1500 Q_D(QPlainTextEdit);
1501 d->control->selectAll();
1505
1506bool QPlainTextEdit::event(QEvent *e)
1508 Q_D(QPlainTextEdit);
1510 switch (e->type()) {
1511#ifndef QT_NO_CONTEXTMENU
1512 case QEvent::ContextMenu:
1513 if (
static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) {
1514 ensureCursorVisible();
1515 const QPoint cursorPos = cursorRect().center();
1516 QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos));
1517 ce.setAccepted(e->isAccepted());
1518 const bool result = QAbstractScrollArea::event(&ce);
1519 e->setAccepted(ce.isAccepted());
1524 case QEvent::ShortcutOverride:
1525 case QEvent::ToolTip:
1526 d->sendControlEvent(e);
1528#ifndef QT_NO_GESTURES
1529 case QEvent::Gesture:
1530 if (
auto *g =
static_cast<QGestureEvent *>(e)->gesture(Qt::PanGesture)) {
1531 QPanGesture *panGesture =
static_cast<QPanGesture *>(g);
1532 QScrollBar *hBar = horizontalScrollBar();
1533 QScrollBar *vBar = verticalScrollBar();
1534 if (panGesture->state() == Qt::GestureStarted)
1535 d->originalOffsetY = vBar->value();
1536 QPointF offset = panGesture->offset();
1537 if (!offset.isNull()) {
1538 if (QGuiApplication::isRightToLeft())
1541 QFontMetrics fm(document()->defaultFont());
1542 int lineHeight = fm.height();
1543 int newX = hBar->value() - panGesture->delta().x();
1544 int newY = d->originalOffsetY - offset.y()/lineHeight;
1545 hBar->setValue(newX);
1546 vBar->setValue(newY);
1551 case QEvent::WindowActivate:
1552 case QEvent::WindowDeactivate:
1553 d->control->setPalette(palette());
1558 return QAbstractScrollArea::event(e);
1562
1564void QPlainTextEdit::timerEvent(QTimerEvent *e)
1566 Q_D(QPlainTextEdit);
1567 if (e->timerId() == d->autoScrollTimer.timerId()) {
1568 QRect visible = d->viewport->rect();
1571 pos = d->autoScrollDragPos;
1572 visible.adjust(qMin(visible.width()/3,20), qMin(visible.height()/3,20),
1573 -qMin(visible.width()/3,20), -qMin(visible.height()/3,20));
1575 const QPoint globalPos = QCursor::pos();
1576 pos = d->viewport->mapFromGlobal(globalPos);
1577 QMouseEvent ev(QEvent::MouseMove, pos, d->viewport->mapTo(d->viewport->topLevelWidget(), pos), globalPos,
1578 Qt::LeftButton, Qt::LeftButton, QGuiApplication::keyboardModifiers());
1579 mouseMoveEvent(&ev);
1581 int deltaY = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height();
1582 int deltaX = qMax(pos.x() - visible.left(), visible.right() - pos.x()) - visible.width();
1583 int delta = qMax(deltaX, deltaY);
1587 int timeout = 4900 / (delta * delta);
1588 d->autoScrollTimer.start(timeout,
this);
1591 d->vbar->triggerAction(pos.y() < visible.center().y() ?
1592 QAbstractSlider::SliderSingleStepSub
1593 : QAbstractSlider::SliderSingleStepAdd);
1595 d->hbar->triggerAction(pos.x() < visible.center().x() ?
1596 QAbstractSlider::SliderSingleStepSub
1597 : QAbstractSlider::SliderSingleStepAdd);
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1618void QPlainTextEdit::setPlainText(
const QString &text)
1620 Q_D(QPlainTextEdit);
1621 d->control->setPlainText(text);
1625
1626
1627
1628
1629
1630
1633
1634void QPlainTextEdit::keyPressEvent(QKeyEvent *e)
1636 Q_D(QPlainTextEdit);
1638#ifndef QT_NO_SHORTCUT
1640 Qt::TextInteractionFlags tif = d->control->textInteractionFlags();
1642 if (tif & Qt::TextSelectableByKeyboard){
1643 if (e == QKeySequence::SelectPreviousPage) {
1645 d->pageUpDown(QTextCursor::Up, QTextCursor::KeepAnchor);
1647 }
else if (e ==QKeySequence::SelectNextPage) {
1649 d->pageUpDown(QTextCursor::Down, QTextCursor::KeepAnchor);
1653 if (tif & (Qt::TextSelectableByKeyboard | Qt::TextEditable)) {
1654 if (e == QKeySequence::MoveToPreviousPage) {
1656 d->pageUpDown(QTextCursor::Up, QTextCursor::MoveAnchor);
1658 }
else if (e == QKeySequence::MoveToNextPage) {
1660 d->pageUpDown(QTextCursor::Down, QTextCursor::MoveAnchor);
1665 if (!(tif & Qt::TextEditable)) {
1669 if (e->modifiers() & Qt::ShiftModifier)
1670 d->vbar->triggerAction(QAbstractSlider::SliderPageStepSub);
1672 d->vbar->triggerAction(QAbstractSlider::SliderPageStepAdd);
1675 d->sendControlEvent(e);
1676 if (!e->isAccepted() && e->modifiers() == Qt::NoModifier) {
1677 if (e->key() == Qt::Key_Home) {
1678 d->vbar->triggerAction(QAbstractSlider::SliderToMinimum);
1680 }
else if (e->key() == Qt::Key_End) {
1681 d->vbar->triggerAction(QAbstractSlider::SliderToMaximum);
1685 if (!e->isAccepted()) {
1686 QAbstractScrollArea::keyPressEvent(e);
1693 d->sendControlEvent(e);
1697
1698void QPlainTextEdit::keyReleaseEvent(QKeyEvent *e)
1700 Q_D(QPlainTextEdit);
1702 d->handleSoftwareInputPanel();
1704 QWidget::keyReleaseEvent(e);
1708
1709
1710
1711
1712
1713
1714QVariant QPlainTextEdit::loadResource(
int type,
const QUrl &name)
1722
1723void QPlainTextEdit::resizeEvent(QResizeEvent *e)
1725 Q_D(QPlainTextEdit);
1726 if (e->oldSize().width() != e->size().width())
1727 d->relayoutDocument();
1728 d->adjustScrollbars();
1733 QTextDocument *doc =
control->document();
1734 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
1735 Q_ASSERT(documentLayout);
1736 documentLayoutPtr = documentLayout;
1738 int width = viewport->width();
1740 if (documentLayout->priv()->mainViewPrivate ==
nullptr
1741 || documentLayout->priv()->mainViewPrivate ==
this
1742 || width > documentLayout->textWidth()) {
1743 documentLayout->priv()->mainViewPrivate =
this;
1744 documentLayout->setTextWidth(width);
1751 if (brush.style() >= Qt::LinearGradientPattern && brush.style() <= Qt::ConicalGradientPattern) {
1752 if (!gradientRect.isNull()) {
1753 QTransform m = QTransform::fromTranslate(gradientRect.left(), gradientRect.top());
1754 m.scale(gradientRect.width(), gradientRect.height());
1755 brush.setTransform(m);
1756 const_cast<QGradient *>(brush.gradient())->setCoordinateMode(QGradient::LogicalMode);
1759 p->setBrushOrigin(rect.topLeft());
1761 p->fillRect(rect, brush);
1768
1769void QPlainTextEdit::paintEvent(QPaintEvent *e)
1771 Q_D(QPlainTextEdit);
1772 QPainter painter(viewport());
1773 Q_ASSERT(qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout()));
1775 QPointF offset(contentOffset());
1777 QRect er = e->rect();
1778 QRect viewportRect = viewport()->rect();
1780 bool editable = !isReadOnly();
1782 QTextBlock block = firstVisibleBlock();
1783 qreal maximumWidth = document()->documentLayout()->documentSize().width();
1786 painter.setBrushOrigin(offset);
1789 int maxX = offset.x() + qMax((qreal)viewportRect.width(), maximumWidth)
1790 - document()->documentMargin() + cursorWidth();
1791 er.setRight(qMin(er.right(), maxX));
1792 painter.setClipRect(er);
1794 if (d->placeHolderTextToBeShown()) {
1795 const QColor col = d->control->palette().placeholderText().color();
1796 painter.setPen(col);
1797 painter.setClipRect(e->rect());
1798 const int margin =
int(document()->documentMargin());
1799 QRectF textRect = viewportRect.adjusted(margin, margin, 0, 0);
1800 painter.drawText(textRect, Qt::AlignTop | Qt::TextWordWrap, placeholderText());
1803 QAbstractTextDocumentLayout::PaintContext context = getPaintContext();
1804 painter.setPen(context.palette.text().color());
1806 while (block.isValid()) {
1808 QRectF r = blockBoundingRect(block).translated(offset);
1809 QTextLayout *layout = block.layout();
1811 if (!block.isVisible()) {
1812 offset.ry() += r.height();
1813 block = block.next();
1817 if (r.bottom() >= er.top() && r.top() <= er.bottom()) {
1819 QTextBlockFormat blockFormat = block.blockFormat();
1821 QBrush bg = blockFormat.background();
1822 if (bg != Qt::NoBrush) {
1823 QRectF contentsRect = r;
1824 contentsRect.setWidth(qMax(r.width(), maximumWidth));
1825 fillBackground(&painter, contentsRect, bg);
1828 QList<QTextLayout::FormatRange> selections;
1829 int blpos = block.position();
1830 int bllen = block.length();
1831 for (
int i = 0; i < context.selections.size(); ++i) {
1832 const QAbstractTextDocumentLayout::Selection &range = context.selections.at(i);
1833 const int selStart = range.cursor.selectionStart() - blpos;
1834 const int selEnd = range.cursor.selectionEnd() - blpos;
1835 if (selStart < bllen && selEnd > 0
1836 && selEnd > selStart) {
1837 QTextLayout::FormatRange o;
1839 o.length = selEnd - selStart;
1840 o.format = range.format;
1841 selections.append(o);
1842 }
else if (!range.cursor.hasSelection() && range.format.hasProperty(QTextFormat::FullWidthSelection)
1843 && block.contains(range.cursor.position())) {
1846 QTextLayout::FormatRange o;
1847 QTextLine l = layout->lineForTextPosition(range.cursor.position() - blpos);
1848 o.start = l.textStart();
1849 o.length = l.textLength();
1850 if (o.start + o.length == bllen - 1)
1852 o.format = range.format;
1853 selections.append(o);
1857 bool drawCursor = ((editable || (textInteractionFlags() & Qt::TextSelectableByKeyboard))
1858 && context.cursorPosition >= blpos
1859 && context.cursorPosition < blpos + bllen);
1861 bool drawCursorAsBlock = drawCursor && overwriteMode() ;
1863 if (drawCursorAsBlock) {
1864 if (context.cursorPosition == blpos + bllen - 1) {
1865 drawCursorAsBlock =
false;
1867 QTextLayout::FormatRange o;
1868 o.start = context.cursorPosition - blpos;
1870 o.format.setForeground(palette().base());
1871 o.format.setBackground(palette().text());
1872 selections.append(o);
1876 layout->draw(&painter, offset, selections, er);
1878 if ((drawCursor && !drawCursorAsBlock)
1879 || (editable && context.cursorPosition < -1
1880 && !layout->preeditAreaText().isEmpty())) {
1881 int cpos = context.cursorPosition;
1883 cpos = layout->preeditAreaPosition() - (cpos + 2);
1886 layout->drawCursor(&painter, offset, cpos, cursorWidth());
1890 offset.ry() += r.height();
1891 if (offset.y() > viewportRect.height())
1893 block = block.next();
1896 if (backgroundVisible() && !block.isValid() && offset.y() <= er.bottom()
1897 && (centerOnScroll() || verticalScrollBar()->maximum() == verticalScrollBar()->minimum())) {
1898 painter.fillRect(QRect(QPoint((
int)er.left(), (
int)offset.y()), er.bottomRight()), palette().window());
1905 QTextDocument *doc =
control->document();
1907 QTextOption opt = doc->defaultTextOption();
1908 QTextOption::WrapMode oldWrapMode = opt.wrapMode();
1910 if (lineWrap == QPlainTextEdit::NoWrap)
1911 opt.setWrapMode(QTextOption::NoWrap);
1913 opt.setWrapMode(wordWrap);
1915 if (opt.wrapMode() != oldWrapMode)
1916 doc->setDefaultTextOption(opt);
1921
1922void QPlainTextEdit::mousePressEvent(QMouseEvent *e)
1924 Q_D(QPlainTextEdit);
1925 d->sendControlEvent(e);
1929
1930void QPlainTextEdit::mouseMoveEvent(QMouseEvent *e)
1932 Q_D(QPlainTextEdit);
1934 const QPoint pos = e->position().toPoint();
1935 d->sendControlEvent(e);
1936 if (!(e->buttons() & Qt::LeftButton))
1938 if (e->source() == Qt::MouseEventNotSynthesized) {
1939 const QRect visible = d->viewport->rect();
1940 if (visible.contains(pos))
1941 d->autoScrollTimer.stop();
1942 else if (!d->autoScrollTimer.isActive())
1943 d->autoScrollTimer.start(100,
this);
1948
1949void QPlainTextEdit::mouseReleaseEvent(QMouseEvent *e)
1951 Q_D(QPlainTextEdit);
1952 d->sendControlEvent(e);
1953 if (e->source() == Qt::MouseEventNotSynthesized && d->autoScrollTimer.isActive()) {
1954 d->autoScrollTimer.stop();
1955 d->ensureCursorVisible();
1958 if (!isReadOnly() && rect().contains(e->position().toPoint()))
1959 d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
1960 d->clickCausedFocus = 0;
1964
1965void QPlainTextEdit::mouseDoubleClickEvent(QMouseEvent *e)
1967 Q_D(QPlainTextEdit);
1968 d->sendControlEvent(e);
1972
1973bool QPlainTextEdit::focusNextPrevChild(
bool next)
1975 Q_D(
const QPlainTextEdit);
1976 if (!d->tabChangesFocus && d->control->textInteractionFlags() & Qt::TextEditable)
1978 return QAbstractScrollArea::focusNextPrevChild(next);
1981#ifndef QT_NO_CONTEXTMENU
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997void QPlainTextEdit::contextMenuEvent(QContextMenuEvent *e)
1999 Q_D(QPlainTextEdit);
2000 d->sendControlEvent(e);
2004#if QT_CONFIG(draganddrop)
2006
2007void QPlainTextEdit::dragEnterEvent(QDragEnterEvent *e)
2009 Q_D(QPlainTextEdit);
2011 d->sendControlEvent(e);
2015
2016void QPlainTextEdit::dragLeaveEvent(QDragLeaveEvent *e)
2018 Q_D(QPlainTextEdit);
2020 d->autoScrollTimer.stop();
2021 d->sendControlEvent(e);
2025
2026void QPlainTextEdit::dragMoveEvent(QDragMoveEvent *e)
2028 Q_D(QPlainTextEdit);
2029 d->autoScrollDragPos = e->position().toPoint();
2030 if (!d->autoScrollTimer.isActive())
2031 d->autoScrollTimer.start(100,
this);
2032 d->sendControlEvent(e);
2036
2037void QPlainTextEdit::dropEvent(QDropEvent *e)
2039 Q_D(QPlainTextEdit);
2041 d->autoScrollTimer.stop();
2042 d->sendControlEvent(e);
2048
2049void QPlainTextEdit::inputMethodEvent(QInputMethodEvent *e)
2051 Q_D(QPlainTextEdit);
2052 d->sendControlEvent(e);
2053 const bool emptyEvent = e->preeditString().isEmpty() && e->commitString().isEmpty()
2054 && e->attributes().isEmpty();
2057 ensureCursorVisible();
2061
2062void QPlainTextEdit::scrollContentsBy(
int dx,
int )
2064 Q_D(QPlainTextEdit);
2065 d->setTopLine(d->vbar->value(), dx);
2069
2070QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery property)
const
2072 return inputMethodQuery(property, QVariant());
2076
2077QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument)
const
2079 Q_D(
const QPlainTextEdit);
2082 return isEnabled() && !isReadOnly();
2084 case Qt::ImInputItemClipRectangle:
2085 return QWidget::inputMethodQuery(query);
2086 case Qt::ImReadOnly:
2087 return isReadOnly();
2092 const QPointF offset = contentOffset();
2093 switch (argument.userType()) {
2094 case QMetaType::QRectF:
2095 argument = argument.toRectF().translated(-offset);
2097 case QMetaType::QPointF:
2098 argument = argument.toPointF() - offset;
2100 case QMetaType::QRect:
2101 argument = argument.toRect().translated(-offset.toPoint());
2103 case QMetaType::QPoint:
2104 argument = argument.toPoint() - offset;
2110 const QVariant v = d->control->inputMethodQuery(query, argument);
2111 switch (v.userType()) {
2112 case QMetaType::QRectF:
2113 return v.toRectF().translated(offset);
2114 case QMetaType::QPointF:
2115 return v.toPointF() + offset;
2116 case QMetaType::QRect:
2117 return v.toRect().translated(offset.toPoint());
2118 case QMetaType::QPoint:
2119 return v.toPoint() + offset.toPoint();
2127
2128void QPlainTextEdit::focusInEvent(QFocusEvent *e)
2130 Q_D(QPlainTextEdit);
2131 if (e->reason() == Qt::MouseFocusReason) {
2132 d->clickCausedFocus = 1;
2134 QAbstractScrollArea::focusInEvent(e);
2135 d->sendControlEvent(e);
2139
2140void QPlainTextEdit::focusOutEvent(QFocusEvent *e)
2142 Q_D(QPlainTextEdit);
2143 QAbstractScrollArea::focusOutEvent(e);
2144 d->sendControlEvent(e);
2148
2149void QPlainTextEdit::showEvent(QShowEvent *)
2151 Q_D(QPlainTextEdit);
2152 if (d->showCursorOnInitialShow) {
2153 d->showCursorOnInitialShow =
false;
2154 ensureCursorVisible();
2156 d->adjustScrollbars();
2160
2161void QPlainTextEdit::changeEvent(QEvent *e)
2163 Q_D(QPlainTextEdit);
2164 QAbstractScrollArea::changeEvent(e);
2166 switch (e->type()) {
2167 case QEvent::ApplicationFontChange:
2168 case QEvent::FontChange:
2169 d->control->document()->setDefaultFont(font());
2171 case QEvent::ActivationChange:
2172 if (!isActiveWindow())
2173 d->autoScrollTimer.stop();
2175 case QEvent::EnabledChange:
2176 e->setAccepted(isEnabled());
2177 d->control->setPalette(palette());
2178 d->sendControlEvent(e);
2180 case QEvent::PaletteChange:
2181 d->control->setPalette(palette());
2183 case QEvent::LayoutDirectionChange:
2184 d->sendControlEvent(e);
2192
2193#if QT_CONFIG(wheelevent)
2194void QPlainTextEdit::wheelEvent(QWheelEvent *e)
2196 Q_D(QPlainTextEdit);
2197 if (!(d->control->textInteractionFlags() & Qt::TextEditable)) {
2198 if (e->modifiers() & Qt::ControlModifier) {
2199 float delta = e->angleDelta().y() / 120.f;
2204 QAbstractScrollArea::wheelEvent(e);
2210
2211
2212
2213
2214
2215
2216void QPlainTextEdit::zoomIn(
int range)
2222
2223
2224
2225
2226
2227
2228void QPlainTextEdit::zoomOut(
int range)
2234
2235
2236void QPlainTextEdit::zoomInF(
float range)
2241 const float newSize = f.pointSizeF() + range;
2244 f.setPointSizeF(newSize);
2248#ifndef QT_NO_CONTEXTMENU
2250
2251
2252
2253
2254
2255
2256
2258QMenu *QPlainTextEdit::createStandardContextMenu()
2260 Q_D(QPlainTextEdit);
2261 return d->control->createStandardContextMenu(QPointF(),
this);
2265
2266
2267
2268
2269
2270
2271
2272
2274QMenu *QPlainTextEdit::createStandardContextMenu(
const QPoint &position)
2276 Q_D(QPlainTextEdit);
2277 return d->control->createStandardContextMenu(position,
this);
2282
2283
2284QTextCursor QPlainTextEdit::cursorForPosition(
const QPoint &pos)
const
2286 Q_D(
const QPlainTextEdit);
2287 return d->control->cursorForPosition(d->mapToContents(pos));
2291
2292
2293
2294QRect QPlainTextEdit::cursorRect(
const QTextCursor &cursor)
const
2296 Q_D(
const QPlainTextEdit);
2297 if (cursor.isNull())
2300 QRect r = d->control->cursorRect(cursor).toRect();
2301 r.translate(-d->horizontalOffset(),-(
int)d->verticalOffset());
2306
2307
2308
2309QRect QPlainTextEdit::cursorRect()
const
2311 Q_D(
const QPlainTextEdit);
2312 QRect r = d->control->cursorRect().toRect();
2313 r.translate(-d->horizontalOffset(),-(
int)d->verticalOffset());
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2332bool QPlainTextEdit::overwriteMode()
const
2334 Q_D(
const QPlainTextEdit);
2335 return d->control->overwriteMode();
2338void QPlainTextEdit::setOverwriteMode(
bool overwrite)
2340 Q_D(QPlainTextEdit);
2341 d->control->setOverwriteMode(overwrite);
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2358qreal QPlainTextEdit::tabStopDistance()
const
2360 Q_D(
const QPlainTextEdit);
2361 return d->control->document()->defaultTextOption().tabStopDistance();
2364void QPlainTextEdit::setTabStopDistance(qreal distance)
2366 Q_D(QPlainTextEdit);
2367 QTextOption opt = d->control->document()->defaultTextOption();
2368 if (opt.tabStopDistance() == distance || distance < 0)
2370 opt.setTabStopDistance(distance);
2371 d->control->document()->setDefaultTextOption(opt);
2376
2377
2378
2379
2380int QPlainTextEdit::cursorWidth()
const
2382 Q_D(
const QPlainTextEdit);
2383 return d->control->cursorWidth();
2386void QPlainTextEdit::setCursorWidth(
int width)
2388 Q_D(QPlainTextEdit);
2389 d->control->setCursorWidth(width);
2395
2396
2397
2398
2399
2400
2401
2402void QPlainTextEdit::setExtraSelections(
const QList<QTextEdit::ExtraSelection> &selections)
2404 Q_D(QPlainTextEdit);
2405 d->control->setExtraSelections(selections);
2409
2410
2411
2412
2413QList<QTextEdit::ExtraSelection> QPlainTextEdit::extraSelections()
const
2415 Q_D(
const QPlainTextEdit);
2416 return d->control->extraSelections();
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429QMimeData *QPlainTextEdit::createMimeDataFromSelection()
const
2431 Q_D(
const QPlainTextEdit);
2432 return d->control->QWidgetTextControl::createMimeDataFromSelection();
2436
2437
2438
2439
2440
2441bool QPlainTextEdit::canInsertFromMimeData(
const QMimeData *source)
const
2443 Q_D(
const QPlainTextEdit);
2444 return d->control->QWidgetTextControl::canInsertFromMimeData(source);
2448
2449
2450
2451
2452
2453
2454void QPlainTextEdit::insertFromMimeData(
const QMimeData *source)
2456 Q_D(QPlainTextEdit);
2457 d->control->QWidgetTextControl::insertFromMimeData(source);
2461
2462
2463
2464
2465
2466
2467
2468
2470bool QPlainTextEdit::isReadOnly()
const
2472 Q_D(
const QPlainTextEdit);
2473 return !d->control || !(d->control->textInteractionFlags() & Qt::TextEditable);
2476void QPlainTextEdit::setReadOnly(
bool ro)
2478 Q_D(QPlainTextEdit);
2479 Qt::TextInteractionFlags flags = Qt::NoTextInteraction;
2481 flags = Qt::TextSelectableByMouse;
2483 flags = Qt::TextEditorInteraction;
2485 d->control->setTextInteractionFlags(flags);
2486 setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(
this));
2487 QEvent event(QEvent::ReadOnlyChange);
2488 QCoreApplication::sendEvent(
this, &event);
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2503void QPlainTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
2505 Q_D(QPlainTextEdit);
2506 d->control->setTextInteractionFlags(flags);
2509Qt::TextInteractionFlags QPlainTextEdit::textInteractionFlags()
const
2511 Q_D(
const QPlainTextEdit);
2512 return d->control->textInteractionFlags();
2516
2517
2518
2519
2520
2521
2522
2523void QPlainTextEdit::mergeCurrentCharFormat(
const QTextCharFormat &modifier)
2525 Q_D(QPlainTextEdit);
2526 d->control->mergeCurrentCharFormat(modifier);
2530
2531
2532
2533
2534
2535void QPlainTextEdit::setCurrentCharFormat(
const QTextCharFormat &format)
2537 Q_D(QPlainTextEdit);
2538 d->control->setCurrentCharFormat(format);
2542
2543
2544QTextCharFormat QPlainTextEdit::currentCharFormat()
const
2546 Q_D(
const QPlainTextEdit);
2547 return d->control->currentCharFormat();
2553
2554
2555
2556
2557
2558
2559
2560void QPlainTextEdit::insertPlainText(
const QString &text)
2562 Q_D(QPlainTextEdit);
2563 d->control->insertPlainText(text);
2568
2569
2570
2571
2572
2573
2574
2575
2576void QPlainTextEdit::moveCursor(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode)
2578 Q_D(QPlainTextEdit);
2579 d->control->moveCursor(operation, mode);
2583
2584
2585bool QPlainTextEdit::canPaste()
const
2587 Q_D(
const QPlainTextEdit);
2588 return d->control->canPaste();
2592
2593
2594
2595
2596
2597
2598#ifndef QT_NO_PRINTER
2599void QPlainTextEdit::print(QPagedPaintDevice *printer)
const
2601 Q_D(
const QPlainTextEdit);
2602 d->control->print(printer);
2607
2608
2609
2610
2611
2612
2613
2615bool QPlainTextEdit::tabChangesFocus()
const
2617 Q_D(
const QPlainTextEdit);
2618 return d->tabChangesFocus;
2621void QPlainTextEdit::setTabChangesFocus(
bool b)
2623 Q_D(QPlainTextEdit);
2624 d->tabChangesFocus = b;
2628
2629
2630
2631
2632
2635
2636
2637
2638
2639
2640
2641
2642
2644QPlainTextEdit::LineWrapMode QPlainTextEdit::lineWrapMode()
const
2646 Q_D(
const QPlainTextEdit);
2650void QPlainTextEdit::setLineWrapMode(LineWrapMode wrap)
2652 Q_D(QPlainTextEdit);
2653 if (d->lineWrap == wrap)
2656 d->updateDefaultTextOption();
2657 d->relayoutDocument();
2658 d->adjustScrollbars();
2659 ensureCursorVisible();
2663
2664
2665
2666
2667
2668
2669
2671QTextOption::WrapMode QPlainTextEdit::wordWrapMode()
const
2673 Q_D(
const QPlainTextEdit);
2677void QPlainTextEdit::setWordWrapMode(QTextOption::WrapMode mode)
2679 Q_D(QPlainTextEdit);
2680 if (mode == d->wordWrap)
2683 d->updateDefaultTextOption();
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2700bool QPlainTextEdit::backgroundVisible()
const
2702 Q_D(
const QPlainTextEdit);
2703 return d->backgroundVisible;
2706void QPlainTextEdit::setBackgroundVisible(
bool visible)
2708 Q_D(QPlainTextEdit);
2709 if (visible == d->backgroundVisible)
2711 d->backgroundVisible = visible;
2712 d->updateViewport();
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2732bool QPlainTextEdit::centerOnScroll()
const
2734 Q_D(
const QPlainTextEdit);
2735 return d->centerOnScroll;
2738void QPlainTextEdit::setCenterOnScroll(
bool enabled)
2740 Q_D(QPlainTextEdit);
2741 if (enabled == d->centerOnScroll)
2743 d->centerOnScroll = enabled;
2744 d->adjustScrollbars();
2750
2751
2752
2753
2754bool QPlainTextEdit::find(
const QString &exp, QTextDocument::FindFlags options)
2756 Q_D(QPlainTextEdit);
2757 return d->control->find(exp, options);
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776#if QT_CONFIG(regularexpression)
2777bool QPlainTextEdit::find(
const QRegularExpression &exp, QTextDocument::FindFlags options)
2779 Q_D(QPlainTextEdit);
2780 return d->control->find(exp, options);
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2802
2803
2804
2805
2806
2807
2810
2811
2812
2813
2814
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2832
2833
2834
2835
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2855 Q_Q(QPlainTextEdit);
2857 QTextDocument *document =
control->document();
2858 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document->documentLayout());
2859 Q_ASSERT(documentLayout);
2861 int maximumBlockCount = document->maximumBlockCount();
2862 if (maximumBlockCount)
2863 document->setMaximumBlockCount(0);
2865 const bool atBottom = q->isVisible()
2866 && (control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
2867 <= viewport->rect().bottom());
2869 if (!q->isVisible())
2870 showCursorOnInitialShow =
true;
2872 bool documentSizeChangedBlocked = documentLayout->priv()->blockDocumentSizeChanged;
2873 documentLayout->priv()->blockDocumentSizeChanged =
true;
2880 control->appendPlainText(text);
2887 if (maximumBlockCount > 0) {
2888 if (document->blockCount() > maximumBlockCount) {
2889 bool blockUpdate =
false;
2893 emit q->updateRequest(viewport->rect(), 0);
2896 bool updatesBlocked = documentLayout->priv()->blockUpdate;
2897 documentLayout->priv()->blockUpdate = blockUpdate;
2898 QTextCursor cursor(document);
2899 cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
2900 cursor.removeSelectedText();
2901 documentLayout->priv()->blockUpdate = updatesBlocked;
2903 document->setMaximumBlockCount(maximumBlockCount);
2906 documentLayout->priv()->blockDocumentSizeChanged = documentSizeChangedBlocked;
2911 const bool needScroll = !centerOnScroll
2912 || control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
2913 > viewport->rect().bottom();
2915 vbar->setValue(vbar->maximum());
2921
2922
2923
2924
2926void QPlainTextEdit::appendPlainText(
const QString &text)
2928 Q_D(QPlainTextEdit);
2929 d->append(text, Qt::PlainText);
2933
2934
2935
2936
2938void QPlainTextEdit::appendHtml(
const QString &html)
2940 Q_D(QPlainTextEdit);
2941 d->append(html, Qt::RichText);
2946 Q_Q(QPlainTextEdit);
2947 QRect visible = viewport->rect();
2948 QRect cr = q->cursorRect();
2949 if (cr.top() < visible.top() || cr.bottom() > visible.bottom()) {
2953 const bool rtl = q->isRightToLeft();
2954 if (cr.left() < visible.left() || cr.right() > visible.right()) {
2956 hbar->setValue(rtl ? hbar->maximum() - x : x);
2961
2962
2963
2964
2965
2966void QPlainTextEdit::ensureCursorVisible()
2968 Q_D(QPlainTextEdit);
2969 d->ensureCursorVisible(d->centerOnScroll);
2974
2975
2976
2977void QPlainTextEdit::centerCursor()
2979 Q_D(QPlainTextEdit);
2980 d->ensureVisible(textCursor().position(),
true,
true);
2984
2985
2986
2987
2988QTextBlock QPlainTextEdit::firstVisibleBlock()
const
2990 Q_D(
const QPlainTextEdit);
2991 return d->control->firstVisibleBlock();
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007QPointF QPlainTextEdit::contentOffset()
const
3009 Q_D(
const QPlainTextEdit);
3010 return QPointF(-d->horizontalOffset(), -d->verticalOffset());
3015
3016
3017
3018
3019
3020QRectF QPlainTextEdit::blockBoundingGeometry(
const QTextBlock &block)
const
3022 Q_D(
const QPlainTextEdit);
3023 return d->control->blockBoundingRect(block);
3027
3028
3029
3030
3031QRectF QPlainTextEdit::blockBoundingRect(
const QTextBlock &block)
const
3033 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout());
3034 Q_ASSERT(documentLayout);
3035 return documentLayout->blockBoundingRect(block);
3039
3040
3041
3042
3043
3044int QPlainTextEdit::blockCount()
const
3046 return document()->blockCount();
3050
3051
3052QAbstractTextDocumentLayout::PaintContext QPlainTextEdit::getPaintContext()
const
3054 Q_D(
const QPlainTextEdit);
3055 return d->control->getPaintContext(d->viewport);
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3078
3079
3080
3081
3082
3085
3086
3087
3088
3089
3092
3093
3094
3095
3096
3100#include "moc_qplaintextedit.cpp"
3101#include "moc_qplaintextedit_p.cpp"
QRect viewport() const
Returns the viewport rectangle.
bool blockDocumentSizeChanged
int maximumWidthBlockNumber
void layoutBlock(const QTextBlock &block)
qreal blockWidth(const QTextBlock &block)
QPlainTextEditPrivate * mainViewPrivate
QPlainTextEdit * textEdit
void insertFromMimeData(const QMimeData *source) override
bool canInsertFromMimeData(const QMimeData *source) const override
QTextBlock firstVisibleBlock() const
QMimeData * createMimeDataFromSelection() const override
qreal verticalOffset() const
int horizontalOffset() const
void pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode, bool moveCursor=true)
QPlainTextEditControl * control
void updateDefaultTextOption()
void ensureVisible(int position, bool center, bool forceCenter=false)
void updatePlaceholderVisibility()
qreal verticalOffset(int topBlock, int topLine) const
void setTopLine(int visualTopLine, int dx=0)
void verticalScrollbarActionTriggered(int action)
void cursorPositionChanged()
void ensureCursorVisible(bool center=false)
void ensureViewportLayouted()
void setTopBlock(int newTopBlock, int newTopLine, int dx=0)
\inmodule QtCore\reentrant
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE bool shouldEnableInputMethod(QPlainTextEdit *control)
static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, const QRectF &gradientRect=QRectF())