Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
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
78
79
80
115
116
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
415 : QWidgetTextControl(parent), textEdit(parent),
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
464 ed->insertFromMimeData(source);
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
494
495
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)
729 , showCursorOnInitialShow(false)
730 , backgroundVisible(false)
731 , centerOnScroll(false)
732 , inDrag(false)
733 , clickCausedFocus(false)
734 , pageUpDownLastCursorYIsValid(false)
735 , placeholderTextShown(false)
736{
737}
738
740{
741 Q_Q(QPlainTextEdit);
743
747 control->setDocument(doc);
748
749 control->setPalette(q->palette());
750
754 [q](){q->updateMicroFocus(); });
772 QObject::connect(control, &QWidgetTextControl::textChanged, q, [q](){q->updateMicroFocus(); });
773
774 // set a null page size initially to avoid any relayouting until the textedit
775 // is shown. relayoutDocument() will take care of setting the page size to the
776 // viewport dimensions later.
777 doc->setTextWidth(-1);
779 doc->setDefaultFont(q->font());
780
781
782 if (!txt.isEmpty())
784
785 hbar->setSingleStep(20);
786 vbar->setSingleStep(1);
787
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);
794
795#ifndef QT_NO_CURSOR
796 viewport->setCursor(Qt::IBeamCursor);
797#endif
798}
799
801{
802 // We normally only repaint the part of view that contains text in the
803 // document that has changed (in repaintContents). But the placeholder
804 // text is not a part of the document, but is drawn on separately. So whenever
805 // we either show or hide the placeholder text, we issue a full update.
807 viewport->update();
809 }
810}
811
813{
814 Q_Q(QPlainTextEdit);
815 if (!contentsRect.isValid()) {
817 return;
818 }
819 const int xOffset = horizontalOffset();
820 const int yOffset = (int)verticalOffset();
821 const QRect visibleRect(xOffset, yOffset, viewport->width(), viewport->height());
822
823 QRect r = contentsRect.adjusted(-1, -1, 1, 1).intersected(visibleRect).toAlignedRect();
824 if (r.isEmpty())
825 return;
826
827 r.translate(-xOffset, -yOffset);
828 viewport->update(r);
829 emit q->updateRequest(r, 0);
830}
831
833{
834
835 Q_Q(QPlainTextEdit);
836
838 if (moveCursor) {
842 }
843
845
846
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);
852 qreal h = 0;
853 int atEnd = false;
854 while (h + br.height() <= visible.bottom()) {
855 if (!block.next().isValid()) {
856 atEnd = true;
857 lastY = visible.bottom(); // set cursor to last line
858 break;
859 }
860 h += br.height();
861 block = block.next();
862 br = q->blockBoundingRect(block);
863 }
864
865 if (!atEnd) {
866 int line = 0;
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) {
871 // the first line that did not completely fit the screen
872 break;
873 }
874 ++line;
875 }
876 setTopBlock(block.blockNumber(), line);
877 }
878
879 if (moveCursor) {
880 // move using movePosition to keep the cursor's x
881 lastY += verticalOffset();
882 bool moved = false;
883 do {
884 moved = cursor.movePosition(op, moveMode);
885 } while (moved && control->cursorRect(cursor).top() < lastY);
886 }
887
888 } else if (op == QTextCursor::Up) {
889
890 QRectF visible = QRectF(viewport->rect()).translated(-q->contentOffset());
891 visible.translate(0, -visible.height()); // previous page
892 QTextBlock block = q->firstVisibleBlock();
893 qreal h = 0;
894 while (h >= visible.top()) {
895 if (!block.previous().isValid()) {
896 if (control->topBlock == 0 && topLine == 0) {
897 lastY = 0; // set cursor to first line
898 }
899 break;
900 }
901 block = block.previous();
902 QRectF br = q->blockBoundingRect(block);
903 h -= br.height();
904 }
905
906 int line = 0;
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)
912 break;
913 ++line;
914 }
915 if (line == lineCount) {
916 if (block.next().isValid() && block.next() != q->firstVisibleBlock()) {
917 block = block.next();
918 line = 0;
919 } else {
920 --line;
921 }
922 }
923 }
924 setTopBlock(block.blockNumber(), line);
925
926 if (moveCursor) {
927 cursor.setVisualNavigation(true);
928 // move using movePosition to keep the cursor's x
929 lastY += verticalOffset();
930 bool moved = false;
931 do {
932 moved = cursor.movePosition(op, moveMode);
933 } while (moved && control->cursorRect(cursor).top() > lastY);
934 }
935 }
936
937 if (moveCursor) {
940 }
941}
942
943#if QT_CONFIG(scrollbar)
944
946{
947 Q_Q(QPlainTextEdit);
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();
954
955 int vmax = 0;
956
957 int vSliderLength = 0;
958 if (!centerOnScroll && q->isVisible()) {
959 QTextBlock block = doc->lastBlock();
960 const qreal visible = viewport->rect().height() - margin - 1;
961 qreal y = 0;
962 int visibleFromBottom = 0;
963
964 while (block.isValid()) {
965 if (!block.isVisible()) {
966 block = block.previous();
967 continue;
968 }
969 y += documentLayout->blockBoundingRect(block).height();
970
971 QTextLayout *layout = block.layout();
972 int layoutLineCount = layout->lineCount();
973 if (y > visible) {
974 int lineNumber = 0;
975 while (lineNumber < layoutLineCount) {
976 QTextLine line = layout->lineAt(lineNumber);
977 const QRectF lr = line.naturalTextRect();
978 if (lr.top() >= y - visible)
979 break;
980 ++lineNumber;
981 }
982 if (lineNumber < layoutLineCount)
983 visibleFromBottom += (layoutLineCount - lineNumber);
984 break;
985
986 }
987 visibleFromBottom += layoutLineCount;
988 block = block.previous();
989 }
990 vmax = qMax(0, doc->lineCount() - visibleFromBottom);
991 vSliderLength = visibleFromBottom;
992
993 } else {
994 vmax = qMax(0, doc->lineCount() - 1);
995 int lineSpacing = q->fontMetrics().lineSpacing();
996 vSliderLength = lineSpacing != 0 ? viewport->height() / lineSpacing : 0;
997 }
998
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;
1006
1007 vbar->setValue(visualTopLine);
1008
1009 hbar->setRange(0, (int)documentSize.width() - viewport->width());
1010 hbar->setPageStep(viewport->width());
1011 documentLayout->priv()->blockDocumentSizeChanged = documentSizeChangedBlocked;
1012 setTopLine(vbar->value());
1013}
1014
1015#endif
1016
1017
1021
1226 : QAbstractScrollArea(*new QPlainTextEditPrivate, parent)
1227{
1228 Q_D(QPlainTextEdit);
1229 d->init();
1230}
1231
1236 : QAbstractScrollArea(dd, parent)
1237{
1238 Q_D(QPlainTextEdit);
1239 d->init();
1240}
1241
1247 : QAbstractScrollArea(*new QPlainTextEditPrivate, parent)
1248{
1249 Q_D(QPlainTextEdit);
1250 d->init(text);
1251}
1252
1253
1258{
1259 Q_D(QPlainTextEdit);
1260 if (d->documentLayoutPtr) {
1261 if (d->documentLayoutPtr->priv()->mainViewPrivate == d)
1262 d->documentLayoutPtr->priv()->mainViewPrivate = nullptr;
1263 }
1264}
1265
1279{
1280 Q_D(QPlainTextEdit);
1281 QPlainTextDocumentLayout *documentLayout = nullptr;
1282
1283 if (!document) {
1284 document = new QTextDocument(d->control);
1285 documentLayout = new QPlainTextDocumentLayout(document);
1286 document->setDocumentLayout(documentLayout);
1287 } else {
1288 documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document->documentLayout());
1289 if (Q_UNLIKELY(!documentLayout)) {
1290 qWarning("QPlainTextEdit::setDocument: Document set does not support QPlainTextDocumentLayout");
1291 return;
1292 }
1293 }
1294 d->control->setDocument(document);
1295 if (!documentLayout->priv()->mainViewPrivate)
1296 documentLayout->priv()->mainViewPrivate = d;
1297 d->documentLayoutPtr = documentLayout;
1298 d->updateDefaultTextOption();
1299 d->relayoutDocument();
1300 d->adjustScrollbars();
1301}
1302
1309{
1310 Q_D(const QPlainTextEdit);
1311 return d->control->document();
1312}
1313
1328{
1329 Q_D(QPlainTextEdit);
1330 if (d->placeholderText != placeholderText) {
1331 d->placeholderText = placeholderText;
1332 d->updatePlaceholderVisibility();
1333 }
1334}
1335
1337{
1338 Q_D(const QPlainTextEdit);
1339 return d->placeholderText;
1340}
1341
1349
1357{
1358 Q_D(QPlainTextEdit);
1359 d->control->setTextCursor(cursor);
1360}
1361
1368{
1369 Q_D(const QPlainTextEdit);
1370 return d->control->textCursor();
1371}
1372
1380{
1381 Q_D(const QPlainTextEdit);
1382 int cursorPos = d->control->hitTest(pos + QPointF(d->horizontalOffset(),
1383 d->verticalOffset()),
1384 Qt::ExactHit);
1385 if (cursorPos < 0)
1386 return QString();
1387
1389 QTextDocumentPrivate::FragmentIterator it = pieceTable->find(cursorPos);
1390 QTextCharFormat fmt = pieceTable->formatCollection()->charFormat(it->format);
1391 return fmt.anchorHref();
1392}
1393
1403{
1404 Q_D(QPlainTextEdit);
1405 d->control->undo();
1406}
1407
1409{
1410 Q_D(QPlainTextEdit);
1411 d->control->redo();
1412}
1413
1425#ifndef QT_NO_CLIPBOARD
1436{
1437 Q_D(QPlainTextEdit);
1438 d->control->cut();
1439}
1440
1448{
1449 Q_D(QPlainTextEdit);
1450 d->control->copy();
1451}
1452
1468{
1469 Q_D(QPlainTextEdit);
1470 d->control->paste();
1471}
1472#endif
1473
1487{
1488 Q_D(QPlainTextEdit);
1489 // clears and sets empty content
1490 d->control->topBlock = d->topLine = d->topLineFracture = 0;
1491 d->control->clear();
1492}
1493
1494
1501{
1502 Q_D(QPlainTextEdit);
1503 d->control->selectAll();
1504}
1505
1509{
1510 Q_D(QPlainTextEdit);
1511
1512 switch (e->type()) {
1513#ifndef QT_NO_CONTEXTMENU
1515 if (static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) {
1517 const QPoint cursorPos = cursorRect().center();
1518 QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos));
1519 ce.setAccepted(e->isAccepted());
1520 const bool result = QAbstractScrollArea::event(&ce);
1521 e->setAccepted(ce.isAccepted());
1522 return result;
1523 }
1524 break;
1525#endif // QT_NO_CONTEXTMENU
1527 case QEvent::ToolTip:
1528 d->sendControlEvent(e);
1529 break;
1530#ifdef QT_KEYPAD_NAVIGATION
1531 case QEvent::EnterEditFocus:
1532 case QEvent::LeaveEditFocus:
1533 if (QApplicationPrivate::keypadNavigationEnabled())
1534 d->sendControlEvent(e);
1535 break;
1536#endif
1537#ifndef QT_NO_GESTURES
1538 case QEvent::Gesture:
1539 if (auto *g = static_cast<QGestureEvent *>(e)->gesture(Qt::PanGesture)) {
1540 QPanGesture *panGesture = static_cast<QPanGesture *>(g);
1541 QScrollBar *hBar = horizontalScrollBar();
1542 QScrollBar *vBar = verticalScrollBar();
1543 if (panGesture->state() == Qt::GestureStarted)
1544 d->originalOffsetY = vBar->value();
1545 QPointF offset = panGesture->offset();
1546 if (!offset.isNull()) {
1548 offset.rx() *= -1;
1549 // QPlainTextEdit scrolls by lines only in vertical direction
1550 QFontMetrics fm(document()->defaultFont());
1551 int lineHeight = fm.height();
1552 int newX = hBar->value() - panGesture->delta().x();
1553 int newY = d->originalOffsetY - offset.y()/lineHeight;
1554 hBar->setValue(newX);
1555 vBar->setValue(newY);
1556 }
1557 }
1558 return true;
1559#endif // QT_NO_GESTURES
1562 d->control->setPalette(palette());
1563 break;
1564 default:
1565 break;
1566 }
1567 return QAbstractScrollArea::event(e);
1568}
1569
1574{
1575 Q_D(QPlainTextEdit);
1576 if (e->timerId() == d->autoScrollTimer.timerId()) {
1577 QRect visible = d->viewport->rect();
1578 QPoint pos;
1579 if (d->inDrag) {
1580 pos = d->autoScrollDragPos;
1581 visible.adjust(qMin(visible.width()/3,20), qMin(visible.height()/3,20),
1582 -qMin(visible.width()/3,20), -qMin(visible.height()/3,20));
1583 } else {
1584 const QPoint globalPos = QCursor::pos();
1585 pos = d->viewport->mapFromGlobal(globalPos);
1586 QMouseEvent ev(QEvent::MouseMove, pos, d->viewport->mapTo(d->viewport->topLevelWidget(), pos), globalPos,
1588 mouseMoveEvent(&ev);
1589 }
1590 int deltaY = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height();
1591 int deltaX = qMax(pos.x() - visible.left(), visible.right() - pos.x()) - visible.width();
1592 int delta = qMax(deltaX, deltaY);
1593 if (delta >= 0) {
1594 if (delta < 7)
1595 delta = 7;
1596 int timeout = 4900 / (delta * delta);
1597 d->autoScrollTimer.start(timeout, this);
1598
1599 if (deltaY > 0)
1600 d->vbar->triggerAction(pos.y() < visible.center().y() ?
1603 if (deltaX > 0)
1604 d->hbar->triggerAction(pos.x() < visible.center().x() ?
1607 }
1608 }
1609#ifdef QT_KEYPAD_NAVIGATION
1610 else if (e->timerId() == d->deleteAllTimer.timerId()) {
1611 d->deleteAllTimer.stop();
1612 clear();
1613 }
1614#endif
1615}
1616
1634{
1635 Q_D(QPlainTextEdit);
1636 d->control->setPlainText(text);
1637}
1638
1650{
1651 Q_D(QPlainTextEdit);
1652
1653#ifdef QT_KEYPAD_NAVIGATION
1654 switch (e->key()) {
1655 case Qt::Key_Select:
1656 if (QApplicationPrivate::keypadNavigationEnabled()) {
1657 if (!(d->control->textInteractionFlags() & Qt::LinksAccessibleByKeyboard))
1658 setEditFocus(!hasEditFocus());
1659 else {
1660 if (!hasEditFocus())
1661 setEditFocus(true);
1662 else {
1663 QTextCursor cursor = d->control->textCursor();
1664 QTextCharFormat charFmt = cursor.charFormat();
1665 if (!cursor.hasSelection() || charFmt.anchorHref().isEmpty()) {
1666 setEditFocus(false);
1667 }
1668 }
1669 }
1670 }
1671 break;
1672 case Qt::Key_Back:
1673 case Qt::Key_No:
1674 if (!QApplicationPrivate::keypadNavigationEnabled()
1675 || (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus())) {
1676 e->ignore();
1677 return;
1678 }
1679 break;
1680 default:
1681 if (QApplicationPrivate::keypadNavigationEnabled()) {
1682 if (!hasEditFocus() && !(e->modifiers() & Qt::ControlModifier)) {
1683 if (e->text()[0].isPrint()) {
1684 setEditFocus(true);
1685 clear();
1686 } else {
1687 e->ignore();
1688 return;
1689 }
1690 }
1691 }
1692 break;
1693 }
1694#endif
1695
1696#ifndef QT_NO_SHORTCUT
1697
1698 Qt::TextInteractionFlags tif = d->control->textInteractionFlags();
1699
1702 e->accept();
1704 return;
1705 } else if (e ==QKeySequence::SelectNextPage) {
1706 e->accept();
1708 return;
1709 }
1710 }
1713 e->accept();
1715 return;
1716 } else if (e == QKeySequence::MoveToNextPage) {
1717 e->accept();
1719 return;
1720 }
1721 }
1722
1723 if (!(tif & Qt::TextEditable)) {
1724 switch (e->key()) {
1725 case Qt::Key_Space:
1726 e->accept();
1727 if (e->modifiers() & Qt::ShiftModifier)
1728 d->vbar->triggerAction(QAbstractSlider::SliderPageStepSub);
1729 else
1730 d->vbar->triggerAction(QAbstractSlider::SliderPageStepAdd);
1731 break;
1732 default:
1733 d->sendControlEvent(e);
1734 if (!e->isAccepted() && e->modifiers() == Qt::NoModifier) {
1735 if (e->key() == Qt::Key_Home) {
1736 d->vbar->triggerAction(QAbstractSlider::SliderToMinimum);
1737 e->accept();
1738 } else if (e->key() == Qt::Key_End) {
1739 d->vbar->triggerAction(QAbstractSlider::SliderToMaximum);
1740 e->accept();
1741 }
1742 }
1743 if (!e->isAccepted()) {
1744 QAbstractScrollArea::keyPressEvent(e);
1745 }
1746 }
1747 return;
1748 }
1749#endif // QT_NO_SHORTCUT
1750
1751 d->sendControlEvent(e);
1752#ifdef QT_KEYPAD_NAVIGATION
1753 if (!e->isAccepted()) {
1754 switch (e->key()) {
1755 case Qt::Key_Up:
1756 case Qt::Key_Down:
1757 if (QApplicationPrivate::keypadNavigationEnabled()) {
1758 // Cursor position didn't change, so we want to leave
1759 // these keys to change focus.
1760 e->ignore();
1761 return;
1762 }
1763 break;
1764 case Qt::Key_Left:
1765 case Qt::Key_Right:
1766 if (QApplicationPrivate::keypadNavigationEnabled()
1767 && QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
1768 // Same as for Key_Up and Key_Down.
1769 e->ignore();
1770 return;
1771 }
1772 break;
1773 case Qt::Key_Back:
1774 if (!e->isAutoRepeat()) {
1775 if (QApplicationPrivate::keypadNavigationEnabled()) {
1776 if (document()->isEmpty()) {
1777 setEditFocus(false);
1778 e->accept();
1779 } else if (!d->deleteAllTimer.isActive()) {
1780 e->accept();
1781 d->deleteAllTimer.start(750, this);
1782 }
1783 } else {
1784 e->ignore();
1785 return;
1786 }
1787 }
1788 break;
1789 default: break;
1790 }
1791 }
1792#endif
1793}
1794
1798{
1799 Q_D(QPlainTextEdit);
1800 if (!isReadOnly())
1801 d->handleSoftwareInputPanel();
1802
1803#ifdef QT_KEYPAD_NAVIGATION
1804 if (QApplicationPrivate::keypadNavigationEnabled()) {
1805 if (!e->isAutoRepeat() && e->key() == Qt::Key_Back
1806 && d->deleteAllTimer.isActive()) {
1807 d->deleteAllTimer.stop();
1808 QTextCursor cursor = d->control->textCursor();
1809 QTextBlockFormat blockFmt = cursor.blockFormat();
1810
1811 QTextList *list = cursor.currentList();
1812 if (list && cursor.atBlockStart()) {
1813 list->remove(cursor.block());
1814 } else if (cursor.atBlockStart() && blockFmt.indent() > 0) {
1815 blockFmt.setIndent(blockFmt.indent() - 1);
1816 cursor.setBlockFormat(blockFmt);
1817 } else {
1818 cursor.deletePreviousChar();
1819 }
1821 }
1822 }
1823#else
1825#endif
1826}
1827
1836{
1837 Q_UNUSED(type);
1838 Q_UNUSED(name);
1839 return QVariant();
1840}
1841
1845{
1846 Q_D(QPlainTextEdit);
1847 if (e->oldSize().width() != e->size().width())
1848 d->relayoutDocument();
1849 d->adjustScrollbars();
1850}
1851
1853{
1854 QTextDocument *doc = control->document();
1855 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
1856 Q_ASSERT(documentLayout);
1857 documentLayoutPtr = documentLayout;
1858
1859 int width = viewport->width();
1860
1861 if (documentLayout->priv()->mainViewPrivate == nullptr
1862 || documentLayout->priv()->mainViewPrivate == this
1863 || width > documentLayout->textWidth()) {
1864 documentLayout->priv()->mainViewPrivate = this;
1865 documentLayout->setTextWidth(width);
1866 }
1867}
1868
1869static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, const QRectF &gradientRect = QRectF())
1870{
1871 p->save();
1872 if (brush.style() >= Qt::LinearGradientPattern && brush.style() <= Qt::ConicalGradientPattern) {
1873 if (!gradientRect.isNull()) {
1874 QTransform m = QTransform::fromTranslate(gradientRect.left(), gradientRect.top());
1875 m.scale(gradientRect.width(), gradientRect.height());
1876 brush.setTransform(m);
1877 const_cast<QGradient *>(brush.gradient())->setCoordinateMode(QGradient::LogicalMode);
1878 }
1879 } else {
1880 p->setBrushOrigin(rect.topLeft());
1881 }
1882 p->fillRect(rect, brush);
1883 p->restore();
1884}
1885
1886
1887
1891{
1892 Q_D(QPlainTextEdit);
1894 Q_ASSERT(qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout()));
1895
1897
1898 QRect er = e->rect();
1899 QRect viewportRect = viewport()->rect();
1900
1901 bool editable = !isReadOnly();
1902
1903 QTextBlock block = firstVisibleBlock();
1904 qreal maximumWidth = document()->documentLayout()->documentSize().width();
1905
1906 // Set a brush origin so that the WaveUnderline knows where the wave started
1908
1909 // keep right margin clean from full-width selection
1910 int maxX = offset.x() + qMax((qreal)viewportRect.width(), maximumWidth)
1912 er.setRight(qMin(er.right(), maxX));
1913 painter.setClipRect(er);
1914
1915 if (d->placeHolderTextToBeShown()) {
1916 const QColor col = d->control->palette().placeholderText().color();
1917 painter.setPen(col);
1918 painter.setClipRect(e->rect());
1919 const int margin = int(document()->documentMargin());
1920 QRectF textRect = viewportRect.adjusted(margin, margin, 0, 0);
1922 }
1923
1925 painter.setPen(context.palette.text().color());
1926
1927 while (block.isValid()) {
1928
1930 QTextLayout *layout = block.layout();
1931
1932 if (!block.isVisible()) {
1933 offset.ry() += r.height();
1934 block = block.next();
1935 continue;
1936 }
1937
1938 if (r.bottom() >= er.top() && r.top() <= er.bottom()) {
1939
1940 QTextBlockFormat blockFormat = block.blockFormat();
1941
1942 QBrush bg = blockFormat.background();
1943 if (bg != Qt::NoBrush) {
1944 QRectF contentsRect = r;
1945 contentsRect.setWidth(qMax(r.width(), maximumWidth));
1946 fillBackground(&painter, contentsRect, bg);
1947 }
1948
1949 QList<QTextLayout::FormatRange> selections;
1950 int blpos = block.position();
1951 int bllen = block.length();
1952 for (int i = 0; i < context.selections.size(); ++i) {
1953 const QAbstractTextDocumentLayout::Selection &range = context.selections.at(i);
1954 const int selStart = range.cursor.selectionStart() - blpos;
1955 const int selEnd = range.cursor.selectionEnd() - blpos;
1956 if (selStart < bllen && selEnd > 0
1957 && selEnd > selStart) {
1959 o.start = selStart;
1960 o.length = selEnd - selStart;
1961 o.format = range.format;
1962 selections.append(o);
1963 } else if (!range.cursor.hasSelection() && range.format.hasProperty(QTextFormat::FullWidthSelection)
1964 && block.contains(range.cursor.position())) {
1965 // for full width selections we don't require an actual selection, just
1966 // a position to specify the line. that's more convenience in usage.
1968 QTextLine l = layout->lineForTextPosition(range.cursor.position() - blpos);
1969 o.start = l.textStart();
1970 o.length = l.textLength();
1971 if (o.start + o.length == bllen - 1)
1972 ++o.length; // include newline
1973 o.format = range.format;
1974 selections.append(o);
1975 }
1976 }
1977
1978 bool drawCursor = ((editable || (textInteractionFlags() & Qt::TextSelectableByKeyboard))
1979 && context.cursorPosition >= blpos
1980 && context.cursorPosition < blpos + bllen);
1981
1982 bool drawCursorAsBlock = drawCursor && overwriteMode() ;
1983
1984 if (drawCursorAsBlock) {
1985 if (context.cursorPosition == blpos + bllen - 1) {
1986 drawCursorAsBlock = false;
1987 } else {
1989 o.start = context.cursorPosition - blpos;
1990 o.length = 1;
1991 o.format.setForeground(palette().base());
1992 o.format.setBackground(palette().text());
1993 selections.append(o);
1994 }
1995 }
1996
1997 layout->draw(&painter, offset, selections, er);
1998
1999 if ((drawCursor && !drawCursorAsBlock)
2000 || (editable && context.cursorPosition < -1
2001 && !layout->preeditAreaText().isEmpty())) {
2002 int cpos = context.cursorPosition;
2003 if (cpos < -1)
2004 cpos = layout->preeditAreaPosition() - (cpos + 2);
2005 else
2006 cpos -= blpos;
2007 layout->drawCursor(&painter, offset, cpos, cursorWidth());
2008 }
2009 }
2010
2011 offset.ry() += r.height();
2012 if (offset.y() > viewportRect.height())
2013 break;
2014 block = block.next();
2015 }
2016
2017 if (backgroundVisible() && !block.isValid() && offset.y() <= er.bottom()
2018 && (centerOnScroll() || verticalScrollBar()->maximum() == verticalScrollBar()->minimum())) {
2019 painter.fillRect(QRect(QPoint((int)er.left(), (int)offset.y()), er.bottomRight()), palette().window());
2020 }
2021}
2022
2023
2025{
2026 QTextDocument *doc = control->document();
2027
2029 QTextOption::WrapMode oldWrapMode = opt.wrapMode();
2030
2032 opt.setWrapMode(QTextOption::NoWrap);
2033 else
2034 opt.setWrapMode(wordWrap);
2035
2036 if (opt.wrapMode() != oldWrapMode)
2038}
2039
2040
2044{
2045 Q_D(QPlainTextEdit);
2046#ifdef QT_KEYPAD_NAVIGATION
2047 if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus())
2048 setEditFocus(true);
2049#endif
2050 d->sendControlEvent(e);
2051}
2052
2056{
2057 Q_D(QPlainTextEdit);
2058 d->inDrag = false; // paranoia
2059 const QPoint pos = e->position().toPoint();
2060 d->sendControlEvent(e);
2061 if (!(e->buttons() & Qt::LeftButton))
2062 return;
2064 const QRect visible = d->viewport->rect();
2065 if (visible.contains(pos))
2066 d->autoScrollTimer.stop();
2067 else if (!d->autoScrollTimer.isActive())
2068 d->autoScrollTimer.start(100, this);
2069 }
2070}
2071
2075{
2076 Q_D(QPlainTextEdit);
2077 d->sendControlEvent(e);
2078 if (e->source() == Qt::MouseEventNotSynthesized && d->autoScrollTimer.isActive()) {
2079 d->autoScrollTimer.stop();
2080 d->ensureCursorVisible();
2081 }
2082
2083 if (!isReadOnly() && rect().contains(e->position().toPoint()))
2084 d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
2085 d->clickCausedFocus = 0;
2086}
2087
2091{
2092 Q_D(QPlainTextEdit);
2093 d->sendControlEvent(e);
2094}
2095
2099{
2100 Q_D(const QPlainTextEdit);
2101 if (!d->tabChangesFocus && d->control->textInteractionFlags() & Qt::TextEditable)
2102 return false;
2103 return QAbstractScrollArea::focusNextPrevChild(next);
2104}
2105
2106#ifndef QT_NO_CONTEXTMENU
2123{
2124 Q_D(QPlainTextEdit);
2125 d->sendControlEvent(e);
2126}
2127#endif // QT_NO_CONTEXTMENU
2128
2129#if QT_CONFIG(draganddrop)
2132void QPlainTextEdit::dragEnterEvent(QDragEnterEvent *e)
2133{
2134 Q_D(QPlainTextEdit);
2135 d->inDrag = true;
2136 d->sendControlEvent(e);
2137}
2138
2141void QPlainTextEdit::dragLeaveEvent(QDragLeaveEvent *e)
2142{
2143 Q_D(QPlainTextEdit);
2144 d->inDrag = false;
2145 d->autoScrollTimer.stop();
2146 d->sendControlEvent(e);
2147}
2148
2151void QPlainTextEdit::dragMoveEvent(QDragMoveEvent *e)
2152{
2153 Q_D(QPlainTextEdit);
2154 d->autoScrollDragPos = e->position().toPoint();
2155 if (!d->autoScrollTimer.isActive())
2156 d->autoScrollTimer.start(100, this);
2157 d->sendControlEvent(e);
2158}
2159
2162void QPlainTextEdit::dropEvent(QDropEvent *e)
2163{
2164 Q_D(QPlainTextEdit);
2165 d->inDrag = false;
2166 d->autoScrollTimer.stop();
2167 d->sendControlEvent(e);
2168}
2169
2170#endif // QT_CONFIG(draganddrop)
2171
2175{
2176 Q_D(QPlainTextEdit);
2177#ifdef QT_KEYPAD_NAVIGATION
2178 if (d->control->textInteractionFlags() & Qt::TextEditable
2179 && QApplicationPrivate::keypadNavigationEnabled()
2180 && !hasEditFocus()) {
2181 setEditFocus(true);
2182 selectAll(); // so text is replaced rather than appended to
2183 }
2184#endif
2185 d->sendControlEvent(e);
2186 const bool emptyEvent = e->preeditString().isEmpty() && e->commitString().isEmpty()
2187 && e->attributes().isEmpty();
2188 if (emptyEvent)
2189 return;
2191}
2192
2195void QPlainTextEdit::scrollContentsBy(int dx, int /*dy*/)
2196{
2197 Q_D(QPlainTextEdit);
2198 d->setTopLine(d->vbar->value(), dx);
2199}
2200
2207
2211{
2212 Q_D(const QPlainTextEdit);
2213 switch (query) {
2214 case Qt::ImEnabled:
2215 return isEnabled() && !isReadOnly();
2216 case Qt::ImHints:
2219 case Qt::ImReadOnly:
2220 return isReadOnly();
2221 default:
2222 break;
2223 }
2224
2225 const QPointF offset = contentOffset();
2226 switch (argument.userType()) {
2227 case QMetaType::QRectF:
2228 argument = argument.toRectF().translated(-offset);
2229 break;
2230 case QMetaType::QPointF:
2231 argument = argument.toPointF() - offset;
2232 break;
2233 case QMetaType::QRect:
2234 argument = argument.toRect().translated(-offset.toPoint());
2235 break;
2236 case QMetaType::QPoint:
2237 argument = argument.toPoint() - offset;
2238 break;
2239 default:
2240 break;
2241 }
2242
2243 const QVariant v = d->control->inputMethodQuery(query, argument);
2244 switch (v.userType()) {
2245 case QMetaType::QRectF:
2246 return v.toRectF().translated(offset);
2247 case QMetaType::QPointF:
2248 return v.toPointF() + offset;
2249 case QMetaType::QRect:
2250 return v.toRect().translated(offset.toPoint());
2251 case QMetaType::QPoint:
2252 return v.toPoint() + offset.toPoint();
2253 default:
2254 break;
2255 }
2256 return v;
2257}
2258
2262{
2263 Q_D(QPlainTextEdit);
2264 if (e->reason() == Qt::MouseFocusReason) {
2265 d->clickCausedFocus = 1;
2266 }
2267 QAbstractScrollArea::focusInEvent(e);
2268 d->sendControlEvent(e);
2269}
2270
2274{
2275 Q_D(QPlainTextEdit);
2276 QAbstractScrollArea::focusOutEvent(e);
2277 d->sendControlEvent(e);
2278}
2279
2283{
2284 Q_D(QPlainTextEdit);
2285 if (d->showCursorOnInitialShow) {
2286 d->showCursorOnInitialShow = false;
2288 }
2289 d->adjustScrollbars();
2290}
2291
2295{
2296 Q_D(QPlainTextEdit);
2297 QAbstractScrollArea::changeEvent(e);
2298
2299 switch (e->type()) {
2301 case QEvent::FontChange:
2302 d->control->document()->setDefaultFont(font());
2303 break;
2305 if (!isActiveWindow())
2306 d->autoScrollTimer.stop();
2307 break;
2309 e->setAccepted(isEnabled());
2310 d->control->setPalette(palette());
2311 d->sendControlEvent(e);
2312 break;
2314 d->control->setPalette(palette());
2315 break;
2317 d->sendControlEvent(e);
2318 break;
2319 default:
2320 break;
2321 }
2322}
2323
2326#if QT_CONFIG(wheelevent)
2327void QPlainTextEdit::wheelEvent(QWheelEvent *e)
2328{
2329 Q_D(QPlainTextEdit);
2330 if (!(d->control->textInteractionFlags() & Qt::TextEditable)) {
2331 if (e->modifiers() & Qt::ControlModifier) {
2332 float delta = e->angleDelta().y() / 120.f;
2333 zoomInF(delta);
2334 return;
2335 }
2336 }
2337 QAbstractScrollArea::wheelEvent(e);
2338 updateMicroFocus();
2339}
2340#endif
2341
2350{
2351 zoomInF(range);
2352}
2353
2362{
2363 zoomInF(-range);
2364}
2365
2370{
2371 if (range == 0.f)
2372 return;
2373 QFont f = font();
2374 const float newSize = f.pointSizeF() + range;
2375 if (newSize <= 0)
2376 return;
2377 f.setPointSizeF(newSize);
2378 setFont(f);
2379}
2380
2381#ifndef QT_NO_CONTEXTMENU
2392{
2393 Q_D(QPlainTextEdit);
2394 return d->control->createStandardContextMenu(QPointF(), this);
2395}
2396
2408{
2409 Q_D(QPlainTextEdit);
2410 return d->control->createStandardContextMenu(position, this);
2411}
2412#endif // QT_NO_CONTEXTMENU
2413
2418{
2419 Q_D(const QPlainTextEdit);
2420 return d->control->cursorForPosition(d->mapToContents(pos));
2421}
2422
2428{
2429 Q_D(const QPlainTextEdit);
2430 if (cursor.isNull())
2431 return QRect();
2432
2433 QRect r = d->control->cursorRect(cursor).toRect();
2434 r.translate(-d->horizontalOffset(),-(int)d->verticalOffset());
2435 return r;
2436}
2437
2443{
2444 Q_D(const QPlainTextEdit);
2445 QRect r = d->control->cursorRect().toRect();
2446 r.translate(-d->horizontalOffset(),-(int)d->verticalOffset());
2447 return r;
2448}
2449
2450
2466{
2467 Q_D(const QPlainTextEdit);
2468 return d->control->overwriteMode();
2469}
2470
2472{
2473 Q_D(QPlainTextEdit);
2474 d->control->setOverwriteMode(overwrite);
2475}
2476
2492{
2493 Q_D(const QPlainTextEdit);
2494 return d->control->document()->defaultTextOption().tabStopDistance();
2495}
2496
2498{
2499 Q_D(QPlainTextEdit);
2500 QTextOption opt = d->control->document()->defaultTextOption();
2501 if (opt.tabStopDistance() == distance || distance < 0)
2502 return;
2503 opt.setTabStopDistance(distance);
2504 d->control->document()->setDefaultTextOption(opt);
2505}
2506
2507
2514{
2515 Q_D(const QPlainTextEdit);
2516 return d->control->cursorWidth();
2517}
2518
2520{
2521 Q_D(QPlainTextEdit);
2522 d->control->setCursorWidth(width);
2523}
2524
2525
2526
2535void QPlainTextEdit::setExtraSelections(const QList<QTextEdit::ExtraSelection> &selections)
2536{
2537 Q_D(QPlainTextEdit);
2538 d->control->setExtraSelections(selections);
2539}
2540
2546QList<QTextEdit::ExtraSelection> QPlainTextEdit::extraSelections() const
2547{
2548 Q_D(const QPlainTextEdit);
2549 return d->control->extraSelections();
2550}
2551
2563{
2564 Q_D(const QPlainTextEdit);
2565 return d->control->QWidgetTextControl::createMimeDataFromSelection();
2566}
2567
2575{
2576 Q_D(const QPlainTextEdit);
2577 return d->control->QWidgetTextControl::canInsertFromMimeData(source);
2578}
2579
2588{
2589 Q_D(QPlainTextEdit);
2590 d->control->QWidgetTextControl::insertFromMimeData(source);
2591}
2592
2604{
2605 Q_D(const QPlainTextEdit);
2606 return !d->control || !(d->control->textInteractionFlags() & Qt::TextEditable);
2607}
2608
2610{
2611 Q_D(QPlainTextEdit);
2612 Qt::TextInteractionFlags flags = Qt::NoTextInteraction;
2613 if (ro) {
2615 } else {
2617 }
2618 d->control->setTextInteractionFlags(flags);
2622}
2623
2637{
2638 Q_D(QPlainTextEdit);
2639 d->control->setTextInteractionFlags(flags);
2640}
2641
2642Qt::TextInteractionFlags QPlainTextEdit::textInteractionFlags() const
2643{
2644 Q_D(const QPlainTextEdit);
2645 return d->control->textInteractionFlags();
2646}
2647
2657{
2658 Q_D(QPlainTextEdit);
2659 d->control->mergeCurrentCharFormat(modifier);
2660}
2661
2669{
2670 Q_D(QPlainTextEdit);
2671 d->control->setCurrentCharFormat(format);
2672}
2673
2678{
2679 Q_D(const QPlainTextEdit);
2680 return d->control->currentCharFormat();
2681}
2682
2683
2684
2694{
2695 Q_D(QPlainTextEdit);
2696 d->control->insertPlainText(text);
2697}
2698
2699
2710{
2711 Q_D(QPlainTextEdit);
2712 d->control->moveCursor(operation, mode);
2713}
2714
2719{
2720 Q_D(const QPlainTextEdit);
2721 return d->control->canPaste();
2722}
2723
2731#ifndef QT_NO_PRINTER
2733{
2734 Q_D(const QPlainTextEdit);
2735 d->control->print(printer);
2736}
2737#endif
2738
2749{
2750 Q_D(const QPlainTextEdit);
2751 return d->tabChangesFocus;
2752}
2753
2755{
2756 Q_D(QPlainTextEdit);
2757 d->tabChangesFocus = b;
2758}
2759
2778{
2779 Q_D(const QPlainTextEdit);
2780 return d->lineWrap;
2781}
2782
2784{
2785 Q_D(QPlainTextEdit);
2786 if (d->lineWrap == wrap)
2787 return;
2788 d->lineWrap = wrap;
2789 d->updateDefaultTextOption();
2790 d->relayoutDocument();
2791 d->adjustScrollbars();
2793}
2794
2805{
2806 Q_D(const QPlainTextEdit);
2807 return d->wordWrap;
2808}
2809
2811{
2812 Q_D(QPlainTextEdit);
2813 if (mode == d->wordWrap)
2814 return;
2815 d->wordWrap = mode;
2816 d->updateDefaultTextOption();
2817}
2818
2834{
2835 Q_D(const QPlainTextEdit);
2836 return d->backgroundVisible;
2837}
2838
2840{
2841 Q_D(QPlainTextEdit);
2842 if (visible == d->backgroundVisible)
2843 return;
2844 d->backgroundVisible = visible;
2845 d->updateViewport();
2846}
2847
2866{
2867 Q_D(const QPlainTextEdit);
2868 return d->centerOnScroll;
2869}
2870
2872{
2873 Q_D(QPlainTextEdit);
2874 if (enabled == d->centerOnScroll)
2875 return;
2876 d->centerOnScroll = enabled;
2877 d->adjustScrollbars();
2878}
2879
2880
2881
2887bool QPlainTextEdit::find(const QString &exp, QTextDocument::FindFlags options)
2888{
2889 Q_D(QPlainTextEdit);
2890 return d->control->find(exp, options);
2891}
2892
2909#if QT_CONFIG(regularexpression)
2910bool QPlainTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
2911{
2912 Q_D(QPlainTextEdit);
2913 return d->control->find(exp, options);
2914}
2915#endif
2916
2987{
2988 Q_Q(QPlainTextEdit);
2989
2990 QTextDocument *document = control->document();
2991 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document->documentLayout());
2992 Q_ASSERT(documentLayout);
2993
2994 int maximumBlockCount = document->maximumBlockCount();
2995 if (maximumBlockCount)
2996 document->setMaximumBlockCount(0);
2997
2998 const bool atBottom = q->isVisible()
2999 && (control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
3000 <= viewport->rect().bottom());
3001
3002 if (!q->isVisible())
3004
3005 bool documentSizeChangedBlocked = documentLayout->priv()->blockDocumentSizeChanged;
3006 documentLayout->priv()->blockDocumentSizeChanged = true;
3007
3008 switch (format) {
3009 case Qt::RichText:
3011 break;
3012 case Qt::PlainText:
3014 break;
3015 default:
3017 break;
3018 }
3019
3020 if (maximumBlockCount > 0) {
3021 if (document->blockCount() > maximumBlockCount) {
3022 bool blockUpdate = false;
3023 if (control->topBlock) {
3024 control->topBlock--;
3025 blockUpdate = true;
3026 emit q->updateRequest(viewport->rect(), 0);
3027 }
3028
3029 bool updatesBlocked = documentLayout->priv()->blockUpdate;
3030 documentLayout->priv()->blockUpdate = blockUpdate;
3031 QTextCursor cursor(document);
3033 cursor.removeSelectedText();
3034 documentLayout->priv()->blockUpdate = updatesBlocked;
3035 }
3036 document->setMaximumBlockCount(maximumBlockCount);
3037 }
3038
3039 documentLayout->priv()->blockDocumentSizeChanged = documentSizeChangedBlocked;
3041
3042
3043 if (atBottom) {
3044 const bool needScroll = !centerOnScroll
3045 || control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
3046 > viewport->rect().bottom();
3047 if (needScroll)
3048 vbar->setValue(vbar->maximum());
3049 }
3050}
3051
3052
3060{
3061 Q_D(QPlainTextEdit);
3062 d->append(text, Qt::PlainText);
3063}
3064
3072{
3073 Q_D(QPlainTextEdit);
3074 d->append(html, Qt::RichText);
3075}
3076
3078{
3079 Q_Q(QPlainTextEdit);
3080 QRect visible = viewport->rect();
3081 QRect cr = q->cursorRect();
3082 if (cr.top() < visible.top() || cr.bottom() > visible.bottom()) {
3084 }
3085
3086 const bool rtl = q->isRightToLeft();
3087 if (cr.left() < visible.left() || cr.right() > visible.right()) {
3088 int x = cr.center().x() + horizontalOffset() - visible.width()/2;
3089 hbar->setValue(rtl ? hbar->maximum() - x : x);
3090 }
3091}
3092
3100{
3101 Q_D(QPlainTextEdit);
3102 d->ensureCursorVisible(d->centerOnScroll);
3103}
3104
3105
3111{
3112 Q_D(QPlainTextEdit);
3113 d->ensureVisible(textCursor().position(), true, true);
3114}
3115
3122{
3123 Q_D(const QPlainTextEdit);
3124 return d->control->firstVisibleBlock();
3125}
3126
3141{
3142 Q_D(const QPlainTextEdit);
3143 return QPointF(-d->horizontalOffset(), -d->verticalOffset());
3144}
3145
3146
3154{
3155 Q_D(const QPlainTextEdit);
3156 return d->control->blockBoundingRect(block);
3157}
3158
3165{
3166 QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout());
3167 Q_ASSERT(documentLayout);
3168 return documentLayout->blockBoundingRect(block);
3169}
3170
3178{
3179 return document()->blockCount();
3180}
3181
3186{
3187 Q_D(const QPlainTextEdit);
3188 return d->control->getPaintContext(d->viewport);
3189}
3190
3232
3233#include "moc_qplaintextedit.cpp"
3234#include "moc_qplaintextedit_p.cpp"
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
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:594
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:307
@ 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
@ WindowActivate
Definition qcoreevent.h:83
@ PaletteChange
Definition qcoreevent.h:94
@ ApplicationFontChange
Definition qcoreevent.h:91
@ WindowDeactivate
Definition qcoreevent.h:84
@ ContextMenu
Definition qcoreevent.h:119
Type type() const
Returns the event type.
Definition qcoreevent.h:304
void ignore()
Clears the accept flag parameter of the event object, the equivalent of calling setAccepted(false).
Definition qcoreevent.h:311
bool isAccepted() const
Definition qcoreevent.h:308
void accept()
Sets the accept flag of the event object, the equivalent of calling setAccepted(true).
Definition qcoreevent.h:310
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:470
Qt::FocusReason reason() const
Returns the reason for this focus event.
Definition qevent.cpp:1569
\reentrant \inmodule QtGui
\reentrant
Definition qfont.h:22
The QGestureEvent class provides the description of triggered gestures.
Definition qgesture.h:244
\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:625
const QString & preeditString() const
Returns the preedit text, i.e.
Definition qevent.h:650
const QString & commitString() const
Returns the text that should get added to (or replace parts of) the text of the editor widget.
Definition qevent.h:652
const QList< Attribute > & attributes() const
Returns the list of attributes passed to the QInputMethodEvent constructor.
Definition qevent.h:649
The QKeyEvent class describes a key event.
Definition qevent.h:424
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately after the event occurred.
Definition qevent.cpp:1468
QString text() const
Returns the Unicode text that this key generated.
Definition qevent.h:443
bool isAutoRepeat() const
Returns true if this event comes from an auto-repeating key; returns false if it comes from an initia...
Definition qevent.h:444
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:434
bool isEmpty() const override
\reimp
Definition qlayout.cpp:422
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:794
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:196
Qt::MouseEventSource source() const
Definition qevent.cpp:801
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:299
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtGui
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:486
const QRect & rect() const
Returns the rectangle that needs to be updated.
Definition qevent.h:492
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
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 pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode, bool moveCursor=true)
QPlainTextEditControl * control
void repaintContents(const QRectF &contentsRect)
void append(const QString &text, Qt::TextFormat format=Qt::AutoText)
void ensureVisible(int position, bool center, bool forceCenter=false)
bool placeHolderTextToBeShown() const
QTextOption::WrapMode wordWrap
void init(const QString &txt=QString())
QPlainTextEdit::LineWrapMode lineWrap
void setTopLine(int visualTopLine, int dx=0)
void verticalScrollbarActionTriggered(int action)
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:217
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
constexpr qreal & rx() noexcept
Returns a reference to the x coordinate of this point.
Definition qpoint.h:363
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:404
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr qreal bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:500
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:732
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:729
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:762
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:813
constexpr void setWidth(qreal w) noexcept
Sets the width of the rectangle to the given finite width.
Definition qrect.h:818
constexpr QPointF topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:511
constexpr QPointF bottomRight() const noexcept
Returns the position of the rectangle's bottom-right corner.
Definition qrect.h:512
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:805
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:738
constexpr qreal top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:498
constexpr bool isValid() const noexcept
Returns true if the rectangle is valid, otherwise returns false.
Definition qrect.h:666
\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:373
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:182
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:370
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:176
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:855
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:173
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:245
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr QPoint center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:233
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:179
\inmodule QtCore \reentrant
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:548
const QSize & oldSize() const
Returns the old size of the widget.
Definition qevent.h:554
const QSize & size() const
Returns the new size of the widget.
Definition qevent.h:553
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:578
QPointF position() const
Returns the position of the point in this event, relative to the widget or item that received the eve...
Definition qevent.h:119
Qt::MouseButton button() const
Returns the button that caused the event.
Definition qevent.h:116
Qt::MouseButtons buttons() const
Returns the button state when the event was generated.
Definition qevent.h:117
\inmodule QtCore
Definition qsize.h:208
constexpr qreal width() const noexcept
Returns the width.
Definition qsize.h:332
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
\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:366
int timerId() const
Returns the unique timer identifier, which is the same identifier as returned from QObject::startTime...
Definition qcoreevent.h:370
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
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:65
QRectF toRectF() const
Returns the variant as a QRectF if the variant has userType() \l QMetaType::QRect or \l QMetaType::QR...
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:9641
virtual QVariant inputMethodQuery(Qt::InputMethodQuery) const
This method is only relevant for input widgets.
Definition qwidget.cpp:9913
QString text
QCursor cursor
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:153
@ NavigationModeKeypadDirectional
@ LeftButton
Definition qnamespace.h:58
@ TextSelectableByMouse
@ TextEditable
@ TextEditorInteraction
@ LinksAccessibleByKeyboard
@ TextSelectableByKeyboard
@ NoTextInteraction
@ WA_KeyCompression
Definition qnamespace.h:300
@ WA_InputMethodEnabled
Definition qnamespace.h:295
TextFormat
@ RichText
@ PlainText
@ GestureStarted
@ StrongFocus
Definition qnamespace.h:110
@ TextWordWrap
Definition qnamespace.h:174
@ MouseEventNotSynthesized
@ IBeamCursor
@ ImhMultiLine
HitTestAccuracy
Definition qnamespace.h:203
@ ExactHit
Definition qnamespace.h:203
@ Key_Select
@ Key_Right
Definition qnamespace.h:679
@ Key_Space
Definition qnamespace.h:513
@ Key_Left
Definition qnamespace.h:677
@ Key_Up
Definition qnamespace.h:678
@ Key_Down
Definition qnamespace.h:680
@ Key_Back
Definition qnamespace.h:846
@ Key_Home
Definition qnamespace.h:675
@ Key_End
Definition qnamespace.h:676
@ 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:166
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:187
static const uint base
Definition qurlidna.cpp:20
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