diff options
Diffstat (limited to 'src/widgets/widgets/qtextedit.cpp')
-rw-r--r-- | src/widgets/widgets/qtextedit.cpp | 157 |
1 files changed, 88 insertions, 69 deletions
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index f3d1d3e511..90f09fcb79 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -21,7 +21,6 @@ #include <qmenu.h> #endif #include <qstyle.h> -#include <qtimer.h> #if QT_CONFIG(accessibility) #include <qaccessible.h> #endif @@ -88,8 +87,7 @@ QTextEditPrivate::QTextEditPrivate() : control(nullptr), autoFormatting(QTextEdit::AutoNone), tabChangesFocus(false), lineWrap(QTextEdit::WidgetWidth), lineWrapColumnOrWidth(0), - wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere), clickCausedFocus(0), - textFormat(Qt::AutoText) + wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere), clickCausedFocus(0) { ignoreAutomaticScrollbarAdjustment = false; preferRichText = false; @@ -97,6 +95,12 @@ QTextEditPrivate::QTextEditPrivate() inDrag = false; } +QTextEditPrivate::~QTextEditPrivate() +{ + for (const QMetaObject::Connection &connection : connections) + QObject::disconnect(connection); +} + void QTextEditPrivate::createAutoBulletList() { QTextCursor cursor = control->textCursor(); @@ -123,24 +127,34 @@ void QTextEditPrivate::init(const QString &html) control = new QTextEditControl(q); control->setPalette(q->palette()); - QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(updateMicroFocus())); - QObject::connect(control, SIGNAL(documentSizeChanged(QSizeF)), q, SLOT(_q_adjustScrollbars())); - QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(_q_repaintContents(QRectF))); - QObject::connect(control, SIGNAL(visibilityRequest(QRectF)), q, SLOT(_q_ensureVisible(QRectF))); - QObject::connect(control, SIGNAL(currentCharFormatChanged(QTextCharFormat)), - q, SLOT(_q_currentCharFormatChanged(QTextCharFormat))); - - QObject::connect(control, SIGNAL(textChanged()), q, SIGNAL(textChanged())); - QObject::connect(control, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool))); - QObject::connect(control, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool))); - QObject::connect(control, SIGNAL(copyAvailable(bool)), q, SIGNAL(copyAvailable(bool))); - QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged())); - QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(_q_cursorPositionChanged())); -#if QT_CONFIG(cursor) - QObject::connect(control, SIGNAL(blockMarkerHovered(QTextBlock)), q, SLOT(_q_hoveredBlockWithMarkerChanged(QTextBlock))); -#endif - - QObject::connect(control, SIGNAL(textChanged()), q, SLOT(updateMicroFocus())); + connections = { + QObjectPrivate::connect(control, &QTextEditControl::documentSizeChanged, + this, &QTextEditPrivate::adjustScrollbars), + QObjectPrivate::connect(control, &QTextEditControl::updateRequest, + this, &QTextEditPrivate::repaintContents), + QObjectPrivate::connect(control, &QTextEditControl::visibilityRequest, + this, &QTextEditPrivate::ensureVisible), + QObjectPrivate::connect(control, &QTextEditControl::blockMarkerHovered, + this, &QTextEditPrivate::hoveredBlockWithMarkerChanged), + QObjectPrivate::connect(control, &QTextEditControl::cursorPositionChanged, + this, &QTextEditPrivate::cursorPositionChanged), + QObject::connect(control, &QTextEditControl::microFocusChanged, + q, [q]() { q->updateMicroFocus(); }), + QObject::connect(control, &QTextEditControl::currentCharFormatChanged, + q, &QTextEdit::currentCharFormatChanged), + QObject::connect(control, &QTextEditControl::textChanged, + q, &QTextEdit::textChanged), + QObject::connect(control, &QTextEditControl::undoAvailable, + q, &QTextEdit::undoAvailable), + QObject::connect(control, &QTextEditControl::redoAvailable, + q, &QTextEdit::redoAvailable), + QObject::connect(control, &QTextEditControl::copyAvailable, + q, &QTextEdit::copyAvailable), + QObject::connect(control, &QTextEditControl::selectionChanged, + q, &QTextEdit::selectionChanged), + QObject::connect(control, &QTextEditControl::textChanged, + q, [q]() { q->updateMicroFocus(); }), + }; QTextDocument *doc = control->document(); // set a null page size initially to avoid any relayouting until the textedit @@ -170,7 +184,7 @@ void QTextEditPrivate::init(const QString &html) #endif } -void QTextEditPrivate::_q_repaintContents(const QRectF &contentsRect) +void QTextEditPrivate::repaintContents(const QRectF &contentsRect) { if (!contentsRect.isValid()) { viewport->update(); @@ -188,7 +202,7 @@ void QTextEditPrivate::_q_repaintContents(const QRectF &contentsRect) viewport->update(r); } -void QTextEditPrivate::_q_cursorPositionChanged() +void QTextEditPrivate::cursorPositionChanged() { Q_Q(QTextEdit); emit q->cursorPositionChanged(); @@ -198,9 +212,9 @@ void QTextEditPrivate::_q_cursorPositionChanged() #endif } -#if QT_CONFIG(cursor) -void QTextEditPrivate::_q_hoveredBlockWithMarkerChanged(const QTextBlock &block) +void QTextEditPrivate::hoveredBlockWithMarkerChanged(const QTextBlock &block) { +#if QT_CONFIG(cursor) Q_Q(QTextEdit); Qt::CursorShape cursor = cursorToRestoreAfterHover; if (block.isValid() && !q->isReadOnly()) { @@ -212,8 +226,8 @@ void QTextEditPrivate::_q_hoveredBlockWithMarkerChanged(const QTextBlock &block) } } viewport->setCursor(cursor); -} #endif +} void QTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode) { @@ -262,7 +276,7 @@ static QSize documentSize(QWidgetTextControl *control) return docSize; } -void QTextEditPrivate::_q_adjustScrollbars() +void QTextEditPrivate::adjustScrollbars() { if (ignoreAutomaticScrollbarAdjustment) return; @@ -312,12 +326,12 @@ void QTextEditPrivate::_q_adjustScrollbars() #endif // rect is in content coordinates -void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) +void QTextEditPrivate::ensureVisible(const QRectF &_rect) { const QRect rect = _rect.toRect(); if ((vbar->isVisible() && vbar->maximum() < rect.bottom()) || (hbar->isVisible() && hbar->maximum() < rect.right())) - _q_adjustScrollbars(); + adjustScrollbars(); const int visibleWidth = viewport->width(); const int visibleHeight = viewport->height(); const bool rtl = q_func()->isRightToLeft(); @@ -540,7 +554,7 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) of the movement keystrokes, for example, \e{Shift+Right} will select the character to the right, and \e{Shift+Ctrl+Right} will select the word to the right, etc. - \sa QTextDocument, QTextCursor, {Qt Widgets - Application Example}, + \sa QTextDocument, QTextCursor, {Syntax Highlighter Example}, {Rich Text Processing} */ @@ -713,7 +727,8 @@ QColor QTextEdit::textColor() const QColor QTextEdit::textBackgroundColor() const { Q_D(const QTextEdit); - return d->control->textCursor().charFormat().background().color(); + const QBrush &brush = d->control->textCursor().charFormat().background(); + return brush.style() == Qt::NoBrush ? Qt::transparent : brush.color(); } /*! @@ -1064,30 +1079,38 @@ void QTextEdit::selectAll() bool QTextEdit::event(QEvent *e) { Q_D(QTextEdit); -#ifndef QT_NO_CONTEXTMENU - if (e->type() == QEvent::ContextMenu - && static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) { - Q_D(QTextEdit); - ensureCursorVisible(); - const QPoint cursorPos = cursorRect().center(); - QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos)); - ce.setAccepted(e->isAccepted()); - const bool result = QAbstractScrollArea::event(&ce); - e->setAccepted(ce.isAccepted()); - return result; - } else if (e->type() == QEvent::ShortcutOverride - || e->type() == QEvent::ToolTip) { + switch (e->type()) { + case QEvent::ShortcutOverride: + case QEvent::ToolTip: d->sendControlEvent(e); - } -#else - Q_UNUSED(d); + break; + case QEvent::WindowActivate: + case QEvent::WindowDeactivate: + d->control->setPalette(palette()); + break; +#ifndef QT_NO_CONTEXTMENU + case QEvent::ContextMenu: + if (static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) { + ensureCursorVisible(); + const QPoint cursorPos = cursorRect().center(); + QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos)); + ce.setAccepted(e->isAccepted()); + const bool result = QAbstractScrollArea::event(&ce); + e->setAccepted(ce.isAccepted()); + return result; + } + break; #endif // QT_NO_CONTEXTMENU #ifdef QT_KEYPAD_NAVIGATION - if (e->type() == QEvent::EnterEditFocus || e->type() == QEvent::LeaveEditFocus) { + case QEvent::EnterEditFocus: + case QEvent::LeaveEditFocus: if (QApplicationPrivate::keypadNavigationEnabled()) d->sendControlEvent(e); - } + break; #endif + default: + break; + } return QAbstractScrollArea::event(e); } @@ -1477,7 +1500,7 @@ void QTextEdit::resizeEvent(QResizeEvent *e) && alignmentProperty.userType() == QMetaType::Bool && !alignmentProperty.toBool()) { - d->_q_adjustScrollbars(); + d->adjustScrollbars(); return; } } @@ -1486,7 +1509,7 @@ void QTextEdit::resizeEvent(QResizeEvent *e) && e->oldSize().width() != e->size().width()) d->relayoutDocument(); else - d->_q_adjustScrollbars(); + d->adjustScrollbars(); } void QTextEditPrivate::relayoutDocument() @@ -1508,7 +1531,7 @@ void QTextEditPrivate::relayoutDocument() else lastUsedSize = layout->documentSize().toSize(); - // ignore calls to _q_adjustScrollbars caused by an emission of the + // ignore calls to adjustScrollbars caused by an emission of the // usedSizeChanged() signal in the layout, as we're calling it // later on our own anyway (or deliberately not) . const bool oldIgnoreScrollbarAdjustment = ignoreAutomaticScrollbarAdjustment; @@ -1547,7 +1570,7 @@ void QTextEditPrivate::relayoutDocument() // its size. So a layout with less width _can_ take up less vertical space, too. // If the wider case causes a vertical scroll bar to appear and the narrower one // (narrower because the vertical scroll bar takes up horizontal space)) to disappear - // again then we have an endless loop, as _q_adjustScrollBars sets new ranges on the + // again then we have an endless loop, as adjustScrollbars sets new ranges on the // scroll bars, the QAbstractScrollArea will find out about it and try to show/hide // the scroll bars again. That's why we try to detect this case here and break out. // @@ -1560,7 +1583,7 @@ void QTextEditPrivate::relayoutDocument() && usedSize.height() <= viewport->height()) return; - _q_adjustScrollbars(); + adjustScrollbars(); } void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e) @@ -1598,6 +1621,8 @@ void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e) This event handler can be reimplemented in a subclass to receive paint events passed in \a event. It is usually unnecessary to reimplement this function in a subclass of QTextEdit. +\note If you create a QPainter, it must operate on the \l{QAbstractScrollArea::}{viewport()}. + \warning The underlying text document must not be modified from within a reimplementation of this function. */ @@ -1608,12 +1633,6 @@ void QTextEdit::paintEvent(QPaintEvent *e) d->paint(&p, e); } -void QTextEditPrivate::_q_currentCharFormatChanged(const QTextCharFormat &fmt) -{ - Q_Q(QTextEdit); - emit q->currentCharFormatChanged(fmt); -} - void QTextEditPrivate::updateDefaultTextOption() { QTextDocument *doc = control->document(); @@ -1804,7 +1823,7 @@ QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argume Q_D(const QTextEdit); switch (query) { case Qt::ImEnabled: - return isEnabled(); + return isEnabled() && !isReadOnly(); case Qt::ImHints: case Qt::ImInputItemClipRectangle: return QWidget::inputMethodQuery(query); @@ -2209,7 +2228,7 @@ void QTextEdit::insertFromMimeData(const QMimeData *source) bool QTextEdit::isReadOnly() const { Q_D(const QTextEdit); - return !(d->control->textInteractionFlags() & Qt::TextEditable); + return !d->control || !(d->control->textInteractionFlags() & Qt::TextEditable); } void QTextEdit::setReadOnly(bool ro) @@ -2366,7 +2385,7 @@ void QTextEdit::scrollToAnchor(const QString &name) QPointF p = d->control->anchorPosition(name); const int newPosition = qRound(p.y()); if ( d->vbar->maximum() < newPosition ) - d->_q_adjustScrollbars(); + d->adjustScrollbars(); d->vbar->setValue(newPosition); } @@ -2580,11 +2599,14 @@ bool QTextEdit::find(const QString &exp, QTextDocument::FindFlags options) \overload Finds the next occurrence, matching the regular expression, \a exp, using the given - \a options. The QTextDocument::FindCaseSensitively option is ignored for this overload, - use QRegularExpression::CaseInsensitiveOption instead. + \a options. Returns \c true if a match was found and changes the cursor to select the match; otherwise returns \c false. + + \warning For historical reasons, the case sensitivity option set on + \a exp is ignored. Instead, the \a options are used to determine + if the search is case sensitive or not. */ #if QT_CONFIG(regularexpression) bool QTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags options) @@ -2648,10 +2670,7 @@ bool QTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags opt */ void QTextEdit::setText(const QString &text) { - Q_D(QTextEdit); - Qt::TextFormat format = d->textFormat; - if (d->textFormat == Qt::AutoText) - format = Qt::mightBeRichText(text) ? Qt::RichText : Qt::PlainText; + Qt::TextFormat format = Qt::mightBeRichText(text) ? Qt::RichText : Qt::PlainText; #ifndef QT_NO_TEXTHTMLPARSER if (format == Qt::RichText) setHtml(text); |