Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qplaintextedit.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 "qplaintextedit_p.h"
5
6
7#include <qfont.h>
8#include <qpainter.h>
9#include <qevent.h>
10#include <qdebug.h>
11#if QT_CONFIG(draganddrop)
12#include <qdrag.h>
13#endif
14#include <qclipboard.h>
15#include <qmath.h>
16#if QT_CONFIG(menu)
17#include <qmenu.h>
18#endif
19#include <qstyle.h>
20#include <qtimer.h>
21#include "private/qapplication_p.h"
22#include "private/qtextdocumentlayout_p.h"
23#include "private/qabstracttextdocumentlayout_p.h"
24#include "qtextdocument.h"
25#include "private/qtextdocument_p.h"
26#include "qtextlist.h"
27#include "qaccessible.h"
28
29#include <qtextformat.h>
30#include <qdatetime.h>
31#include <qapplication.h>
32#include <limits.h>
33#include <qtexttable.h>
34#include <qvariant.h>
35
37
38static inline bool shouldEnableInputMethod(QPlainTextEdit *control)
39{
40#if defined(Q_OS_ANDROID)
41 Q_UNUSED(control);
42 return !control->isReadOnly() || (control->textInteractionFlags() & Qt::TextSelectableByMouse);
43#else
44 return !control->isReadOnly();
45#endif
46}
47
49{
50 Q_DECLARE_PUBLIC(QPlainTextDocumentLayout)
51public:
53 mainViewPrivate = nullptr;
54 width = 0;
55 maximumWidth = 0;
57 blockCount = 1;
59 cursorWidth = 1;
61 }
62
72
73 void layoutBlock(const QTextBlock &block);
75
76 void relayout();
77};
78
79
80
110}
115
116
121{
122}
123
128{
129// this function is used from
130// QAbstractTextDocumentLayout::anchorAt(), but is not
131// implementable in a plain text document layout, because the
132// layout depends on the top block and top line which depends on
133// the view
134 return -1;
135}
136
141{ return 1; }
142
147{
148 Q_D(const QPlainTextDocumentLayout);
149 return QSizeF(d->maximumWidth, document()->lineCount());
150}
151
156{
157 Q_D(const QPlainTextDocumentLayout);
158 return QRectF(0, 0, qMax(d->width, d->maximumWidth), qreal(INT_MAX));
159}
160
165{
166 if (!block.isValid()) { return QRectF(); }
167 QTextLayout *tl = block.layout();
168 if (!tl->lineCount())
169 const_cast<QPlainTextDocumentLayout*>(this)->layoutBlock(block);
170 QRectF br;
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);
179 }
180 return br;
181
182}
183
188{
189 if (!block.isValid())
190 return;
191 QTextLayout *tl = block.layout();
192 if (!tl->lineCount())
193 const_cast<QPlainTextDocumentLayout*>(this)->layoutBlock(block);
194}
195
196
202{
204 d->cursorWidth = width;
205}
206
208{
209 Q_D(const QPlainTextDocumentLayout);
210 return d->cursorWidth;
211}
212
213QPlainTextDocumentLayoutPrivate *QPlainTextDocumentLayout::priv() const
214{
215 Q_D(const QPlainTextDocumentLayout);
216 return const_cast<QPlainTextDocumentLayoutPrivate*>(d);
217}
218
219
225{
226 emit update(QRectF(0., -document()->documentMargin(), 1000000000., 1000000000.));
227}
228
229
230void QPlainTextDocumentLayout::setTextWidth(qreal newWidth)
231{
233 d->width = d->maximumWidth = newWidth;
234 d->relayout();
235}
236
237qreal QPlainTextDocumentLayout::textWidth() const
238{
239 Q_D(const QPlainTextDocumentLayout);
240 return d->width;
241}
242
244{
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();
251 }
252 emit q->update();
253}
254
255
258void QPlainTextDocumentLayout::documentChanged(int from, int charsRemoved, int charsAdded)
259{
261 QTextDocument *doc = document();
262 int newBlockCount = doc->blockCount();
263 int charsChanged = charsRemoved + charsAdded;
264
265 QTextBlock changeStartBlock = doc->findBlock(from);
266 QTextBlock changeEndBlock = doc->findBlock(qMax(0, from + charsChanged - 1));
267 bool blockVisibilityChanged = false;
268
269 if (changeStartBlock == changeEndBlock && newBlockCount == d->blockCount) {
270 QTextBlock block = changeStartBlock;
271 if (block.isValid() && block.length()) {
272 QRectF oldBr = blockBoundingRect(block);
273 layoutBlock(block);
274 QRectF newBr = blockBoundingRect(block);
275 if (newBr.height() == oldBr.height()) {
276 if (!d->blockUpdate)
277 emit updateBlock(block);
278 return;
279 }
280 }
281 } else {
282 QTextBlock block = changeStartBlock;
283 do {
284 block.clearLayout();
285 if (block.isVisible()
286 ? (block.lineCount() == 0)
287 : (block.lineCount() > 0)) {
288 blockVisibilityChanged = true;
289 block.setLineCount(block.isVisible() ? 1 : 0);
290 }
291 if (block == changeEndBlock)
292 break;
293 block = block.next();
294 } while(block.isValid());
295 }
296
297 if (newBlockCount != d->blockCount || blockVisibilityChanged) {
298 int changeEnd = changeEndBlock.blockNumber();
299 int blockDiff = newBlockCount - d->blockCount;
300 int oldChangeEnd = changeEnd - blockDiff;
301
302 if (d->maximumWidthBlockNumber > oldChangeEnd)
303 d->maximumWidthBlockNumber += blockDiff;
304
305 d->blockCount = newBlockCount;
306 if (d->blockCount == 1)
307 d->maximumWidth = blockWidth(doc->firstBlock());
308
309 if (!d->blockDocumentSizeChanged)
311
312 if (blockDiff == 1 && changeEnd == newBlockCount -1 ) {
313 if (!d->blockUpdate) {
314 QTextBlock b = changeStartBlock;
315 for(;;) {
317 if (b == changeEndBlock)
318 break;
319 b = b.next();
320 }
321 }
322 return;
323 }
324 }
325
326 if (!d->blockUpdate)
327 emit update(QRectF(0., -doc->documentMargin(), 1000000000., 1000000000.)); // optimization potential
328}
329
330
331void QPlainTextDocumentLayout::layoutBlock(const QTextBlock &block)
332{
334 QTextDocument *doc = document();
335 qreal margin = doc->documentMargin();
336 qreal blockMaximumWidth = 0;
337
338 qreal height = 0;
339 QTextLayout *tl = block.layout();
342
343 int extraMargin = 0;
345 QFontMetrics fm(block.charFormat().font());
346 extraMargin += fm.horizontalAdvance(QChar(0x21B5));
347 }
348 tl->beginLayout();
349 qreal availableWidth = d->width;
350 if (availableWidth <= 0) {
351 availableWidth = qreal(INT_MAX); // similar to text edit with pageSize.width == 0
352 }
353 availableWidth -= 2*margin + extraMargin;
354 while (1) {
355 QTextLine line = tl->createLine();
356 if (!line.isValid())
357 break;
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);
365 }
366 tl->endLayout();
367
368 int previousLineCount = doc->lineCount();
369 const_cast<QTextBlock&>(block).setLineCount(block.isVisible() ? tl->lineCount() : 0);
370 int lineCount = doc->lineCount();
371
372 bool emitDocumentSizeChanged = previousLineCount != lineCount;
373 if (blockMaximumWidth > d->maximumWidth) {
374 // new longest line
375 d->maximumWidth = blockMaximumWidth;
376 d->maximumWidthBlockNumber = block.blockNumber();
377 emitDocumentSizeChanged = true;
378 } else if (block.blockNumber() == d->maximumWidthBlockNumber && blockMaximumWidth < d->maximumWidth) {
379 // longest line shrinking
380 QTextBlock b = doc->firstBlock();
381 d->maximumWidth = 0;
382 QTextBlock maximumBlock;
383 while (b.isValid()) {
384 qreal blockMaximumWidth = blockWidth(b);
385 if (blockMaximumWidth > d->maximumWidth) {
386 d->maximumWidth = blockMaximumWidth;
387 maximumBlock = b;
388 }
389 b = b.next();
390 }
391 if (maximumBlock.isValid()) {
392 d->maximumWidthBlockNumber = maximumBlock.blockNumber();
393 emitDocumentSizeChanged = true;
394 }
395 }
396 if (emitDocumentSizeChanged && !d->blockDocumentSizeChanged)
398}
399
400qreal QPlainTextDocumentLayout::blockWidth(const QTextBlock &block)
401{
402 QTextLayout *layout = block.layout();
403 if (!layout->lineCount())
404 return 0; // only for layouted blocks
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);
409 }
410 return blockWidth;
411}
412
413
416 topBlock(0)
417{
418 setAcceptRichText(false);
419}
420
422{
424 Q_Q(QPlainTextEdit);
425#if QT_CONFIG(accessibility)
426 QAccessibleTextCursorEvent ev(q, q->textCursor().position());
427 QAccessible::updateAccessibility(&ev);
428#endif
429 emit q->cursorPositionChanged();
430}
431
433
434 const auto a = static_cast<QAbstractSlider::SliderAction>(action);
435 switch (a) {
438 break;
441 break;
442 default:
443 break;
444 }
445}
446
448 QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(parent());
449 if (!ed)
451 return ed->createMimeDataFromSelection();
452 }
454 QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(parent());
455 if (!ed)
457 return ed->canInsertFromMimeData(source);
458}
460 QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(parent());
461 if (!ed)
463 else
465}
466
467qreal QPlainTextEditPrivate::verticalOffset(int topBlock, int topLine) const
468{
469 qreal offset = 0;
471
472 if (topLine) {
473 QTextBlock currentBlock = doc->findBlockByNumber(topBlock);
474 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
475 Q_ASSERT(documentLayout);
476 QRectF r = documentLayout->blockBoundingRect(currentBlock);
477 Q_UNUSED(r);
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();
483 }
484 }
485 if (topBlock == 0 && topLine == 0)
486 offset -= doc->documentMargin(); // top margin
487 return offset;
488}
489
490
493}
494
495
497{
499}
500
501
502
504 int currentBlockNumber = topBlock;
505 QTextBlock currentBlock = document()->findBlockByNumber(currentBlockNumber);
506 if (!currentBlock.isValid())
507 return -1;
508
509 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout());
510 Q_ASSERT(documentLayout);
511
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);
519 }
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);
525 }
526
527
528 if (!currentBlock.isValid())
529 return -1;
530 QTextLayout *layout = currentBlock.layout();
531 int off = 0;
532 QPointF pos = point - offset;
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());
540 } else {
541 off = line.xToCursor(pos.x(), overwriteMode() ?
543 break;
544 }
545 }
546
547 return currentBlock.position() + off;
548}
549
551 int currentBlockNumber = topBlock;
552 int blockNumber = block.blockNumber();
553 QTextBlock currentBlock = document()->findBlockByNumber(currentBlockNumber);
554 if (!currentBlock.isValid())
555 return QRectF();
556 Q_ASSERT(currentBlock.blockNumber() == currentBlockNumber);
557 QTextDocument *doc = document();
558 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
559 Q_ASSERT(documentLayout);
560
562 if (!block.isValid())
563 return QRectF();
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();
573 }
574 r = documentLayout->blockBoundingRect(currentBlock);
575 }
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;
582 }
583 if (!currentBlock.isValid())
584 break;
585
586 r = documentLayout->blockBoundingRect(currentBlock);
587 offset.ry() -= r.height();
588 }
589
590 if (currentBlockNumber != blockNumber) {
591 // fallback for blocks out of reach. Give it some geometry at
592 // least, and ensure the layout is up to date.
593 r = documentLayout->blockBoundingRect(block);
594 if (currentBlockNumber > blockNumber)
595 offset.ry() -= r.height();
596 }
597 r.translate(offset);
598 return r;
599}
600
602{
603 return textEdit->anchorAt(pos.toPoint());
604}
605
606void QPlainTextEditPrivate::setTopLine(int visualTopLine, int dx)
607{
609 QTextBlock block = doc->findBlockByLineNumber(visualTopLine);
610 int blockNumber = block.blockNumber();
611 int lineNumber = visualTopLine - block.firstLineNumber();
612 setTopBlock(blockNumber, lineNumber, dx);
613}
614
615void QPlainTextEditPrivate::setTopBlock(int blockNumber, int lineNumber, int dx)
616{
617 Q_Q(QPlainTextEdit);
618 blockNumber = qMax(0, blockNumber);
619 lineNumber = qMax(0, lineNumber);
621 QTextBlock block = doc->findBlockByNumber(blockNumber);
622
623 int newTopLine = block.firstLineNumber() + lineNumber;
624 int maxTopLine = vbar->maximum();
625
626 if (newTopLine > maxTopLine) {
627 block = doc->findBlockByLineNumber(maxTopLine);
628 blockNumber = block.blockNumber();
629 lineNumber = maxTopLine - block.firstLineNumber();
630 }
631
632 vbar->setValue(newTopLine);
633
634 if (!dx && blockNumber == control->topBlock && lineNumber == topLine)
635 return;
636
637 if (viewport->updatesEnabled() && viewport->isVisible()) {
638 int dy = 0;
640 qreal realdy = -q->blockBoundingGeometry(block).y()
641 + verticalOffset() - verticalOffset(blockNumber, lineNumber);
642 dy = (int)realdy;
643 topLineFracture = realdy - dy;
644 }
645 control->topBlock = blockNumber;
646 topLine = lineNumber;
647
648 vbar->setValue(block.firstLineNumber() + lineNumber);
649
650 if (dx || dy) {
651 viewport->scroll(q->isRightToLeft() ? -dx : dx, dy);
653 } else {
654 viewport->update();
655 topLineFracture = 0;
656 }
657 emit q->updateRequest(viewport->rect(), dy);
658 } else {
659 control->topBlock = blockNumber;
660 topLine = lineNumber;
661 topLineFracture = 0;
662 }
663
664}
665
666
667
668void QPlainTextEditPrivate::ensureVisible(int position, bool center, bool forceCenter) {
669 Q_Q(QPlainTextEdit);
670 QRectF visible = QRectF(viewport->rect()).translated(-q->contentOffset());
672 if (!block.isValid())
673 return;
674 QRectF br = control->blockBoundingRect(block);
675 if (!br.isValid())
676 return;
678 Q_ASSERT(line.isValid());
679 QRectF lr = line.naturalTextRect().translated(br.topLeft());
680
681 if (lr.bottom() >= visible.bottom() || (center && lr.top() < visible.top()) || forceCenter){
682
683 qreal height = visible.height();
684 if (center)
685 height /= 2;
686
687 qreal h = center ? line.naturalTextRect().center().y() : line.naturalTextRect().bottom();
688
689 QTextBlock previousVisibleBlock = block;
690 while (h < height && block.previous().isValid()) {
691 previousVisibleBlock = block;
692 do {
693 block = block.previous();
694 } while (!block.isVisible() && block.previous().isValid());
695 h += q->blockBoundingRect(block).height();
696 }
697
698 int l = 0;
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)
704 break;
705 ++l;
706 }
707
708 if (l >= lineCount) {
709 block = previousVisibleBlock;
710 l = 0;
711 }
712 setTopBlock(block.blockNumber(), l);
713 } else if (lr.top() < visible.top()) {
714 setTopBlock(block.blockNumber(), line.lineNumber());
715 }
716
717}
718
719
721{
722 Q_Q(QPlainTextEdit);
723 viewport->update();
724 emit q->updateRequest(viewport->rect(), 0);
725}
726
728 : tabChangesFocus(false), showCursorOnInitialShow(false), backgroundVisible(false),
729 centerOnScroll(false), inDrag(false), clickCausedFocus(false), placeholderVisible(true),
730 pageUpDownLastCursorYIsValid(false)
731{
732}
733
735{
736 Q_Q(QPlainTextEdit);
738
742 control->setDocument(doc);
743
744 control->setPalette(q->palette());
745
749 [q](){q->updateMicroFocus(); });
767 QObject::connect(control, &QWidgetTextControl::textChanged, q, [q](){q->updateMicroFocus(); });
768
769 // set a null page size initially to avoid any relayouting until the textedit
770 // is shown. relayoutDocument() will take care of setting the page size to the
771 // viewport dimensions later.
772 doc->setTextWidth(-1);
774 doc->setDefaultFont(q->font());
775
776
777 if (!txt.isEmpty())
779
780 hbar->setSingleStep(20);
781 vbar->setSingleStep(1);
782
783 viewport->setBackgroundRole(QPalette::Base);
784 q->setAcceptDrops(true);
785 q->setFocusPolicy(Qt::StrongFocus);
786 q->setAttribute(Qt::WA_KeyCompression);
787 q->setAttribute(Qt::WA_InputMethodEnabled);
788 q->setInputMethodHints(Qt::ImhMultiLine);
789
790#ifndef QT_NO_CURSOR
791 viewport->setCursor(Qt::IBeamCursor);
792#endif
793}
794
796{
797 Q_Q(QPlainTextEdit);
798
799 // We normally only repaint the part of view that contains text in the
800 // document that has changed (in _q_repaintContents). But the placeholder
801 // text is not a part of the document, but is drawn on separately. So whenever
802 // we either show or hide the placeholder text, we issue a full update.
803 bool placeholderCurrentyVisible = placeholderVisible;
804
806 && q->document()->isEmpty()
807 && (!q->firstVisibleBlock().isValid() ||
808 q->firstVisibleBlock().layout()->preeditAreaText().isEmpty());
809
810 if (placeholderCurrentyVisible != placeholderVisible)
811 viewport->update();
812}
813
815{
816 Q_Q(QPlainTextEdit);
817 if (!contentsRect.isValid()) {
819 return;
820 }
821 const int xOffset = horizontalOffset();
822 const int yOffset = (int)verticalOffset();
823 const QRect visibleRect(xOffset, yOffset, viewport->width(), viewport->height());
824
825 QRect r = contentsRect.adjusted(-1, -1, 1, 1).intersected(visibleRect).toAlignedRect();
826 if (r.isEmpty())
827 return;
828
829 r.translate(-xOffset, -yOffset);
830 viewport->update(r);
831 emit q->updateRequest(r, 0);
832}
833
835{
836
837 Q_Q(QPlainTextEdit);
838
840 if (moveCursor) {
844 }
845
847
848
849 if (op == QTextCursor::Down) {
850 QRectF visible = QRectF(viewport->rect()).translated(-q->contentOffset());
851 QTextBlock firstVisibleBlock = q->firstVisibleBlock();
852 QTextBlock block = firstVisibleBlock;
853 QRectF br = q->blockBoundingRect(block);
854 qreal h = 0;
855 int atEnd = false;
856 while (h + br.height() <= visible.bottom()) {
857 if (!block.next().isValid()) {
858 atEnd = true;
859 lastY = visible.bottom(); // set cursor to last line
860 break;
861 }
862 h += br.height();
863 block = block.next();
864 br = q->blockBoundingRect(block);
865 }
866
867 if (!atEnd) {
868 int line = 0;
869 qreal diff = visible.bottom() - h;
870 int lineCount = block.layout()->lineCount();
871 while (line < lineCount - 1) {
872 if (block.layout()->lineAt(line).naturalTextRect().bottom() > diff) {
873 // the first line that did not completely fit the screen
874 break;
875 }
876 ++line;
877 }
878 setTopBlock(block.blockNumber(), line);
879 }
880
881 if (moveCursor) {
882 // move using movePosition to keep the cursor's x
883 lastY += verticalOffset();
884 bool moved = false;
885 do {
886 moved = cursor.movePosition(op, moveMode);
887 } while (moved && control->cursorRect(cursor).top() < lastY);
888 }
889
890 } else if (op == QTextCursor::Up) {
891
892 QRectF visible = QRectF(viewport->rect()).translated(-q->contentOffset());
893 visible.translate(0, -visible.height()); // previous page
894 QTextBlock block = q->firstVisibleBlock();
895 qreal h = 0;
896 while (h >= visible.top()) {
897 if (!block.previous().isValid()) {
898 if (control->topBlock == 0 && topLine == 0) {
899 lastY = 0; // set cursor to first line
900 }
901 break;
902 }
903 block = block.previous();
904 QRectF br = q->blockBoundingRect(block);
905 h -= br.height();
906 }
907
908 int line = 0;
909 if (block.isValid()) {
910 qreal diff = visible.top() - h;
911 int lineCount = block.layout()->lineCount();
912 while (line < lineCount) {
913 if (block.layout()->lineAt(line).naturalTextRect().top() >= diff)
914 break;
915 ++line;
916 }
917 if (line == lineCount) {
918 if (block.next().isValid() && block.next() != q->firstVisibleBlock()) {
919 block = block.next();
920 line = 0;
921 } else {
922 --line;
923 }
924 }
925 }
926 setTopBlock(block.blockNumber(), line);
927
928 if (moveCursor) {
929 cursor.setVisualNavigation(true);
930 // move using movePosition to keep the cursor's x
931 lastY += verticalOffset();
932 bool moved = false;
933 do {
934 moved = cursor.movePosition(op, moveMode);
935 } while (moved && control->cursorRect(cursor).top() > lastY);
936 }
937 }
938
939 if (moveCursor) {
942 }
943}
944
945#if QT_CONFIG(scrollbar)
946
948{
949 Q_Q(QPlainTextEdit);
951 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
952 Q_ASSERT(documentLayout);
953 bool documentSizeChangedBlocked = documentLayout->priv()->blockDocumentSizeChanged;
954 documentLayout->priv()->blockDocumentSizeChanged = true;
955 qreal margin = doc->documentMargin();
956
957 int vmax = 0;
958
959 int vSliderLength = 0;
960 if (!centerOnScroll && q->isVisible()) {
961 QTextBlock block = doc->lastBlock();
962 const qreal visible = viewport->rect().height() - margin - 1;
963 qreal y = 0;
964 int visibleFromBottom = 0;
965
966 while (block.isValid()) {
967 if (!block.isVisible()) {
968 block = block.previous();
969 continue;
970 }
971 y += documentLayout->blockBoundingRect(block).height();
972
973 QTextLayout *layout = block.layout();
974 int layoutLineCount = layout->lineCount();
975 if (y > visible) {
976 int lineNumber = 0;
977 while (lineNumber < layoutLineCount) {
978 QTextLine line = layout->lineAt(lineNumber);
979 const QRectF lr = line.naturalTextRect();
980 if (lr.top() >= y - visible)
981 break;
982 ++lineNumber;
983 }
984 if (lineNumber < layoutLineCount)
985 visibleFromBottom += (layoutLineCount - lineNumber);
986 break;
987
988 }
989 visibleFromBottom += layoutLineCount;
990 block = block.previous();
991 }
992 vmax = qMax(0, doc->lineCount() - visibleFromBottom);
993 vSliderLength = visibleFromBottom;
994
995 } else {
996 vmax = qMax(0, doc->lineCount() - 1);
997 int lineSpacing = q->fontMetrics().lineSpacing();
998 vSliderLength = lineSpacing != 0 ? viewport->height() / lineSpacing : 0;
999 }
1000
1001 QSizeF documentSize = documentLayout->documentSize();
1002 vbar->setRange(0, qMax(0, vmax));
1003 vbar->setPageStep(vSliderLength);
1004 int visualTopLine = vmax;
1005 QTextBlock firstVisibleBlock = q->firstVisibleBlock();
1006 if (firstVisibleBlock.isValid())
1007 visualTopLine = firstVisibleBlock.firstLineNumber() + topLine;
1008
1009 vbar->setValue(visualTopLine);
1010
1011 hbar->setRange(0, (int)documentSize.width() - viewport->width());
1012 hbar->setPageStep(viewport->width());
1013 documentLayout->priv()->blockDocumentSizeChanged = documentSizeChangedBlocked;
1014 setTopLine(vbar->value());
1015}
1016
1017#endif
1018
1019
1021{
1022}
1023
1228 : QAbstractScrollArea(*new QPlainTextEditPrivate, parent)
1229{
1230 Q_D(QPlainTextEdit);
1231 d->init();
1232}
1233
1238 : QAbstractScrollArea(dd, parent)
1239{
1240 Q_D(QPlainTextEdit);
1241 d->init();
1242}
1243
1249 : QAbstractScrollArea(*new QPlainTextEditPrivate, parent)
1250{
1251 Q_D(QPlainTextEdit);
1252 d->init(text);
1253}
1254
1255
1260{
1261 Q_D(QPlainTextEdit);
1262 if (d->documentLayoutPtr) {
1263 if (d->documentLayoutPtr->priv()->mainViewPrivate == d)
1264 d->documentLayoutPtr->priv()->mainViewPrivate = nullptr;
1265 }
1266}
1267
1281{
1282 Q_D(QPlainTextEdit);
1283 QPlainTextDocumentLayout *documentLayout = nullptr;
1284
1285 if (!document) {
1286 document = new QTextDocument(d->control);
1287 documentLayout = new QPlainTextDocumentLayout(document);
1288 document->setDocumentLayout(documentLayout);
1289 } else {
1290 documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document->documentLayout());
1291 if (Q_UNLIKELY(!documentLayout)) {
1292 qWarning("QPlainTextEdit::setDocument: Document set does not support QPlainTextDocumentLayout");
1293 return;
1294 }
1295 }
1296 d->control->setDocument(document);
1297 if (!documentLayout->priv()->mainViewPrivate)
1298 documentLayout->priv()->mainViewPrivate = d;
1299 d->documentLayoutPtr = documentLayout;
1300 d->updateDefaultTextOption();
1301 d->relayoutDocument();
1302 d->_q_adjustScrollbars();
1303}
1304
1311{
1312 Q_D(const QPlainTextEdit);
1313 return d->control->document();
1314}
1315
1330{
1331 Q_D(QPlainTextEdit);
1332 if (d->placeholderText != placeholderText) {
1333 d->placeholderText = placeholderText;
1334 d->_q_updatePlaceholderVisibility();
1335 }
1336}
1337
1339{
1340 Q_D(const QPlainTextEdit);
1341 return d->placeholderText;
1342}
1343
1348{
1350}
1351
1359{
1360 Q_D(QPlainTextEdit);
1361 d->control->setTextCursor(cursor);
1362}
1363
1370{
1371 Q_D(const QPlainTextEdit);
1372 return d->control->textCursor();
1373}
1374
1382{
1383 Q_D(const QPlainTextEdit);
1384 int cursorPos = d->control->hitTest(pos + QPointF(d->horizontalOffset(),
1385 d->verticalOffset()),
1386 Qt::ExactHit);
1387 if (cursorPos < 0)
1388 return QString();
1389
1391 QTextDocumentPrivate::FragmentIterator it = pieceTable->find(cursorPos);
1392 QTextCharFormat fmt = pieceTable->formatCollection()->charFormat(it->format);
1393 return fmt.anchorHref();
1394}
1395
1405{
1406 Q_D(QPlainTextEdit);
1407 d->control->undo();
1408}
1409
1411{
1412 Q_D(QPlainTextEdit);
1413 d->control->redo();
1414}
1415
1427#ifndef QT_NO_CLIPBOARD
1438{
1439 Q_D(QPlainTextEdit);
1440 d->control->cut();
1441}
1442
1450{
1451 Q_D(QPlainTextEdit);
1452 d->control->copy();
1453}
1454
1470{
1471 Q_D(QPlainTextEdit);
1472 d->control->paste();
1473}
1474#endif
1475
1489{
1490 Q_D(QPlainTextEdit);
1491 // clears and sets empty content
1492 d->control->topBlock = d->topLine = d->topLineFracture = 0;
1493 d->control->clear();
1494}
1495
1496
1503{
1504 Q_D(QPlainTextEdit);
1505 d->control->selectAll();
1506}
1507
1511{
1512 Q_D(QPlainTextEdit);
1513
1514 switch (e->type()) {
1515#ifndef QT_NO_CONTEXTMENU
1517 if (static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) {
1519 const QPoint cursorPos = cursorRect().center();
1520 QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos));
1521 ce.setAccepted(e->isAccepted());
1522 const bool result = QAbstractScrollArea::event(&ce);
1523 e->setAccepted(ce.isAccepted());
1524 return result;
1525 }
1526 break;
1527#endif // QT_NO_CONTEXTMENU
1529 case QEvent::ToolTip:
1530 d->sendControlEvent(e);
1531 break;
1532#ifdef QT_KEYPAD_NAVIGATION
1533 case QEvent::EnterEditFocus:
1534 case QEvent::LeaveEditFocus:
1535 if (QApplicationPrivate::keypadNavigationEnabled())
1536 d->sendControlEvent(e);
1537 break;
1538#endif
1539#ifndef QT_NO_GESTURES
1540 case QEvent::Gesture:
1541 if (auto *g = static_cast<QGestureEvent *>(e)->gesture(Qt::PanGesture)) {
1542 QPanGesture *panGesture = static_cast<QPanGesture *>(g);
1543 QScrollBar *hBar = horizontalScrollBar();
1544 QScrollBar *vBar = verticalScrollBar();
1545 if (panGesture->state() == Qt::GestureStarted)
1546 d->originalOffsetY = vBar->value();
1547 QPointF offset = panGesture->offset();
1548 if (!offset.isNull()) {
1550 offset.rx() *= -1;
1551 // QPlainTextEdit scrolls by lines only in vertical direction
1552 QFontMetrics fm(document()->defaultFont());
1553 int lineHeight = fm.height();
1554 int newX = hBar->value() - panGesture->delta().x();
1555 int newY = d->originalOffsetY - offset.y()/lineHeight;
1556 hBar->setValue(newX);
1557 vBar->setValue(newY);
1558 }
1559 }
1560 return true;
1561#endif // QT_NO_GESTURES
1562 default:
1563 break;
1564 }
1565 return QAbstractScrollArea::event(e);
1566}
1567
1572{
1573 Q_D(QPlainTextEdit);
1574 if (e->timerId() == d->autoScrollTimer.timerId()) {
1575 QRect visible = d->viewport->rect();
1576 QPoint pos;
1577 if (d->inDrag) {
1578 pos = d->autoScrollDragPos;
1579 visible.adjust(qMin(visible.width()/3,20), qMin(visible.height()/3,20),
1580 -qMin(visible.width()/3,20), -qMin(visible.height()/3,20));
1581 } else {
1582 const QPoint globalPos = QCursor::pos();
1583 pos = d->viewport->mapFromGlobal(globalPos);
1584 QMouseEvent ev(QEvent::MouseMove, pos, d->viewport->mapTo(d->viewport->topLevelWidget(), pos), globalPos,
1586 mouseMoveEvent(&ev);
1587 }
1588 int deltaY = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height();
1589 int deltaX = qMax(pos.x() - visible.left(), visible.right() - pos.x()) - visible.width();
1590 int delta = qMax(deltaX, deltaY);
1591 if (delta >= 0) {
1592 if (delta < 7)
1593 delta = 7;
1594 int timeout = 4900 / (delta * delta);
1595 d->autoScrollTimer.start(timeout, this);
1596
1597 if (deltaY > 0)
1598 d->vbar->triggerAction(pos.y() < visible.center().y() ?
1601 if (deltaX > 0)
1602 d->hbar->triggerAction(pos.x() < visible.center().x() ?
1605 }
1606 }
1607#ifdef QT_KEYPAD_NAVIGATION
1608 else if (e->timerId() == d->deleteAllTimer.timerId()) {
1609 d->deleteAllTimer.stop();
1610 clear();
1611 }
1612#endif
1613}
1614
1632{
1633 Q_D(QPlainTextEdit);
1634 d->control->setPlainText(text);
1635}
1636
1648{
1649 Q_D(QPlainTextEdit);
1650
1651#ifdef QT_KEYPAD_NAVIGATION
1652 switch (e->key()) {
1653 case Qt::Key_Select:
1654 if (QApplicationPrivate::keypadNavigationEnabled()) {
1655 if (!(d->control->textInteractionFlags() & Qt::LinksAccessibleByKeyboard))
1656 setEditFocus(!hasEditFocus());
1657 else {
1658 if (!hasEditFocus())
1659 setEditFocus(true);
1660 else {
1661 QTextCursor cursor = d->control->textCursor();
1662 QTextCharFormat charFmt = cursor.charFormat();
1663 if (!cursor.hasSelection() || charFmt.anchorHref().isEmpty()) {
1664 setEditFocus(false);
1665 }
1666 }
1667 }
1668 }
1669 break;
1670 case Qt::Key_Back:
1671 case Qt::Key_No:
1672 if (!QApplicationPrivate::keypadNavigationEnabled()
1673 || (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus())) {
1674 e->ignore();
1675 return;
1676 }
1677 break;
1678 default:
1679 if (QApplicationPrivate::keypadNavigationEnabled()) {
1680 if (!hasEditFocus() && !(e->modifiers() & Qt::ControlModifier)) {
1681 if (e->text()[0].isPrint()) {
1682 setEditFocus(true);
1683 clear();
1684 } else {
1685 e->ignore();
1686 return;
1687 }
1688 }
1689 }
1690 break;
1691 }
1692#endif
1693
1694#ifndef QT_NO_SHORTCUT
1695
1696 Qt::TextInteractionFlags tif = d->control->textInteractionFlags();
1697
1700 e->accept();
1702 return;
1703 } else if (e ==QKeySequence::SelectNextPage) {
1704 e->accept();
1706 return;
1707 }
1708 }
1711 e->accept();
1713 return;
1714 } else if (e == QKeySequence::MoveToNextPage) {
1715 e->accept();
1717 return;
1718 }
1719 }
1720
1721 if (!(tif & Qt::TextEditable)) {
1722 switch (e->key()) {
1723 case Qt::Key_Space:
1724 e->accept();
1725 if (e->modifiers() & Qt::ShiftModifier)
1726 d->vbar->triggerAction(QAbstractSlider::SliderPageStepSub);
1727 else
1728 d->vbar->triggerAction(QAbstractSlider::SliderPageStepAdd);
1729 break;
1730 default:
1731 d->sendControlEvent(e);
1732 if (!e->isAccepted() && e->modifiers() == Qt::NoModifier) {
1733 if (e->key() == Qt::Key_Home) {
1734 d->vbar->triggerAction(QAbstractSlider::SliderToMinimum);
1735 e->accept();
1736 } else if (e->key() == Qt::Key_End) {
1737 d->vbar->triggerAction(QAbstractSlider::SliderToMaximum);
1738 e->accept();
1739 }
1740 }
1741 if (!e->isAccepted()) {
1742 QAbstractScrollArea::keyPressEvent(e);
1743 }
1744 }
1745 return;
1746 }
1747#endif // QT_NO_SHORTCUT
1748
1749 d->sendControlEvent(e);
1750#ifdef QT_KEYPAD_NAVIGATION
1751 if (!e->isAccepted()) {
1752 switch (e->key()) {
1753 case Qt::Key_Up:
1754 case Qt::Key_Down:
1755 if (QApplicationPrivate::keypadNavigationEnabled()) {
1756 // Cursor position didn't change, so we want to leave
1757 // these keys to change focus.
1758 e->ignore();
1759 return;
1760 }
1761 break;
1762 case Qt::Key_Left:
1763 case Qt::Key_Right:
1764 if (QApplicationPrivate::keypadNavigationEnabled()
1765 && QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
1766 // Same as for Key_Up and Key_Down.
1767 e->ignore();
1768 return;
1769 }
1770 break;
1771 case Qt::Key_Back:
1772 if (!e->isAutoRepeat()) {
1773 if (QApplicationPrivate::keypadNavigationEnabled()) {
1774 if (document()->isEmpty()) {
1775 setEditFocus(false);
1776 e->accept();
1777 } else if (!d->deleteAllTimer.isActive()) {
1778 e->accept();
1779 d->deleteAllTimer.start(750, this);
1780 }
1781 } else {
1782 e->ignore();
1783 return;
1784 }
1785 }
1786 break;
1787 default: break;
1788 }
1789 }
1790#endif
1791}
1792
1796{
1797 Q_D(QPlainTextEdit);
1798 if (!isReadOnly())
1799 d->handleSoftwareInputPanel();
1800
1801#ifdef QT_KEYPAD_NAVIGATION
1802 if (QApplicationPrivate::keypadNavigationEnabled()) {
1803 if (!e->isAutoRepeat() && e->key() == Qt::Key_Back
1804 && d->deleteAllTimer.isActive()) {
1805 d->deleteAllTimer.stop();
1806 QTextCursor cursor = d->control->textCursor();
1807 QTextBlockFormat blockFmt = cursor.blockFormat();
1808
1809 QTextList *list = cursor.currentList();
1810 if (list && cursor.atBlockStart()) {
1811 list->remove(cursor.block());
1812 } else if (cursor.atBlockStart() && blockFmt.indent() > 0) {
1813 blockFmt.setIndent(blockFmt.indent() - 1);
1814 cursor.setBlockFormat(blockFmt);
1815 } else {
1816 cursor.deletePreviousChar();
1817 }
1819 }
1820 }
1821#else
1823#endif
1824}
1825
1834{
1835 Q_UNUSED(type);
1836 Q_UNUSED(name);
1837 return QVariant();
1838}
1839
1843{
1844 Q_D(QPlainTextEdit);
1845 if (e->oldSize().width() != e->size().width())
1846 d->relayoutDocument();
1847 d->_q_adjustScrollbars();
1848}
1849
1851{
1852 QTextDocument *doc = control->document();
1853 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
1854 Q_ASSERT(documentLayout);
1855 documentLayoutPtr = documentLayout;
1856
1857 int width = viewport->width();
1858
1859 if (documentLayout->priv()->mainViewPrivate == nullptr
1860 || documentLayout->priv()->mainViewPrivate == this
1861 || width > documentLayout->textWidth()) {
1862 documentLayout->priv()->mainViewPrivate = this;
1863 documentLayout->setTextWidth(width);
1864 }
1865}
1866
1867static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, const QRectF &gradientRect = QRectF())
1868{
1869 p->save();
1870 if (brush.style() >= Qt::LinearGradientPattern && brush.style() <= Qt::ConicalGradientPattern) {
1871 if (!gradientRect.isNull()) {
1872 QTransform m = QTransform::fromTranslate(gradientRect.left(), gradientRect.top());
1873 m.scale(gradientRect.width(), gradientRect.height());
1874 brush.setTransform(m);
1875 const_cast<QGradient *>(brush.gradient())->setCoordinateMode(QGradient::LogicalMode);
1876 }
1877 } else {
1878 p->setBrushOrigin(rect.topLeft());
1879 }
1880 p->fillRect(rect, brush);
1881 p->restore();
1882}
1883
1884
1885
1889{
1890 Q_D(QPlainTextEdit);
1892 Q_ASSERT(qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout()));
1893
1895
1896 QRect er = e->rect();
1897 QRect viewportRect = viewport()->rect();
1898
1899 bool editable = !isReadOnly();
1900
1901 QTextBlock block = firstVisibleBlock();
1902 qreal maximumWidth = document()->documentLayout()->documentSize().width();
1903
1904 // Set a brush origin so that the WaveUnderline knows where the wave started
1906
1907 // keep right margin clean from full-width selection
1908 int maxX = offset.x() + qMax((qreal)viewportRect.width(), maximumWidth)
1910 er.setRight(qMin(er.right(), maxX));
1911 painter.setClipRect(er);
1912
1913 if (d->placeholderVisible) {
1914 const QColor col = d->control->palette().placeholderText().color();
1915 painter.setPen(col);
1916 painter.setClipRect(e->rect());
1917 const int margin = int(document()->documentMargin());
1918 QRectF textRect = viewportRect.adjusted(margin, margin, 0, 0);
1920 }
1921
1923 painter.setPen(context.palette.text().color());
1924
1925 while (block.isValid()) {
1926
1928 QTextLayout *layout = block.layout();
1929
1930 if (!block.isVisible()) {
1931 offset.ry() += r.height();
1932 block = block.next();
1933 continue;
1934 }
1935
1936 if (r.bottom() >= er.top() && r.top() <= er.bottom()) {
1937
1938 QTextBlockFormat blockFormat = block.blockFormat();
1939
1940 QBrush bg = blockFormat.background();
1941 if (bg != Qt::NoBrush) {
1942 QRectF contentsRect = r;
1943 contentsRect.setWidth(qMax(r.width(), maximumWidth));
1944 fillBackground(&painter, contentsRect, bg);
1945 }
1946
1948 int blpos = block.position();
1949 int bllen = block.length();
1950 for (int i = 0; i < context.selections.size(); ++i) {
1951 const QAbstractTextDocumentLayout::Selection &range = context.selections.at(i);
1952 const int selStart = range.cursor.selectionStart() - blpos;
1953 const int selEnd = range.cursor.selectionEnd() - blpos;
1954 if (selStart < bllen && selEnd > 0
1955 && selEnd > selStart) {
1957 o.start = selStart;
1958 o.length = selEnd - selStart;
1959 o.format = range.format;
1960 selections.append(o);
1961 } else if (!range.cursor.hasSelection() && range.format.hasProperty(QTextFormat::FullWidthSelection)
1962 && block.contains(range.cursor.position())) {
1963 // for full width selections we don't require an actual selection, just
1964 // a position to specify the line. that's more convenience in usage.
1966 QTextLine l = layout->lineForTextPosition(range.cursor.position() - blpos);
1967 o.start = l.textStart();
1968 o.length = l.textLength();
1969 if (o.start + o.length == bllen - 1)
1970 ++o.length; // include newline
1971 o.format = range.format;
1972 selections.append(o);
1973 }
1974 }
1975
1976 bool drawCursor = ((editable || (textInteractionFlags() & Qt::TextSelectableByKeyboard))
1977 && context.cursorPosition >= blpos
1978 && context.cursorPosition < blpos + bllen);
1979
1980 bool drawCursorAsBlock = drawCursor && overwriteMode() ;
1981
1982 if (drawCursorAsBlock) {
1983 if (context.cursorPosition == blpos + bllen - 1) {
1984 drawCursorAsBlock = false;
1985 } else {
1987 o.start = context.cursorPosition - blpos;
1988 o.length = 1;
1989 o.format.setForeground(palette().base());
1990 o.format.setBackground(palette().text());
1991 selections.append(o);
1992 }
1993 }
1994
1995 layout->draw(&painter, offset, selections, er);
1996
1997 if ((drawCursor && !drawCursorAsBlock)
1998 || (editable && context.cursorPosition < -1
1999 && !layout->preeditAreaText().isEmpty())) {
2000 int cpos = context.cursorPosition;
2001 if (cpos < -1)
2002 cpos = layout->preeditAreaPosition() - (cpos + 2);
2003 else
2004 cpos -= blpos;
2005 layout->drawCursor(&painter, offset, cpos, cursorWidth());
2006 }
2007 }
2008
2009 offset.ry() += r.height();
2010 if (offset.y() > viewportRect.height())
2011 break;
2012 block = block.next();
2013 }
2014
2015 if (backgroundVisible() && !block.isValid() && offset.y() <= er.bottom()
2016 && (centerOnScroll() || verticalScrollBar()->maximum() == verticalScrollBar()->minimum())) {
2017 painter.fillRect(QRect(QPoint((int)er.left(), (int)offset.y()), er.bottomRight()), palette().window());
2018 }
2019}
2020
2021
2023{
2024 QTextDocument *doc = control->document();
2025
2027 QTextOption::WrapMode oldWrapMode = opt.wrapMode();
2028
2030 opt.setWrapMode(QTextOption::NoWrap);
2031 else
2032 opt.setWrapMode(wordWrap);
2033
2034 if (opt.wrapMode() != oldWrapMode)
2036}
2037
2038
2042{
2043 Q_D(QPlainTextEdit);
2044#ifdef QT_KEYPAD_NAVIGATION
2045 if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus())
2046 setEditFocus(true);
2047#endif
2048 d->sendControlEvent(e);
2049}
2050
2054{
2055 Q_D(QPlainTextEdit);
2056 d->inDrag = false; // paranoia
2057 const QPoint pos = e->position().toPoint();
2058 d->sendControlEvent(e);
2059 if (!(e->buttons() & Qt::LeftButton))
2060 return;
2061 if (e->source() == Qt::MouseEventNotSynthesized) {
2062 const QRect visible = d->viewport->rect();
2063 if (visible.contains(pos))
2064 d->autoScrollTimer.stop();
2065 else if (!d->autoScrollTimer.isActive())
2066 d->autoScrollTimer.start(100, this);
2067 }
2068}
2069
2073{
2074 Q_D(QPlainTextEdit);
2075 d->sendControlEvent(e);
2076 if (e->source() == Qt::MouseEventNotSynthesized && d->autoScrollTimer.isActive()) {
2077 d->autoScrollTimer.stop();
2078 d->ensureCursorVisible();
2079 }
2080
2081 if (!isReadOnly() && rect().contains(e->position().toPoint()))
2082 d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
2083 d->clickCausedFocus = 0;
2084}
2085
2089{
2090 Q_D(QPlainTextEdit);
2091 d->sendControlEvent(e);
2092}
2093
2097{
2098 Q_D(const QPlainTextEdit);
2099 if (!d->tabChangesFocus && d->control->textInteractionFlags() & Qt::TextEditable)
2100 return false;
2101 return QAbstractScrollArea::focusNextPrevChild(next);
2102}
2103
2104#ifndef QT_NO_CONTEXTMENU
2121{
2122 Q_D(QPlainTextEdit);
2123 d->sendControlEvent(e);
2124}
2125#endif // QT_NO_CONTEXTMENU
2126
2127#if QT_CONFIG(draganddrop)
2130void QPlainTextEdit::dragEnterEvent(QDragEnterEvent *e)
2131{
2132 Q_D(QPlainTextEdit);
2133 d->inDrag = true;
2134 d->sendControlEvent(e);
2135}
2136
2139void QPlainTextEdit::dragLeaveEvent(QDragLeaveEvent *e)
2140{
2141 Q_D(QPlainTextEdit);
2142 d->inDrag = false;
2143 d->autoScrollTimer.stop();
2144 d->sendControlEvent(e);
2145}
2146
2149void QPlainTextEdit::dragMoveEvent(QDragMoveEvent *e)
2150{
2151 Q_D(QPlainTextEdit);
2152 d->autoScrollDragPos = e->position().toPoint();
2153 if (!d->autoScrollTimer.isActive())
2154 d->autoScrollTimer.start(100, this);
2155 d->sendControlEvent(e);
2156}
2157
2160void QPlainTextEdit::dropEvent(QDropEvent *e)
2161{
2162 Q_D(QPlainTextEdit);
2163 d->inDrag = false;
2164 d->autoScrollTimer.stop();
2165 d->sendControlEvent(e);
2166}
2167
2168#endif // QT_CONFIG(draganddrop)
2169
2173{
2174 Q_D(QPlainTextEdit);
2175#ifdef QT_KEYPAD_NAVIGATION
2176 if (d->control->textInteractionFlags() & Qt::TextEditable
2177 && QApplicationPrivate::keypadNavigationEnabled()
2178 && !hasEditFocus()) {
2179 setEditFocus(true);
2180 selectAll(); // so text is replaced rather than appended to
2181 }
2182#endif
2183 d->sendControlEvent(e);
2184 const bool emptyEvent = e->preeditString().isEmpty() && e->commitString().isEmpty()
2185 && e->attributes().isEmpty();
2186 if (emptyEvent)
2187 return;
2189}
2190
2193void QPlainTextEdit::scrollContentsBy(int dx, int /*dy*/)
2194{
2195 Q_D(QPlainTextEdit);
2196 d->setTopLine(d->vbar->value(), dx);
2197}
2198
2202{
2204}
2205
2209{
2210 Q_D(const QPlainTextEdit);
2211 switch (query) {
2212 case Qt::ImEnabled:
2213 return isEnabled();
2214 case Qt::ImHints:
2217 case Qt::ImReadOnly:
2218 return isReadOnly();
2219 default:
2220 break;
2221 }
2222
2223 const QPointF offset = contentOffset();
2224 switch (argument.userType()) {
2225 case QMetaType::QRectF:
2226 argument = argument.toRectF().translated(-offset);
2227 break;
2228 case QMetaType::QPointF:
2229 argument = argument.toPointF() - offset;
2230 break;
2231 case QMetaType::QRect:
2232 argument = argument.toRect().translated(-offset.toPoint());
2233 break;
2234 case QMetaType::QPoint:
2235 argument = argument.toPoint() - offset;
2236 break;
2237 default:
2238 break;
2239 }
2240
2241 const QVariant v = d->control->inputMethodQuery(query, argument);
2242 switch (v.userType()) {
2243 case QMetaType::QRectF:
2244 return v.toRectF().translated(offset);
2245 case QMetaType::QPointF:
2246 return v.toPointF() + offset;
2247 case QMetaType::QRect:
2248 return v.toRect().translated(offset.toPoint());
2249 case QMetaType::QPoint:
2250 return v.toPoint() + offset.toPoint();
2251 default:
2252 break;
2253 }
2254 return v;
2255}
2256
2260{
2261 Q_D(QPlainTextEdit);
2262 if (e->reason() == Qt::MouseFocusReason) {
2263 d->clickCausedFocus = 1;
2264 }
2265 QAbstractScrollArea::focusInEvent(e);
2266 d->sendControlEvent(e);
2267}
2268
2272{
2273 Q_D(QPlainTextEdit);
2274 QAbstractScrollArea::focusOutEvent(e);
2275 d->sendControlEvent(e);
2276}
2277
2281{
2282 Q_D(QPlainTextEdit);
2283 if (d->showCursorOnInitialShow) {
2284 d->showCursorOnInitialShow = false;
2286 }
2287 d->_q_adjustScrollbars();
2288}
2289
2293{
2294 Q_D(QPlainTextEdit);
2295 QAbstractScrollArea::changeEvent(e);
2296
2297 switch (e->type()) {
2299 case QEvent::FontChange:
2300 d->control->document()->setDefaultFont(font());
2301 break;
2303 d->control->setPalette(palette());
2304 if (!isActiveWindow())
2305 d->autoScrollTimer.stop();
2306 break;
2308 e->setAccepted(isEnabled());
2309 d->control->setPalette(palette());
2310 d->sendControlEvent(e);
2311 break;
2313 d->control->setPalette(palette());
2314 break;
2316 d->sendControlEvent(e);
2317 break;
2318 default:
2319 break;
2320 }
2321}
2322
2325#if QT_CONFIG(wheelevent)
2326void QPlainTextEdit::wheelEvent(QWheelEvent *e)
2327{
2328 Q_D(QPlainTextEdit);
2329 if (!(d->control->textInteractionFlags() & Qt::TextEditable)) {
2330 if (e->modifiers() & Qt::ControlModifier) {
2331 float delta = e->angleDelta().y() / 120.f;
2332 zoomInF(delta);
2333 return;
2334 }
2335 }
2336 QAbstractScrollArea::wheelEvent(e);
2337 updateMicroFocus();
2338}
2339#endif
2340
2349{
2350 zoomInF(range);
2351}
2352
2361{
2362 zoomInF(-range);
2363}
2364
2369{
2370 if (range == 0.f)
2371 return;
2372 QFont f = font();
2373 const float newSize = f.pointSizeF() + range;
2374 if (newSize <= 0)
2375 return;
2376 f.setPointSizeF(newSize);
2377 setFont(f);
2378}
2379
2380#ifndef QT_NO_CONTEXTMENU
2391{
2392 Q_D(QPlainTextEdit);
2393 return d->control->createStandardContextMenu(QPointF(), this);
2394}
2395
2407{
2408 Q_D(QPlainTextEdit);
2409 return d->control->createStandardContextMenu(position, this);
2410}
2411#endif // QT_NO_CONTEXTMENU
2412
2417{
2418 Q_D(const QPlainTextEdit);
2419 return d->control->cursorForPosition(d->mapToContents(pos));
2420}
2421
2427{
2428 Q_D(const QPlainTextEdit);
2429 if (cursor.isNull())
2430 return QRect();
2431
2432 QRect r = d->control->cursorRect(cursor).toRect();
2433 r.translate(-d->horizontalOffset(),-(int)d->verticalOffset());
2434 return r;
2435}
2436
2442{
2443 Q_D(const QPlainTextEdit);
2444 QRect r = d->control->cursorRect().toRect();
2445 r.translate(-d->horizontalOffset(),-(int)d->verticalOffset());
2446 return r;
2447}
2448
2449
2465{
2466 Q_D(const QPlainTextEdit);
2467 return d->control->overwriteMode();
2468}
2469
2471{
2472 Q_D(QPlainTextEdit);
2473 d->control->setOverwriteMode(overwrite);
2474}
2475
2491{
2492 Q_D(const QPlainTextEdit);
2493 return d->control->document()->defaultTextOption().tabStopDistance();
2494}
2495
2497{
2498 Q_D(QPlainTextEdit);
2499 QTextOption opt = d->control->document()->defaultTextOption();
2500 if (opt.tabStopDistance() == distance || distance < 0)
2501 return;
2502 opt.setTabStopDistance(distance);
2503 d->control->document()->setDefaultTextOption(opt);
2504}
2505
2506
2513{
2514 Q_D(const QPlainTextEdit);
2515 return d->control->cursorWidth();
2516}
2517
2519{
2520 Q_D(QPlainTextEdit);
2521 d->control->setCursorWidth(width);
2522}
2523
2524
2525
2535{
2536 Q_D(QPlainTextEdit);
2537 d->control->setExtraSelections(selections);
2538}
2539
2546{
2547 Q_D(const QPlainTextEdit);
2548 return d->control->extraSelections();
2549}
2550
2562{
2563 Q_D(const QPlainTextEdit);
2564 return d->control->QWidgetTextControl::createMimeDataFromSelection();
2565}
2566
2574{
2575 Q_D(const QPlainTextEdit);
2576 return d->control->QWidgetTextControl::canInsertFromMimeData(source);
2577}
2578
2587{
2588 Q_D(QPlainTextEdit);
2589 d->control->QWidgetTextControl::insertFromMimeData(source);
2590}
2591
2603{
2604 Q_D(const QPlainTextEdit);
2605 return !(d->control->textInteractionFlags() & Qt::TextEditable);
2606}
2607
2609{
2610 Q_D(QPlainTextEdit);
2611 Qt::TextInteractionFlags flags = Qt::NoTextInteraction;
2612 if (ro) {
2614 } else {
2616 }
2617 d->control->setTextInteractionFlags(flags);
2621}
2622
2636{
2637 Q_D(QPlainTextEdit);
2638 d->control->setTextInteractionFlags(flags);
2639}
2640
2641Qt::TextInteractionFlags QPlainTextEdit::textInteractionFlags() const
2642{
2643 Q_D(const QPlainTextEdit);
2644 return d->control->textInteractionFlags();
2645}
2646
2656{
2657 Q_D(QPlainTextEdit);
2658 d->control->mergeCurrentCharFormat(modifier);
2659}
2660
2668{
2669 Q_D(QPlainTextEdit);
2670 d->control->setCurrentCharFormat(format);
2671}
2672
2677{
2678 Q_D(const QPlainTextEdit);
2679 return d->control->currentCharFormat();
2680}
2681
2682
2683
2693{
2694 Q_D(QPlainTextEdit);
2695 d->control->insertPlainText(text);
2696}
2697
2698
2709{
2710 Q_D(QPlainTextEdit);
2711 d->control->moveCursor(operation, mode);
2712}
2713
2718{
2719 Q_D(const QPlainTextEdit);
2720 return d->control->canPaste();
2721}
2722
2730#ifndef QT_NO_PRINTER
2732{
2733 Q_D(const QPlainTextEdit);
2734 d->control->print(printer);
2735}
2736#endif
2737
2748{
2749 Q_D(const QPlainTextEdit);
2750 return d->tabChangesFocus;
2751}
2752
2754{
2755 Q_D(QPlainTextEdit);
2756 d->tabChangesFocus = b;
2757}
2758
2777{
2778 Q_D(const QPlainTextEdit);
2779 return d->lineWrap;
2780}
2781
2783{
2784 Q_D(QPlainTextEdit);
2785 if (d->lineWrap == wrap)
2786 return;
2787 d->lineWrap = wrap;
2788 d->updateDefaultTextOption();
2789 d->relayoutDocument();
2790 d->_q_adjustScrollbars();
2792}
2793
2804{
2805 Q_D(const QPlainTextEdit);
2806 return d->wordWrap;
2807}
2808
2810{
2811 Q_D(QPlainTextEdit);
2812 if (mode == d->wordWrap)
2813 return;
2814 d->wordWrap = mode;
2815 d->updateDefaultTextOption();
2816}
2817
2833{
2834 Q_D(const QPlainTextEdit);
2835 return d->backgroundVisible;
2836}
2837
2839{
2840 Q_D(QPlainTextEdit);
2841 if (visible == d->backgroundVisible)
2842 return;
2843 d->backgroundVisible = visible;
2844 d->updateViewport();
2845}
2846
2865{
2866 Q_D(const QPlainTextEdit);
2867 return d->centerOnScroll;
2868}
2869
2871{
2872 Q_D(QPlainTextEdit);
2873 if (enabled == d->centerOnScroll)
2874 return;
2875 d->centerOnScroll = enabled;
2876 d->_q_adjustScrollbars();
2877}
2878
2879
2880
2886bool QPlainTextEdit::find(const QString &exp, QTextDocument::FindFlags options)
2887{
2888 Q_D(QPlainTextEdit);
2889 return d->control->find(exp, options);
2890}
2891
2905#if QT_CONFIG(regularexpression)
2906bool QPlainTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
2907{
2908 Q_D(QPlainTextEdit);
2909 return d->control->find(exp, options);
2910}
2911#endif
2912
2983{
2984 Q_Q(QPlainTextEdit);
2985
2986 QTextDocument *document = control->document();
2987 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document->documentLayout());
2988 Q_ASSERT(documentLayout);
2989
2990 int maximumBlockCount = document->maximumBlockCount();
2991 if (maximumBlockCount)
2992 document->setMaximumBlockCount(0);
2993
2994 const bool atBottom = q->isVisible()
2995 && (control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
2996 <= viewport->rect().bottom());
2997
2998 if (!q->isVisible())
3000
3001 bool documentSizeChangedBlocked = documentLayout->priv()->blockDocumentSizeChanged;
3002 documentLayout->priv()->blockDocumentSizeChanged = true;
3003
3004 switch (format) {
3005 case Qt::RichText:
3007 break;
3008 case Qt::PlainText:
3010 break;
3011 default:
3013 break;
3014 }
3015
3016 if (maximumBlockCount > 0) {
3017 if (document->blockCount() > maximumBlockCount) {
3018 bool blockUpdate = false;
3019 if (control->topBlock) {
3020 control->topBlock--;
3021 blockUpdate = true;
3022 emit q->updateRequest(viewport->rect(), 0);
3023 }
3024
3025 bool updatesBlocked = documentLayout->priv()->blockUpdate;
3026 documentLayout->priv()->blockUpdate = blockUpdate;
3027 QTextCursor cursor(document);
3029 cursor.removeSelectedText();
3030 documentLayout->priv()->blockUpdate = updatesBlocked;
3031 }
3032 document->setMaximumBlockCount(maximumBlockCount);
3033 }
3034
3035 documentLayout->priv()->blockDocumentSizeChanged = documentSizeChangedBlocked;
3037
3038
3039 if (atBottom) {
3040 const bool needScroll = !centerOnScroll
3041 || control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
3042 > viewport->rect().bottom();
3043 if (needScroll)
3044 vbar->setValue(vbar->maximum());
3045 }
3046}
3047
3048
3056{
3057 Q_D(QPlainTextEdit);
3058 d->append(text, Qt::PlainText);
3059}
3060
3068{
3069 Q_D(QPlainTextEdit);
3070 d->append(html, Qt::RichText);
3071}
3072
3074{
3075 Q_Q(QPlainTextEdit);
3076 QRect visible = viewport->rect();
3077 QRect cr = q->cursorRect();
3078 if (cr.top() < visible.top() || cr.bottom() > visible.bottom()) {
3080 }
3081
3082 const bool rtl = q->isRightToLeft();
3083 if (cr.left() < visible.left() || cr.right() > visible.right()) {
3084 int x = cr.center().x() + horizontalOffset() - visible.width()/2;
3085 hbar->setValue(rtl ? hbar->maximum() - x : x);
3086 }
3087}
3088
3096{
3097 Q_D(QPlainTextEdit);
3098 d->ensureCursorVisible(d->centerOnScroll);
3099}
3100
3101
3107{
3108 Q_D(QPlainTextEdit);
3109 d->ensureVisible(textCursor().position(), true, true);
3110}
3111
3118{
3119 Q_D(const QPlainTextEdit);
3120 return d->control->firstVisibleBlock();
3121}
3122
3137{
3138 Q_D(const QPlainTextEdit);
3139 return QPointF(-d->horizontalOffset(), -d->verticalOffset());
3140}
3141
3142
3150{
3151 Q_D(const QPlainTextEdit);
3152 return d->control->blockBoundingRect(block);
3153}
3154
3161{
3162 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout());
3163 Q_ASSERT(documentLayout);
3164 return documentLayout->blockBoundingRect(block);
3165}
3166
3174{
3175 return document()->blockCount();
3176}
3177
3182{
3183 Q_D(const QPlainTextEdit);
3184 return d->control->getPaintContext(d->viewport);
3185}
3186
3228
3229#include "moc_qplaintextedit.cpp"
3230#include "moc_qplaintextedit_p.cpp"
int value
the slider's current value
SliderAction
\value SliderNoAction \value SliderSingleStepAdd \value SliderSingleStepSub \value SliderPageStepAdd ...
void actionTriggered(int action)
This signal is emitted when the slider action action is triggered.
void documentSizeChanged(const QSizeF &newSize)
This signal is emitted when the size of the document layout changes to newSize.
QTextDocument * document() const
Returns the text document that this layout is operating on.
void updateBlock(const QTextBlock &block)
void setPaintDevice(QPaintDevice *device)
Sets the paint device used for rendering the document's layout to the given device.
void update(const QRectF &=QRectF(0., 0., 1000000000., 1000000000.))
This signal is emitted when the rectangle rect has been updated.
virtual QSizeF documentSize() const =0
Returns the total size of the document's layout.
\inmodule QtGui
Definition qbrush.h:30
\inmodule QtCore
Definition qchar.h:48
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
The QContextMenuEvent class contains parameters that describe a context menu event.
Definition qevent.h:593
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
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
Definition qcoreevent.h:45
virtual void setAccepted(bool accepted)
Definition qcoreevent.h:302
@ EnabledChange
Definition qcoreevent.h:134
@ LayoutDirectionChange
Definition qcoreevent.h:124
@ ReadOnlyChange
Definition qcoreevent.h:145
@ ShortcutOverride
Definition qcoreevent.h:158
@ FontChange
Definition qcoreevent.h:133
@ MouseMove
Definition qcoreevent.h:63
@ ActivationChange
Definition qcoreevent.h:135
@ PaletteChange
Definition qcoreevent.h:94
@ ApplicationFontChange
Definition qcoreevent.h:91
@ ContextMenu
Definition qcoreevent.h:119
bool isAccepted() const
Definition qcoreevent.h:303
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:469
\reentrant \inmodule QtGui
int height() const
Returns the height of the font.
\reentrant
Definition qfont.h:20
The QGestureEvent class provides the description of triggered gestures.
Definition qgesture.h:244
Qt::GestureState state
the current state of the gesture
Definition qgesture.h:33
\inmodule QtGui
Definition qbrush.h:135
@ LogicalMode
Definition qbrush.h:154
static QInputMethod * inputMethod()
returns the input method.
static Qt::KeyboardModifiers keyboardModifiers()
Returns the current state of the modifier keys on the keyboard.
static bool isRightToLeft()
Returns true if the application's layout direction is Qt::RightToLeft; otherwise returns false.
The QInputMethodEvent class provides parameters for input method events.
Definition qevent.h:624
void update(Qt::InputMethodQueries queries)
Called by the input item to inform the platform input methods when there has been state changes in ed...
The QKeyEvent class describes a key event.
Definition qevent.h:423
bool isEmpty() const override
\reimp
Definition qlayout.cpp:422
Definition qlist.h:74
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:787
void append(parameter_type t)
Definition qlist.h:441
The QMenu class provides a menu widget for use in menu bars, context menus, and other popup menus.
Definition qmenu.h:26
\inmodule QtCore
Definition qmimedata.h:16
\inmodule QtGui
Definition qevent.h:195
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:298
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
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
\inmodule QtGui
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:485
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
void setClipRect(const QRectF &, Qt::ClipOperation op=Qt::ReplaceClip)
Enables clipping, and sets the clip region to the given rectangle using the given clip operation.
void setPen(const QColor &color)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void setBrushOrigin(int x, int y)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qpainter.h:698
void drawText(const QPointF &p, const QString &s)
Draws the given text with the currently defined text direction, beginning at the given position.
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
The QPanGesture class describes a panning gesture made by the user.\inmodule QtWidgets.
Definition qgesture.h:73
QPointF delta
the offset from the previous input position to the current input
Definition qgesture.h:79
QPointF offset
the total offset from the first input position to the current input position
Definition qgesture.h:78
QPlainTextEditPrivate * mainViewPrivate
void layoutBlock(const QTextBlock &block)
qreal blockWidth(const QTextBlock &block)
The QPlainTextDocumentLayout class implements a plain text layout for QTextDocument.
void ensureBlockLayout(const QTextBlock &block) const
Ensures that block has a valid layout.
~QPlainTextDocumentLayout()
Destructs a plain text document layout.
QRectF frameBoundingRect(QTextFrame *) const override
\reimp
void documentChanged(int from, int, int charsAdded) override
\reimp
void requestUpdate()
Requests a complete update on all views.
int hitTest(const QPointF &, Qt::HitTestAccuracy) const override
\reimp
QRectF blockBoundingRect(const QTextBlock &block) const override
\reimp
void draw(QPainter *, const PaintContext &) override
\reimp
QSizeF documentSize() const override
\reimp
int pageCount() const override
\reimp
QPlainTextDocumentLayout(QTextDocument *document)
Constructs a plain text document layout for the text document.
int cursorWidth
This property specifies the width of the cursor in pixels.
QPlainTextEdit * textEdit
QRectF cursorRect(const QTextCursor &cursor) const
void insertFromMimeData(const QMimeData *source) override
bool canInsertFromMimeData(const QMimeData *source) const override
QTextBlock firstVisibleBlock() const
QRectF blockBoundingRect(const QTextBlock &block) const override
int hitTest(const QPointF &point, Qt::HitTestAccuracy=Qt::FuzzyHit) const override
QString anchorAt(const QPointF &pos) const override
QPlainTextEditControl(QPlainTextEdit *parent)
QMimeData * createMimeDataFromSelection() const override
void _q_repaintContents(const QRectF &contentsRect)
void _q_verticalScrollbarActionTriggered(int action)
void pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode, bool moveCursor=true)
QPlainTextEditControl * control
void append(const QString &text, Qt::TextFormat format=Qt::AutoText)
void ensureVisible(int position, bool center, bool forceCenter=false)
QTextOption::WrapMode wordWrap
void init(const QString &txt=QString())
QPlainTextEdit::LineWrapMode lineWrap
void setTopLine(int visualTopLine, int dx=0)
QPointer< QPlainTextDocumentLayout > documentLayoutPtr
void ensureCursorVisible(bool center=false)
void setTopBlock(int newTopBlock, int newTopLine, int dx=0)
The QPlainTextEdit class provides a widget that is used to edit and display plain text.
void cut()
Copies the selected text to the clipboard and deletes it from the text edit.
virtual void mouseMoveEvent(QMouseEvent *e) override
\reimp
virtual ~QPlainTextEdit()
Destructor.
virtual bool focusNextPrevChild(bool next) override
\reimp
QTextBlock firstVisibleBlock() const
Returns the first visible block.
int cursorWidth
This property specifies the width of the cursor in pixels.
QRectF blockBoundingGeometry(const QTextBlock &block) const
Returns the bounding rectangle of the text block in content coordinates.
void zoomOut(int range=1)
Zooms out on the text by making the base font size range points smaller and recalculating all font si...
virtual QVariant loadResource(int type, const QUrl &name)
Loads the resource specified by the given type and name.
void setTabStopDistance(qreal distance)
void copy()
Copies any selected text to the clipboard.
virtual void paintEvent(QPaintEvent *e) override
\reimp
void setCursorWidth(int width)
virtual bool canInsertFromMimeData(const QMimeData *source) const
This function returns true if the contents of the MIME data object, specified by source,...
QTextOption::WrapMode wordWrapMode() const
the mode QPlainTextEdit will use when wrapping text by words
void setLineWrapMode(LineWrapMode mode)
void setExtraSelections(const QList< QTextEdit::ExtraSelection > &selections)
This function allows temporarily marking certain regions in the document with a given color,...
QMenu * createStandardContextMenu()
This function creates the standard context menu which is shown when the user clicks on the text edit ...
void setPlainText(const QString &text)
Changes the text of the text edit to the string text.
QTextCharFormat currentCharFormat() const
Returns the char format that is used when inserting new text.
virtual void mouseDoubleClickEvent(QMouseEvent *e) override
\reimp
void setTabChangesFocus(bool b)
QTextCursor cursorForPosition(const QPoint &pos) const
returns a QTextCursor at position pos (in viewport coordinates).
void setBackgroundVisible(bool visible)
virtual void keyReleaseEvent(QKeyEvent *e) override
\reimp
void centerCursor()
Scrolls the document in order to center the cursor vertically.
virtual void resizeEvent(QResizeEvent *e) override
\reimp
void copyAvailable(bool b)
This signal is emitted when text is selected or de-selected in the text edit.
void paste()
Pastes the text from the clipboard into the text edit at the current cursor position.
virtual void keyPressEvent(QKeyEvent *e) override
\reimp
void selectionChanged()
This signal is emitted whenever the selection changes.
void undoAvailable(bool b)
This signal is emitted whenever undo operations become available (available is true) or unavailable (...
void ensureCursorVisible()
Ensures that the cursor is visible by scrolling the text edit if necessary.
void insertPlainText(const QString &text)
Convenience slot that inserts text at the current cursor position.
void blockCountChanged(int newBlockCount)
This signal is emitted whenever the block count changes.
void clear()
Deletes all the text in the text edit.
void zoomIn(int range=1)
\reimp
void redo()
Redoes the last operation.
virtual void timerEvent(QTimerEvent *e) override
void redoAvailable(bool b)
This signal is emitted whenever redo operations become available (available is true) or unavailable (...
bool backgroundVisible
whether the palette background is visible outside the document area
virtual void doSetTextCursor(const QTextCursor &cursor)
QAbstractTextDocumentLayout::PaintContext getPaintContext() const
Returns the paint context for the viewport(), useful only when reimplementing paintEvent().
void setCenterOnScroll(bool enabled)
LineWrapMode
\value NoWrap \value WidgetWidth
void setOverwriteMode(bool overwrite)
virtual void showEvent(QShowEvent *) override
\reimp
QTextDocument * document() const
Returns a pointer to the underlying document.
QPointF contentOffset() const
Returns the content's origin in viewport coordinates.
virtual void changeEvent(QEvent *e) override
\reimp
QTextCursor textCursor() const
Returns a copy of the QTextCursor that represents the currently visible cursor.
virtual void inputMethodEvent(QInputMethodEvent *) override
\reimp
void print(QPagedPaintDevice *printer) const
Convenience function to print the text edit's document to the given printer.
virtual void mousePressEvent(QMouseEvent *e) override
\reimp
void setCurrentCharFormat(const QTextCharFormat &format)
Sets the char format that is be used when inserting new text to format by calling QTextCursor::setCha...
QList< QTextEdit::ExtraSelection > extraSelections() const
Returns previously set extra selections.
void textChanged()
This signal is emitted whenever the document's content changes; for example, when text is inserted or...
virtual void focusOutEvent(QFocusEvent *e) override
\reimp
virtual QMimeData * createMimeDataFromSelection() const
This function returns a new MIME data object to represent the contents of the text edit's current sel...
void selectAll()
Selects all text.
virtual bool event(QEvent *e) override
QVariant inputMethodQuery(Qt::InputMethodQuery property) const override
\reimp
bool canPaste() const
Returns whether text can be pasted from the clipboard into the textedit.
QRectF blockBoundingRect(const QTextBlock &block) const
Returns the bounding rectangle of the text block in the block's own coordinates.
bool find(const QString &exp, QTextDocument::FindFlags options=QTextDocument::FindFlags())
Finds the next occurrence of the string, exp, using the given options.
void setPlaceholderText(const QString &placeholderText)
virtual void contextMenuEvent(QContextMenuEvent *e) override
Shows the standard context menu created with createStandardContextMenu().
Qt::TextInteractionFlags textInteractionFlags
Specifies how the label should interact with user input if it displays text.
QString placeholderText
the editor placeholder text
LineWrapMode lineWrapMode
the line wrap mode
void appendPlainText(const QString &text)
Appends a new paragraph with text to the end of the text edit.
void undo()
Undoes the last operation.
QRect cursorRect() const
returns a rectangle (in viewport coordinates) that includes the cursor of the text edit.
QString anchorAt(const QPoint &pos) const
Returns the reference of the anchor at position pos, or an empty string if no anchor exists at that p...
void setDocument(QTextDocument *document)
Makes document the new document of the text editor.
int blockCount
the number of text blocks in the document.
void modificationChanged(bool)
This signal is emitted whenever the content of the document changes in a way that affects the modific...
void setTextInteractionFlags(Qt::TextInteractionFlags flags)
void zoomInF(float range)
virtual void scrollContentsBy(int dx, int dy) override
\reimp
void setTextCursor(const QTextCursor &cursor)
Sets the visible cursor.
void mergeCurrentCharFormat(const QTextCharFormat &modifier)
Merges the properties specified in modifier into the current character format by calling QTextCursor:...
void setReadOnly(bool ro)
virtual void insertFromMimeData(const QMimeData *source)
This function inserts the contents of the MIME data object, specified by source, into the text edit a...
void appendHtml(const QString &html)
Appends a new paragraph with html to the end of the text edit.
virtual void focusInEvent(QFocusEvent *e) override
\reimp
qreal tabStopDistance
the tab stop distance in pixels
QPlainTextEdit(QWidget *parent=nullptr)
Constructs an empty QPlainTextEdit with parent parent.
virtual void mouseReleaseEvent(QMouseEvent *e) override
\reimp
bool centerOnScroll
whether the cursor should be centered on screen
void moveCursor(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode=QTextCursor::MoveAnchor)
Moves the cursor by performing the given operation.
void setWordWrapMode(QTextOption::WrapMode policy)
bool isReadOnly() const
bool tabChangesFocus
whether \uicontrol Tab changes focus or is accepted as input
bool overwriteMode
whether text entered by the user will overwrite existing text
\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
constexpr qreal & rx() noexcept
Returns a reference to the x coordinate of this point.
Definition qpoint.h:353
\inmodule QtCore\reentrant
Definition qpoint.h:23
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:127
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:132
\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
QRect toAlignedRect() const noexcept
Definition qrect.cpp:2330
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 QRectF translated(qreal dx, qreal dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
Definition qrect.h:748
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 void setWidth(qreal w) noexcept
Sets the width of the rectangle to the given finite width.
Definition qrect.h:804
constexpr QPointF topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:510
constexpr QPointF bottomRight() const noexcept
Returns the position of the rectangle's bottom-right corner.
Definition qrect.h:511
constexpr void adjust(qreal x1, qreal y1, qreal x2, qreal y2) noexcept
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition qrect.h:791
constexpr void translate(qreal dx, qreal dy) noexcept
Moves the rectangle dx along the x-axis and dy along the y-axis, relative to the current position.
Definition qrect.h:724
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
QRectF intersected(const QRectF &other) const noexcept
Definition qrect.h:833
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr void adjust(int x1, int y1, int x2, int y2) noexcept
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition qrect.h:372
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:181
constexpr void setRight(int pos) noexcept
Sets the right edge of the rectangle to the given x coordinate.
Definition qrect.h:196
constexpr QRect adjusted(int x1, int y1, int x2, int y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:369
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:175
bool contains(const QRect &r, bool proper=false) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:851
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:172
constexpr void translate(int dx, int dy) noexcept
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position.
Definition qrect.h:244
constexpr QPoint bottomRight() const noexcept
Returns the position of the rectangle's bottom-right corner.
Definition qrect.h:223
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
constexpr QPoint center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:232
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:178
\inmodule QtCore \reentrant
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:547
The QScrollBar widget provides a vertical or horizontal scroll bar.
Definition qscrollbar.h:20
The QShowEvent class provides an event that is sent when a widget is shown.
Definition qevent.h:577
\inmodule QtCore
Definition qsize.h:207
constexpr qreal width() const noexcept
Returns the width.
Definition qsize.h:321
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
void setIndent(int indent)
Sets the paragraph's indentation.
int indent() const
Returns the paragraph's indent.
\reentrant
int length() const
Returns the length of the block in characters.
int lineCount() const
void setLineCount(int count)
QTextBlockFormat blockFormat() const
Returns the QTextBlockFormat that describes block-specific properties.
int blockNumber() const
const QTextDocument * document() const
Returns the text document this text block belongs to, or \nullptr if the text block does not belong t...
bool isValid() const
Returns true if this text block is valid; otherwise returns false.
bool contains(int position) const
Returns true if the given position is located within the text block; 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...
bool isVisible() const
int firstLineNumber() const
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.
QTextCharFormat charFormat() const
Returns the QTextCharFormat that describes the block's character format.
QTextBlock previous() const
Returns the text block in the document before this block, or an empty text block if this is the first...
void clearLayout()
QString anchorHref() const
Returns the text format's hypertext link, or an empty string if none has been set.
QFont font() const
Returns the font for this character format.
\reentrant \inmodule QtGui
Definition qtextcursor.h:30
MoveMode
\value MoveAnchor Moves the anchor to the same position as the cursor itself.
Definition qtextcursor.h:47
MoveOperation
\value NoMove Keep the cursor where it is
Definition qtextcursor.h:61
int position() const
Returns the absolute position of the cursor within the document.
QTextFormatCollection * formatCollection()
static const QTextDocumentPrivate * get(const QTextDocument *document)
FragmentMap::ConstIterator FragmentIterator
FragmentIterator find(int pos) const
\reentrant \inmodule QtGui
QTextBlock findBlockByLineNumber(int blockNumber) const
int lineCount() const
void setDefaultTextOption(const QTextOption &option)
QTextBlock findBlockByNumber(int blockNumber) const
int blockCount
the number of text blocks in the document.
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.
QTextBlock findBlock(int pos) const
Returns the text block that contains the {pos}-th character.
QTextBlock firstBlock() const
void setDocumentLayout(QAbstractTextDocumentLayout *layout)
Sets the document to use the given layout.
QTextBlock lastBlock() const
void setTextWidth(qreal width)
QTextCharFormat charFormat(int index) const
QBrush background() const
Returns the brush used to paint the document's background.
\reentrant
Definition qtextobject.h:81
\reentrant
Definition qtextlayout.h:70
QTextLine lineForTextPosition(int pos) const
Returns the line that contains the cursor position specified by pos.
QTextLine createLine()
Returns a new text line to be laid out if there is text to be inserted into the layout; otherwise ret...
void beginLayout()
Begins the layout process.
int lineCount() const
Returns the number of lines in this text layout.
QTextLine lineAt(int i) const
Returns the {i}-th line of text in this text layout.
void setTextOption(const QTextOption &option)
Sets the text option structure that controls the layout process to the given option.
void endLayout()
Ends the layout process.
void clearLayout()
QRectF boundingRect() const
The smallest rectangle that contains all the lines in the layout.
\reentrant
int textStart() const
Returns the start of the line from the beginning of the string passed to the QTextLayout.
QRectF naturalTextRect() const
Returns the rectangle covered by the line.
qreal naturalTextWidth() const
Returns the width of the line that is occupied by text.
@ CursorBetweenCharacters
@ CursorOnCharacter
int textLength() const
Returns the length of the text in the line.
\reentrant
Definition qtextlist.h:18
\reentrant
Definition qtextoption.h:18
@ AddSpaceForLineAndParagraphSeparators
Definition qtextoption.h:73
WrapMode
This enum describes how text is wrapped in a document.
Definition qtextoption.h:60
\inmodule QtCore
Definition qcoreevent.h:359
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
static QTransform fromTranslate(qreal dx, qreal dy)
Creates a matrix which corresponds to a translation of dx along the x axis and dy along the y axis.
\inmodule QtCore
Definition qurl.h:94
\inmodule QtCore
Definition qvariant.h:64
void setPlainText(const QString &text)
QTextCursor textCursor() const
void redoAvailable(bool b)
void appendPlainText(const QString &text)
void cursorPositionChanged()
virtual QMimeData * createMimeDataFromSelection() const
void setTextCursor(const QTextCursor &cursor, bool selectionClipboard=false)
void undoAvailable(bool b)
void setAcceptRichText(bool accept)
void modificationChanged(bool m)
void updateRequest(const QRectF &rect=QRectF())
void setDocument(QTextDocument *document)
void append(const QString &text)
void documentSizeChanged(const QSizeF &)
virtual void insertFromMimeData(const QMimeData *source)
virtual bool canInsertFromMimeData(const QMimeData *source) const
void setPalette(const QPalette &pal)
QTextDocument * document() const
void appendHtml(const QString &html)
void blockCountChanged(int newBlockCount)
void copyAvailable(bool b)
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
virtual void keyReleaseEvent(QKeyEvent *event)
This event handler, for event event, can be reimplemented in a subclass to receive key release events...
Definition qwidget.cpp:9687
virtual QVariant inputMethodQuery(Qt::InputMethodQuery) const
This method is only relevant for input widgets.
Definition qwidget.cpp:9959
QString text
QCursor cursor
double e
QSet< QString >::iterator it
rect
[4]
QStyleOptionButton opt
QRect textRect
short next
Definition keywords.cpp:445
QVector3D vmax(const QVector3D &a, const QVector3D &b)
Combined button and popup list for selecting options.
InputMethodQuery
@ ImAnchorRectangle
@ ImInputItemClipRectangle
@ ImReadOnly
@ ImCursorRectangle
@ ImHints
@ ImEnabled
@ AlignTop
Definition qnamespace.h:152
@ NavigationModeKeypadDirectional
@ LeftButton
Definition qnamespace.h:57
@ TextSelectableByMouse
@ TextEditable
@ TextEditorInteraction
@ LinksAccessibleByKeyboard
@ TextSelectableByKeyboard
@ NoTextInteraction
@ WA_KeyCompression
Definition qnamespace.h:299
@ WA_InputMethodEnabled
Definition qnamespace.h:294
TextFormat
@ RichText
@ PlainText
@ GestureStarted
@ StrongFocus
Definition qnamespace.h:109
@ TextWordWrap
Definition qnamespace.h:173
@ MouseEventNotSynthesized
@ IBeamCursor
@ ImhMultiLine
HitTestAccuracy
Definition qnamespace.h:202
@ ExactHit
Definition qnamespace.h:202
@ Key_Select
@ Key_Right
Definition qnamespace.h:674
@ Key_Space
Definition qnamespace.h:512
@ Key_Left
Definition qnamespace.h:672
@ Key_Up
Definition qnamespace.h:673
@ Key_Down
Definition qnamespace.h:675
@ Key_Back
Definition qnamespace.h:841
@ Key_Home
Definition qnamespace.h:670
@ Key_End
Definition qnamespace.h:671
@ Key_No
@ ShiftModifier
@ ControlModifier
@ NoModifier
@ LinearGradientPattern
@ NoBrush
@ ConicalGradientPattern
@ PanGesture
@ MouseFocusReason
Definition brush.cpp:5
static void * context
#define Q_UNLIKELY(x)
#define qWarning
Definition qlogging.h:162
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 & qMax(const T &a, const T &b)
Definition qminmax.h:42
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum mode
const GLfloat * m
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLboolean r
[2]
GLbitfield GLuint64 timeout
[4]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLsizei range
GLsizei GLsizei GLfloat distance
GLint GLsizei width
GLenum type
GLbitfield flags
GLenum GLuint GLintptr offset
GLboolean GLboolean g
GLuint name
GLint GLsizei GLsizei GLenum format
GLint y
GLfloat GLfloat GLfloat GLfloat maxX
GLfloat GLfloat GLfloat GLfloat h
GLsizei GLsizei GLchar * source
struct _cl_event * event
GLenum query
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLuint GLenum option
static QT_BEGIN_NAMESPACE bool shouldEnableInputMethod(QPlainTextEdit *control)
static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, const QRectF &gradientRect=QRectF())
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QT_BEGIN_NAMESPACE QAsn1Element wrap(quint8 type, const QAsn1Element &child)
static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, const QPointF &origin, const QRectF &gradientRect=QRectF())
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:92
QVideoFrameFormat::PixelFormat fmt
#define enabled
const char property[13]
Definition qwizard.cpp:101
QList< int > list
[14]
QVBoxLayout * layout
Text files * txt
QGraphicsWidget * textEdit
view viewport() -> scroll(dx, dy, deviceRect)
app setAttribute(Qt::AA_DontShowIconsInMenus)
QPainter painter(this)
[7]
QDBusArgument argument
\variable QAbstractTextDocumentLayout::PaintContext::cursorPosition
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent