129 control =
new QTextEditControl(q);
130 control->setPalette(q->palette());
133 QObjectPrivate::connect(control, &QTextEditControl::documentSizeChanged,
134 this, &QTextEditPrivate::adjustScrollbars),
135 QObjectPrivate::connect(control, &QTextEditControl::updateRequest,
136 this, &QTextEditPrivate::repaintContents),
137 QObjectPrivate::connect(control, &QTextEditControl::visibilityRequest,
138 this, &QTextEditPrivate::ensureVisible),
139 QObjectPrivate::connect(control, &QTextEditControl::blockMarkerHovered,
140 this, &QTextEditPrivate::hoveredBlockWithMarkerChanged),
141 QObjectPrivate::connect(control, &QTextEditControl::cursorPositionChanged,
142 this, &QTextEditPrivate::cursorPositionChanged),
143 QObject::connect(control, &QTextEditControl::microFocusChanged,
144 q, [q]() { q->updateMicroFocus(); }),
145 QObject::connect(control, &QTextEditControl::currentCharFormatChanged,
146 q, &QTextEdit::currentCharFormatChanged),
147 QObject::connect(control, &QTextEditControl::textChanged,
148 q, &QTextEdit::textChanged),
149 QObject::connect(control, &QTextEditControl::undoAvailable,
150 q, &QTextEdit::undoAvailable),
151 QObject::connect(control, &QTextEditControl::redoAvailable,
152 q, &QTextEdit::redoAvailable),
153 QObject::connect(control, &QTextEditControl::copyAvailable,
154 q, &QTextEdit::copyAvailable),
155 QObject::connect(control, &QTextEditControl::selectionChanged,
156 q, &QTextEdit::selectionChanged),
157 QObject::connect(control, &QTextEditControl::textChanged,
158 q, [q]() { q->updateMicroFocus(); }),
161 QTextDocument *doc = control->document();
165 doc->setPageSize(QSize(0, 0));
166 doc->documentLayout()->setPaintDevice(viewport);
167 doc->setDefaultFont(q->font());
168 doc->setUndoRedoEnabled(
false);
169 doc->setUndoRedoEnabled(
true);
172 control->setHtml(html);
174 const auto singleStep = defaultSingleStep();
175 hbar->setSingleStep(singleStep);
176 vbar->setSingleStep(singleStep);
178 viewport->setBackgroundRole(QPalette::Base);
179 q->setMouseTracking(
true);
180 q->setAcceptDrops(
true);
181 q->setFocusPolicy(Qt::StrongFocus);
182 q->setAttribute(Qt::WA_KeyCompression);
183 q->setAttribute(Qt::WA_InputMethodEnabled);
184 q->setInputMethodHints(Qt::ImhMultiLine);
186 viewport->setCursor(Qt::IBeamCursor);
237 QTextCursor cursor = control->textCursor();
239 qreal lastY = control->cursorRect(cursor).top();
243 qreal y = control->cursorRect(cursor).top();
244 distance += qAbs(y - lastY);
246 moved = cursor.movePosition(op, moveMode);
247 }
while (moved && distance < viewport->height());
250 if (op == QTextCursor::Up) {
251 cursor.movePosition(QTextCursor::Down, moveMode);
252 vbar->triggerAction(QAbstractSlider::SliderPageStepSub);
254 cursor.movePosition(QTextCursor::Up, moveMode);
255 vbar->triggerAction(QAbstractSlider::SliderPageStepAdd);
258 control->setTextCursor(cursor, moveMode == QTextCursor::KeepAnchor);
334 const QRect rect = _rect.toRect();
335 if ((vbar->isVisible() && vbar->maximum() < rect.bottom())
336 || (hbar->isVisible() && hbar->maximum() < rect.right()))
338 const int visibleWidth = viewport->width();
339 const int visibleHeight = viewport->height();
340 const bool rtl = q_func()->isRightToLeft();
344 hbar->setValue(hbar->maximum() - rect.x());
346 hbar->setValue(rect.x());
349 hbar->setValue(hbar->maximum() - (rect.x() + rect.width() - visibleWidth));
351 hbar->setValue(rect.x() + rect.width() - visibleWidth);
354 if (rect.y() < verticalOffset())
355 vbar->setValue(rect.y());
356 else if (rect.y() + rect.height() > verticalOffset() + visibleHeight)
357 vbar->setValue(rect.y() + rect.height() - visibleHeight);
1087bool QTextEdit::event(QEvent *e)
1090 switch (e->type()) {
1091 case QEvent::ShortcutOverride:
1092 case QEvent::ToolTip:
1093 d->sendControlEvent(e);
1095 case QEvent::WindowActivate:
1096 case QEvent::WindowDeactivate:
1097 d->control->setPalette(palette());
1099#ifndef QT_NO_CONTEXTMENU
1100 case QEvent::ContextMenu:
1101 if (
static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) {
1102 ensureCursorVisible();
1103 const QPoint cursorPos = cursorRect().center();
1104 QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos));
1105 ce.setAccepted(e->isAccepted());
1106 const bool result = QAbstractScrollArea::event(&ce);
1107 e->setAccepted(ce.isAccepted());
1112#ifdef QT_KEYPAD_NAVIGATION
1113 case QEvent::EnterEditFocus:
1114 case QEvent::LeaveEditFocus:
1115 if (QApplicationPrivate::keypadNavigationEnabled())
1116 d->sendControlEvent(e);
1122 return QAbstractScrollArea::event(e);
1128void QTextEdit::timerEvent(QTimerEvent *e)
1131 if (e->timerId() == d->autoScrollTimer.timerId()) {
1132 QRect visible = d->viewport->rect();
1135 pos = d->autoScrollDragPos;
1136 visible.adjust(qMin(visible.width()/3,20), qMin(visible.height()/3,20),
1137 -qMin(visible.width()/3,20), -qMin(visible.height()/3,20));
1139 const QPoint globalPos = QCursor::pos();
1140 pos = d->viewport->mapFromGlobal(globalPos);
1141 QMouseEvent ev(QEvent::MouseMove, pos, mapTo(topLevelWidget(), pos), globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1142 mouseMoveEvent(&ev);
1144 int deltaY = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height();
1145 int deltaX = qMax(pos.x() - visible.left(), visible.right() - pos.x()) - visible.width();
1146 int delta = qMax(deltaX, deltaY);
1150 int timeout = 4900 / (delta * delta);
1151 d->autoScrollTimer.start(timeout,
this);
1154 d->vbar->triggerAction(pos.y() < visible.center().y() ?
1155 QAbstractSlider::SliderSingleStepSub
1156 : QAbstractSlider::SliderSingleStepAdd);
1158 d->hbar->triggerAction(pos.x() < visible.center().x() ?
1159 QAbstractSlider::SliderSingleStepSub
1160 : QAbstractSlider::SliderSingleStepAdd);
1163#ifdef QT_KEYPAD_NAVIGATION
1164 else if (e->timerId() == d->deleteAllTimer.timerId()) {
1165 d->deleteAllTimer.stop();
1297void QTextEdit::keyPressEvent(QKeyEvent *e)
1301#ifdef QT_KEYPAD_NAVIGATION
1303 case Qt::Key_Select:
1304 if (QApplicationPrivate::keypadNavigationEnabled()) {
1306 if (d->control->textInteractionFlags() & Qt::TextEditable) {
1307 setEditFocus(!hasEditFocus());
1309 if (!hasEditFocus())
1312 QTextCursor cursor = d->control->textCursor();
1313 QTextCharFormat charFmt = cursor.charFormat();
1314 if (!(d->control->textInteractionFlags() & Qt::LinksAccessibleByKeyboard)
1315 || !cursor.hasSelection() || charFmt.anchorHref().isEmpty()) {
1325 if (!QApplicationPrivate::keypadNavigationEnabled() || !hasEditFocus()) {
1331 if (QApplicationPrivate::keypadNavigationEnabled()) {
1332 if (!hasEditFocus() && !(e->modifiers() & Qt::ControlModifier)) {
1333 if (e->text()[0].isPrint())
1344#ifndef QT_NO_SHORTCUT
1346 Qt::TextInteractionFlags tif = d->control->textInteractionFlags();
1348 if (tif & Qt::TextSelectableByKeyboard){
1349 if (e == QKeySequence::SelectPreviousPage) {
1351 d->pageUpDown(QTextCursor::Up, QTextCursor::KeepAnchor);
1353 }
else if (e ==QKeySequence::SelectNextPage) {
1355 d->pageUpDown(QTextCursor::Down, QTextCursor::KeepAnchor);
1359 if (tif & (Qt::TextSelectableByKeyboard | Qt::TextEditable)) {
1360 if (e == QKeySequence::MoveToPreviousPage) {
1362 d->pageUpDown(QTextCursor::Up, QTextCursor::MoveAnchor);
1364 }
else if (e == QKeySequence::MoveToNextPage) {
1366 d->pageUpDown(QTextCursor::Down, QTextCursor::MoveAnchor);
1371 if (!(tif & Qt::TextEditable)) {
1375 if (e->modifiers() & Qt::ShiftModifier)
1376 d->vbar->triggerAction(QAbstractSlider::SliderPageStepSub);
1378 d->vbar->triggerAction(QAbstractSlider::SliderPageStepAdd);
1381 d->sendControlEvent(e);
1382 if (!e->isAccepted() && e->modifiers() == Qt::NoModifier) {
1383 if (e->key() == Qt::Key_Home) {
1384 d->vbar->triggerAction(QAbstractSlider::SliderToMinimum);
1386 }
else if (e->key() == Qt::Key_End) {
1387 d->vbar->triggerAction(QAbstractSlider::SliderToMaximum);
1391 if (!e->isAccepted()) {
1392 QAbstractScrollArea::keyPressEvent(e);
1400 QTextCursor cursor = d->control->textCursor();
1401 const QString text = e->text();
1402 if (cursor.atBlockStart()
1403 && (d->autoFormatting & AutoBulletList)
1404 && (text.size() == 1)
1405 && (text.at(0) == u'-' || text.at(0) == u'*')
1406 && (!cursor.currentList())) {
1408 d->createAutoBulletList();
1414 d->sendControlEvent(e);
1415#ifdef QT_KEYPAD_NAVIGATION
1416 if (!e->isAccepted()) {
1420 if (QApplicationPrivate::keypadNavigationEnabled()) {
1428 if (!e->isAutoRepeat()) {
1429 if (QApplicationPrivate::keypadNavigationEnabled()) {
1430 if (document()->isEmpty() || !(d->control->textInteractionFlags() & Qt::TextEditable)) {
1431 setEditFocus(
false);
1433 }
else if (!d->deleteAllTimer.isActive()) {
1435 d->deleteAllTimer.start(750,
this);
1451void QTextEdit::keyReleaseEvent(QKeyEvent *e)
1455 d->handleSoftwareInputPanel();
1456#ifdef QT_KEYPAD_NAVIGATION
1457 if (QApplicationPrivate::keypadNavigationEnabled()) {
1458 if (!e->isAutoRepeat() && e->key() == Qt::Key_Back
1459 && d->deleteAllTimer.isActive()) {
1460 d->deleteAllTimer.stop();
1461 QTextCursor cursor = d->control->textCursor();
1462 QTextBlockFormat blockFmt = cursor.blockFormat();
1464 QTextList *list = cursor.currentList();
1465 if (list && cursor.atBlockStart()) {
1466 list->remove(cursor.block());
1467 }
else if (cursor.atBlockStart() && blockFmt.indent() > 0) {
1468 blockFmt.setIndent(blockFmt.indent() - 1);
1469 cursor.setBlockFormat(blockFmt);
1471 cursor.deletePreviousChar();
1473 setTextCursor(cursor);
1524 QTextDocument *doc = control->document();
1525 QAbstractTextDocumentLayout *layout = doc->documentLayout();
1527 if (QTextDocumentLayout *tlayout = qobject_cast<QTextDocumentLayout *>(layout)) {
1528 if (lineWrap == QTextEdit::FixedColumnWidth)
1529 tlayout->setFixedColumnWidth(lineWrapColumnOrWidth);
1531 tlayout->setFixedColumnWidth(-1);
1534 QTextDocumentLayout *tlayout = qobject_cast<QTextDocumentLayout *>(layout);
1537 lastUsedSize = tlayout->dynamicDocumentSize().toSize();
1539 lastUsedSize = layout->documentSize().toSize();
1544 const bool oldIgnoreScrollbarAdjustment = ignoreAutomaticScrollbarAdjustment;
1545 ignoreAutomaticScrollbarAdjustment =
true;
1547 int width = viewport->width();
1548 if (lineWrap == QTextEdit::FixedPixelWidth)
1550 else if (lineWrap == QTextEdit::NoWrap) {
1551 QVariant alignmentProperty = doc->documentLayout()->property(
"contentHasAlignment");
1552 if (alignmentProperty.userType() == QMetaType::Bool && !alignmentProperty.toBool()) {
1558 doc->setPageSize(QSize(width, -1));
1562 ignoreAutomaticScrollbarAdjustment = oldIgnoreScrollbarAdjustment;
1566 usedSize = tlayout->dynamicDocumentSize().toSize();
1568 usedSize = layout->documentSize().toSize();
1586 if (lastUsedSize.isValid()
1587 && !vbar->isHidden()
1588 && viewport->width() < lastUsedSize.width()
1589 && usedSize.height() < lastUsedSize.height()
1590 && usedSize.height() <= viewport->height())
1601 QRect r = e->rect();
1602 p->translate(-xOffset, -yOffset);
1603 r.translate(xOffset, yOffset);
1605 QTextDocument *doc = control->document();
1606 QTextDocumentLayout *layout = qobject_cast<QTextDocumentLayout *>(doc->documentLayout());
1611 layout->setViewport(viewport->rect());
1613 control->drawContents(p, r, q_func());
1616 layout->setViewport(QRect());
1618 if (!placeholderText.isEmpty() && doc->isEmpty() && !control->isPreediting()) {
1619 const QColor col = control->palette().placeholderText().color();
1621 const int margin =
int(doc->documentMargin());
1622 QRectF boundingRect = layout ? layout->frameBoundingRect(doc->rootFrame()) : viewport->rect();
1623 p->drawText(boundingRect.adjusted(margin, margin, -margin, -margin),
1624 Qt::AlignTop | Qt::TextWordWrap,
1831QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument)
const
1833 Q_D(
const QTextEdit);
1836 return isEnabled() && !isReadOnly();
1838 case Qt::ImInputItemClipRectangle:
1839 return QWidget::inputMethodQuery(query);
1840 case Qt::ImReadOnly:
1841 return isReadOnly();
1846 const QPointF offset(-d->horizontalOffset(), -d->verticalOffset());
1847 switch (argument.userType()) {
1848 case QMetaType::QRectF:
1849 argument = argument.toRectF().translated(-offset);
1851 case QMetaType::QPointF:
1852 argument = argument.toPointF() - offset;
1854 case QMetaType::QRect:
1855 argument = argument.toRect().translated(-offset.toPoint());
1857 case QMetaType::QPoint:
1858 argument = argument.toPoint() - offset;
1864 const QVariant v = d->control->inputMethodQuery(query, argument);
1865 switch (v.userType()) {
1866 case QMetaType::QRectF:
1867 return v.toRectF().translated(offset);
1868 case QMetaType::QPointF:
1869 return v.toPointF() + offset;
1870 case QMetaType::QRect:
1871 return v.toRect().translated(offset.toPoint());
1872 case QMetaType::QPoint:
1873 return v.toPoint() + offset.toPoint();
1918void QTextEdit::changeEvent(QEvent *e)
1921 QAbstractScrollArea::changeEvent(e);
1922 if (e->type() == QEvent::ApplicationFontChange
1923 || e->type() == QEvent::FontChange) {
1924 d->control->document()->setDefaultFont(font());
1925 }
else if (e->type() == QEvent::ActivationChange) {
1926 if (!isActiveWindow())
1927 d->autoScrollTimer.stop();
1928 }
else if (e->type() == QEvent::EnabledChange) {
1929 e->setAccepted(isEnabled());
1930 d->control->setPalette(palette());
1931 d->sendControlEvent(e);
1932 }
else if (e->type() == QEvent::PaletteChange) {
1933 d->control->setPalette(palette());
1934 }
else if (e->type() == QEvent::LayoutDirectionChange) {
1935 d->sendControlEvent(e);
2244void QTextEdit::setReadOnly(
bool ro)
2247 Qt::TextInteractionFlags flags = Qt::NoTextInteraction;
2249 flags = Qt::TextSelectableByMouse;
2250#if QT_CONFIG(textbrowser)
2251 if (qobject_cast<QTextBrowser *>(
this))
2252 flags |= Qt::TextBrowserInteraction;
2255 flags = Qt::TextEditorInteraction;
2257 d->control->setTextInteractionFlags(flags);
2258 setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(
this));
2259 QEvent event(QEvent::ReadOnlyChange);
2260 QCoreApplication::sendEvent(
this, &event);
virtual void insertFromMimeData(const QMimeData *source) override
virtual QMimeData * createMimeDataFromSelection() const override
QVariant loadResource(int type, const QUrl &name) override
virtual bool canInsertFromMimeData(const QMimeData *source) const override
void pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode)
The QTextEdit class provides a widget that is used to edit and display both plain and rich text.
static QT_BEGIN_NAMESPACE bool shouldEnableInputMethod(QTextEdit *textedit)