QTextEdit/Browser: use pmf-style connects

Use pmf-style connections instead old string-based ones.

Change-Id: I80b36272e129589b735ec63d23c264b1e3e4bea2
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This commit is contained in:
Christian Ehrlicher 2023-11-05 11:26:32 +01:00
parent d759c5c5ac
commit 597de2b1dc
5 changed files with 77 additions and 65 deletions

View File

@ -46,6 +46,11 @@ public:
, lastKeypadScrollValue(-1) , lastKeypadScrollValue(-1)
#endif #endif
{} {}
~QTextBrowserPrivate()
{
for (const QMetaObject::Connection &connection : connections)
QObject::disconnect(connection);
}
void init(); void init();
@ -103,14 +108,14 @@ public:
QString findFile(const QUrl &name) const; QString findFile(const QUrl &name) const;
inline void _q_documentModified() inline void documentModified()
{ {
textOrSourceChanged = true; textOrSourceChanged = true;
forceLoadOnSourceChange = !currentURL.path().isEmpty(); forceLoadOnSourceChange = !currentURL.path().isEmpty();
} }
void _q_activateAnchor(const QString &href); void activateAnchor(const QString &href);
void _q_highlightLink(const QString &href); void highlightLink(const QString &href);
void setSource(const QUrl &url, QTextDocument::ResourceType type); void setSource(const QUrl &url, QTextDocument::ResourceType type);
@ -129,6 +134,7 @@ public:
Q_Q(QTextBrowser); Q_Q(QTextBrowser);
emit q->highlighted(url); emit q->highlighted(url);
} }
std::array<QMetaObject::Connection, 3> connections;
}; };
Q_DECLARE_TYPEINFO(QTextBrowserPrivate::HistoryEntry, Q_RELOCATABLE_TYPE); Q_DECLARE_TYPEINFO(QTextBrowserPrivate::HistoryEntry, Q_RELOCATABLE_TYPE);
@ -190,7 +196,7 @@ QUrl QTextBrowserPrivate::resolveUrl(const QUrl &url) const
return url; return url;
} }
void QTextBrowserPrivate::_q_activateAnchor(const QString &href) void QTextBrowserPrivate::activateAnchor(const QString &href)
{ {
if (href.isEmpty()) if (href.isEmpty())
return; return;
@ -231,7 +237,7 @@ void QTextBrowserPrivate::_q_activateAnchor(const QString &href)
q->setSource(url); q->setSource(url);
} }
void QTextBrowserPrivate::_q_highlightLink(const QString &anchor) void QTextBrowserPrivate::highlightLink(const QString &anchor)
{ {
if (anchor.isEmpty()) { if (anchor.isEmpty()) {
#ifndef QT_NO_CURSOR #ifndef QT_NO_CURSOR
@ -670,11 +676,14 @@ void QTextBrowserPrivate::init()
q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(q)); q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(q));
q->setUndoRedoEnabled(false); q->setUndoRedoEnabled(false);
viewport->setMouseTracking(true); viewport->setMouseTracking(true);
QObject::connect(q->document(), SIGNAL(contentsChanged()), q, SLOT(_q_documentModified())); connections = {
QObject::connect(control, SIGNAL(linkActivated(QString)), QObjectPrivate::connect(q->document(), &QTextDocument::contentsChanged,
q, SLOT(_q_activateAnchor(QString))); this, &QTextBrowserPrivate::documentModified),
QObject::connect(control, SIGNAL(linkHovered(QString)), QObjectPrivate::connect(control, &QWidgetTextControl::linkActivated,
q, SLOT(_q_highlightLink(QString))); this, &QTextBrowserPrivate::activateAnchor),
QObjectPrivate::connect(control, &QWidgetTextControl::linkHovered,
this, &QTextBrowserPrivate::highlightLink),
};
} }
/*! /*!

View File

@ -82,9 +82,6 @@ protected:
private: private:
Q_DISABLE_COPY(QTextBrowser) Q_DISABLE_COPY(QTextBrowser)
Q_DECLARE_PRIVATE(QTextBrowser) Q_DECLARE_PRIVATE(QTextBrowser)
Q_PRIVATE_SLOT(d_func(), void _q_documentModified())
Q_PRIVATE_SLOT(d_func(), void _q_activateAnchor(const QString &))
Q_PRIVATE_SLOT(d_func(), void _q_highlightLink(const QString &))
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -96,6 +96,12 @@ QTextEditPrivate::QTextEditPrivate()
inDrag = false; inDrag = false;
} }
QTextEditPrivate::~QTextEditPrivate()
{
for (const QMetaObject::Connection &connection : connections)
QObject::disconnect(connection);
}
void QTextEditPrivate::createAutoBulletList() void QTextEditPrivate::createAutoBulletList()
{ {
QTextCursor cursor = control->textCursor(); QTextCursor cursor = control->textCursor();
@ -122,24 +128,34 @@ void QTextEditPrivate::init(const QString &html)
control = new QTextEditControl(q); control = new QTextEditControl(q);
control->setPalette(q->palette()); control->setPalette(q->palette());
QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(updateMicroFocus())); connections = {
QObject::connect(control, SIGNAL(documentSizeChanged(QSizeF)), q, SLOT(_q_adjustScrollbars())); QObjectPrivate::connect(control, &QTextEditControl::documentSizeChanged,
QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(_q_repaintContents(QRectF))); this, &QTextEditPrivate::adjustScrollbars),
QObject::connect(control, SIGNAL(visibilityRequest(QRectF)), q, SLOT(_q_ensureVisible(QRectF))); QObjectPrivate::connect(control, &QTextEditControl::updateRequest,
QObject::connect(control, SIGNAL(currentCharFormatChanged(QTextCharFormat)), this, &QTextEditPrivate::repaintContents),
q, SLOT(_q_currentCharFormatChanged(QTextCharFormat))); QObjectPrivate::connect(control, &QTextEditControl::visibilityRequest,
this, &QTextEditPrivate::ensureVisible),
QObject::connect(control, SIGNAL(textChanged()), q, SIGNAL(textChanged())); QObjectPrivate::connect(control, &QTextEditControl::blockMarkerHovered,
QObject::connect(control, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool))); this, &QTextEditPrivate::hoveredBlockWithMarkerChanged),
QObject::connect(control, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool))); QObjectPrivate::connect(control, &QTextEditControl::cursorPositionChanged,
QObject::connect(control, SIGNAL(copyAvailable(bool)), q, SIGNAL(copyAvailable(bool))); this, &QTextEditPrivate::cursorPositionChanged),
QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged())); QObject::connect(control, &QTextEditControl::microFocusChanged,
QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(_q_cursorPositionChanged())); q, [q]() { q->updateMicroFocus(); }),
#if QT_CONFIG(cursor) QObject::connect(control, &QTextEditControl::currentCharFormatChanged,
QObject::connect(control, SIGNAL(blockMarkerHovered(QTextBlock)), q, SLOT(_q_hoveredBlockWithMarkerChanged(QTextBlock))); q, &QTextEdit::currentCharFormatChanged),
#endif QObject::connect(control, &QTextEditControl::textChanged,
q, &QTextEdit::textChanged),
QObject::connect(control, SIGNAL(textChanged()), q, SLOT(updateMicroFocus())); 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(); QTextDocument *doc = control->document();
// set a null page size initially to avoid any relayouting until the textedit // set a null page size initially to avoid any relayouting until the textedit
@ -169,7 +185,7 @@ void QTextEditPrivate::init(const QString &html)
#endif #endif
} }
void QTextEditPrivate::_q_repaintContents(const QRectF &contentsRect) void QTextEditPrivate::repaintContents(const QRectF &contentsRect)
{ {
if (!contentsRect.isValid()) { if (!contentsRect.isValid()) {
viewport->update(); viewport->update();
@ -187,7 +203,7 @@ void QTextEditPrivate::_q_repaintContents(const QRectF &contentsRect)
viewport->update(r); viewport->update(r);
} }
void QTextEditPrivate::_q_cursorPositionChanged() void QTextEditPrivate::cursorPositionChanged()
{ {
Q_Q(QTextEdit); Q_Q(QTextEdit);
emit q->cursorPositionChanged(); emit q->cursorPositionChanged();
@ -197,9 +213,9 @@ void QTextEditPrivate::_q_cursorPositionChanged()
#endif #endif
} }
#if QT_CONFIG(cursor) void QTextEditPrivate::hoveredBlockWithMarkerChanged(const QTextBlock &block)
void QTextEditPrivate::_q_hoveredBlockWithMarkerChanged(const QTextBlock &block)
{ {
#if QT_CONFIG(cursor)
Q_Q(QTextEdit); Q_Q(QTextEdit);
Qt::CursorShape cursor = cursorToRestoreAfterHover; Qt::CursorShape cursor = cursorToRestoreAfterHover;
if (block.isValid() && !q->isReadOnly()) { if (block.isValid() && !q->isReadOnly()) {
@ -211,8 +227,8 @@ void QTextEditPrivate::_q_hoveredBlockWithMarkerChanged(const QTextBlock &block)
} }
} }
viewport->setCursor(cursor); viewport->setCursor(cursor);
}
#endif #endif
}
void QTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode) void QTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode)
{ {
@ -261,7 +277,7 @@ static QSize documentSize(QWidgetTextControl *control)
return docSize; return docSize;
} }
void QTextEditPrivate::_q_adjustScrollbars() void QTextEditPrivate::adjustScrollbars()
{ {
if (ignoreAutomaticScrollbarAdjustment) if (ignoreAutomaticScrollbarAdjustment)
return; return;
@ -311,12 +327,12 @@ void QTextEditPrivate::_q_adjustScrollbars()
#endif #endif
// rect is in content coordinates // rect is in content coordinates
void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) void QTextEditPrivate::ensureVisible(const QRectF &_rect)
{ {
const QRect rect = _rect.toRect(); const QRect rect = _rect.toRect();
if ((vbar->isVisible() && vbar->maximum() < rect.bottom()) if ((vbar->isVisible() && vbar->maximum() < rect.bottom())
|| (hbar->isVisible() && hbar->maximum() < rect.right())) || (hbar->isVisible() && hbar->maximum() < rect.right()))
_q_adjustScrollbars(); adjustScrollbars();
const int visibleWidth = viewport->width(); const int visibleWidth = viewport->width();
const int visibleHeight = viewport->height(); const int visibleHeight = viewport->height();
const bool rtl = q_func()->isRightToLeft(); const bool rtl = q_func()->isRightToLeft();
@ -1477,7 +1493,7 @@ void QTextEdit::resizeEvent(QResizeEvent *e)
&& alignmentProperty.userType() == QMetaType::Bool && alignmentProperty.userType() == QMetaType::Bool
&& !alignmentProperty.toBool()) { && !alignmentProperty.toBool()) {
d->_q_adjustScrollbars(); d->adjustScrollbars();
return; return;
} }
} }
@ -1486,7 +1502,7 @@ void QTextEdit::resizeEvent(QResizeEvent *e)
&& e->oldSize().width() != e->size().width()) && e->oldSize().width() != e->size().width())
d->relayoutDocument(); d->relayoutDocument();
else else
d->_q_adjustScrollbars(); d->adjustScrollbars();
} }
void QTextEditPrivate::relayoutDocument() void QTextEditPrivate::relayoutDocument()
@ -1508,7 +1524,7 @@ void QTextEditPrivate::relayoutDocument()
else else
lastUsedSize = layout->documentSize().toSize(); 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 // usedSizeChanged() signal in the layout, as we're calling it
// later on our own anyway (or deliberately not) . // later on our own anyway (or deliberately not) .
const bool oldIgnoreScrollbarAdjustment = ignoreAutomaticScrollbarAdjustment; const bool oldIgnoreScrollbarAdjustment = ignoreAutomaticScrollbarAdjustment;
@ -1547,7 +1563,7 @@ void QTextEditPrivate::relayoutDocument()
// its size. So a layout with less width _can_ take up less vertical space, too. // 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 // 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 // (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 // 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. // the scroll bars again. That's why we try to detect this case here and break out.
// //
@ -1560,7 +1576,7 @@ void QTextEditPrivate::relayoutDocument()
&& usedSize.height() <= viewport->height()) && usedSize.height() <= viewport->height())
return; return;
_q_adjustScrollbars(); adjustScrollbars();
} }
void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e) void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e)
@ -1610,12 +1626,6 @@ void QTextEdit::paintEvent(QPaintEvent *e)
d->paint(&p, e); d->paint(&p, e);
} }
void QTextEditPrivate::_q_currentCharFormatChanged(const QTextCharFormat &fmt)
{
Q_Q(QTextEdit);
emit q->currentCharFormatChanged(fmt);
}
void QTextEditPrivate::updateDefaultTextOption() void QTextEditPrivate::updateDefaultTextOption()
{ {
QTextDocument *doc = control->document(); QTextDocument *doc = control->document();
@ -2369,7 +2379,7 @@ void QTextEdit::scrollToAnchor(const QString &name)
QPointF p = d->control->anchorPosition(name); QPointF p = d->control->anchorPosition(name);
const int newPosition = qRound(p.y()); const int newPosition = qRound(p.y());
if ( d->vbar->maximum() < newPosition ) if ( d->vbar->maximum() < newPosition )
d->_q_adjustScrollbars(); d->adjustScrollbars();
d->vbar->setValue(newPosition); d->vbar->setValue(newPosition);
} }

View File

@ -280,14 +280,6 @@ protected:
private: private:
Q_DISABLE_COPY(QTextEdit) Q_DISABLE_COPY(QTextEdit)
Q_PRIVATE_SLOT(d_func(), void _q_repaintContents(const QRectF &r))
Q_PRIVATE_SLOT(d_func(), void _q_currentCharFormatChanged(const QTextCharFormat &))
Q_PRIVATE_SLOT(d_func(), void _q_adjustScrollbars())
Q_PRIVATE_SLOT(d_func(), void _q_ensureVisible(const QRectF &))
Q_PRIVATE_SLOT(d_func(), void _q_cursorPositionChanged())
#if QT_CONFIG(cursor)
Q_PRIVATE_SLOT(d_func(), void _q_hoveredBlockWithMarkerChanged(const QTextBlock &))
#endif
friend class QTextEditControl; friend class QTextEditControl;
friend class QTextDocument; friend class QTextDocument;
friend class QWidgetTextControl; friend class QWidgetTextControl;

View File

@ -33,6 +33,8 @@
#include "private/qwidgettextcontrol_p.h" #include "private/qwidgettextcontrol_p.h"
#include <array>
QT_REQUIRE_CONFIG(textedit); QT_REQUIRE_CONFIG(textedit);
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -43,16 +45,17 @@ class QTextEditPrivate : public QAbstractScrollAreaPrivate
Q_DECLARE_PUBLIC(QTextEdit) Q_DECLARE_PUBLIC(QTextEdit)
public: public:
QTextEditPrivate(); QTextEditPrivate();
~QTextEditPrivate();
void init(const QString &html = QString()); void init(const QString &html = QString());
void paint(QPainter *p, QPaintEvent *e); void paint(QPainter *p, QPaintEvent *e);
void _q_repaintContents(const QRectF &contentsRect); void repaintContents(const QRectF &contentsRect);
inline QPoint mapToContents(const QPoint &point) const inline QPoint mapToContents(const QPoint &point) const
{ return QPoint(point.x() + horizontalOffset(), point.y() + verticalOffset()); } { return QPoint(point.x() + horizontalOffset(), point.y() + verticalOffset()); }
void _q_adjustScrollbars(); void adjustScrollbars();
void _q_ensureVisible(const QRectF &rect); void ensureVisible(const QRectF &rect);
void relayoutDocument(); void relayoutDocument();
void createAutoBulletList(); void createAutoBulletList();
@ -66,9 +69,8 @@ public:
inline void sendControlEvent(QEvent *e) inline void sendControlEvent(QEvent *e)
{ control->processEvent(e, QPointF(horizontalOffset(), verticalOffset()), viewport); } { control->processEvent(e, QPointF(horizontalOffset(), verticalOffset()), viewport); }
void _q_currentCharFormatChanged(const QTextCharFormat &format); void cursorPositionChanged();
void _q_cursorPositionChanged(); void hoveredBlockWithMarkerChanged(const QTextBlock &block);
void _q_hoveredBlockWithMarkerChanged(const QTextBlock &block);
void updateDefaultTextOption(); void updateDefaultTextOption();
@ -100,6 +102,8 @@ public:
Qt::CursorShape cursorToRestoreAfterHover = Qt::IBeamCursor; Qt::CursorShape cursorToRestoreAfterHover = Qt::IBeamCursor;
std::array<QMetaObject::Connection, 13> connections;
#ifdef QT_KEYPAD_NAVIGATION #ifdef QT_KEYPAD_NAVIGATION
QBasicTimer deleteAllTimer; QBasicTimer deleteAllTimer;
#endif #endif