From d8e110054876b1cbf186e95bac5561a237ee1c13 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Wed, 27 Sep 2023 22:16:18 +0200 Subject: QComboBox: Modernise connect statements Replace string based syntax with PMF. Use QObjectPrivate::connect. Rename _q_ functions. Fix dangling connections in QComboBox d'tor: Completely disconnect model, instead of only disconnecting QObject::destroyed. Task-number: QTBUG-117644 Pick-to: 6.6 6.5 Change-Id: Ie87ac4881029ed1ef2f5c627f631cc54ccb39706 Reviewed-by: Michael Weghorn Reviewed-by: Liang Qi --- src/widgets/widgets/qcombobox.cpp | 194 +++++++++++++++++++++----------------- src/widgets/widgets/qcombobox.h | 15 --- src/widgets/widgets/qcombobox_p.h | 33 ++++--- 3 files changed, 124 insertions(+), 118 deletions(-) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 97e6153b08..c31f682f13 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -48,6 +48,7 @@ #if QT_CONFIG(accessibility) #include "qaccessible.h" #endif +#include QT_BEGIN_NAMESPACE @@ -65,6 +66,7 @@ QComboBoxPrivate::QComboBoxPrivate() QComboBoxPrivate::~QComboBoxPrivate() { + disconnectModel(); #ifdef Q_OS_MAC cleanupNativePopup(); #endif @@ -200,7 +202,7 @@ bool QComboMenuDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, } #if QT_CONFIG(completer) -void QComboBoxPrivate::_q_completerActivated(const QModelIndex &index) +void QComboBoxPrivate::completerActivated(const QModelIndex &index) { Q_Q(QComboBox); #if QT_CONFIG(proxymodel) @@ -240,7 +242,7 @@ void QComboBoxPrivate::updateArrow(QStyle::StateFlag state) q->update(q->rect()); } -void QComboBoxPrivate::_q_modelReset() +void QComboBoxPrivate::modelReset() { Q_Q(QComboBox); if (lineEdit) { @@ -252,7 +254,7 @@ void QComboBoxPrivate::_q_modelReset() q->update(); } -void QComboBoxPrivate::_q_modelDestroyed() +void QComboBoxPrivate::modelDestroyed() { model = QAbstractItemModelPrivate::staticEmptyModel(); } @@ -490,11 +492,13 @@ QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView if (top) { layout->insertWidget(0, top); - connect(top, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int))); + connect(top, &QComboBoxPrivateScroller::doScroll, + this, &QComboBoxPrivateContainer::scrollItemView); } if (bottom) { layout->addWidget(bottom); - connect(bottom, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int))); + connect(bottom, &QComboBoxPrivateScroller::doScroll, + this, &QComboBoxPrivateContainer::scrollItemView); } // Some styles (Mac) have a margin at the top and bottom of the popup. @@ -503,6 +507,12 @@ QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView updateStyleSettings(); } +QComboBoxPrivateContainer::~QComboBoxPrivateContainer() +{ + disconnect(view, &QAbstractItemView::destroyed, + this, &QComboBoxPrivateContainer::viewDestroyed); +} + void QComboBoxPrivateContainer::scrollItemView(int action) { #if QT_CONFIG(scrollbar) @@ -583,13 +593,13 @@ void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView) view->removeEventFilter(this); view->viewport()->removeEventFilter(this); #if QT_CONFIG(scrollbar) - disconnect(view->verticalScrollBar(), SIGNAL(valueChanged(int)), - this, SLOT(updateScrollers())); - disconnect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)), - this, SLOT(updateScrollers())); + disconnect(view->verticalScrollBar(), &QScrollBar::valueChanged, + this, &QComboBoxPrivateContainer::updateScrollers); + disconnect(view->verticalScrollBar(), &QScrollBar::rangeChanged, + this, &QComboBoxPrivateContainer::updateScrollers); #endif - disconnect(view, SIGNAL(destroyed()), - this, SLOT(viewDestroyed())); + disconnect(view, &QAbstractItemView::destroyed, + this, &QComboBoxPrivateContainer::viewDestroyed); if (isAncestorOf(view)) delete view; @@ -620,13 +630,13 @@ void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView) view->setLineWidth(0); view->setEditTriggers(QAbstractItemView::NoEditTriggers); #if QT_CONFIG(scrollbar) - connect(view->verticalScrollBar(), SIGNAL(valueChanged(int)), - this, SLOT(updateScrollers())); - connect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)), - this, SLOT(updateScrollers())); + connect(view->verticalScrollBar(), &QScrollBar::valueChanged, + this, &QComboBoxPrivateContainer::updateScrollers); + connect(view->verticalScrollBar(), &QScrollBar::rangeChanged, + this, &QComboBoxPrivateContainer::updateScrollers); #endif - connect(view, SIGNAL(destroyed()), - this, SLOT(viewDestroyed())); + connect(view, &QAbstractItemView::destroyed, + this, &QComboBoxPrivateContainer::viewDestroyed); } /*! @@ -1041,22 +1051,23 @@ QComboBoxPrivateContainer* QComboBoxPrivate::viewContainer() updateDelegate(true); updateLayoutDirection(); updateViewContainerPaletteAndOpacity(); - QObject::connect(container, SIGNAL(itemSelected(QModelIndex)), - q, SLOT(_q_itemSelected(QModelIndex))); - QObject::connect(container->itemView()->selectionModel(), - SIGNAL(currentChanged(QModelIndex,QModelIndex)), - q, SLOT(_q_emitHighlighted(QModelIndex))); - QObject::connect(container, SIGNAL(resetButton()), q, SLOT(_q_resetButton())); + QObjectPrivate::connect(container, &QComboBoxPrivateContainer::itemSelected, + this, &QComboBoxPrivate::itemSelected); + QObjectPrivate::connect(container->itemView()->selectionModel(), + &QItemSelectionModel::currentChanged, + this, &QComboBoxPrivate::emitHighlighted); + QObjectPrivate::connect(container, &QComboBoxPrivateContainer::resetButton, + this, &QComboBoxPrivate::resetButton); return container; } -void QComboBoxPrivate::_q_resetButton() +void QComboBoxPrivate::resetButton() { updateArrow(QStyle::State_None); } -void QComboBoxPrivate::_q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +void QComboBoxPrivate::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { Q_Q(QComboBox); if (inserting || topLeft.parent() != root) @@ -1084,7 +1095,7 @@ void QComboBoxPrivate::_q_dataChanged(const QModelIndex &topLeft, const QModelIn } } -void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int end) +void QComboBoxPrivate::rowsInserted(const QModelIndex &parent, int start, int end) { Q_Q(QComboBox); if (inserting || parent != root) @@ -1103,16 +1114,16 @@ void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int // need to emit changed if model updated index "silently" } else if (currentIndex.row() != indexBeforeChange) { q->update(); - _q_emitCurrentIndexChanged(currentIndex); + emitCurrentIndexChanged(currentIndex); } } -void QComboBoxPrivate::_q_updateIndexBeforeChange() +void QComboBoxPrivate::updateIndexBeforeChange() { indexBeforeChange = currentIndex.row(); } -void QComboBoxPrivate::_q_rowsRemoved(const QModelIndex &parent, int /*start*/, int /*end*/) +void QComboBoxPrivate::rowsRemoved(const QModelIndex &parent, int /*start*/, int /*end*/) { Q_Q(QComboBox); if (parent != root) @@ -1141,7 +1152,7 @@ void QComboBoxPrivate::_q_rowsRemoved(const QModelIndex &parent, int /*start*/, updateLineEditGeometry(); } q->update(); - _q_emitCurrentIndexChanged(currentIndex); + emitCurrentIndexChanged(currentIndex); } } @@ -1250,7 +1261,7 @@ Qt::MatchFlags QComboBoxPrivate::matchFlags() const } -void QComboBoxPrivate::_q_editingFinished() +void QComboBoxPrivate::editingFinished() { Q_Q(QComboBox); if (!lineEdit) @@ -1282,13 +1293,13 @@ void QComboBoxPrivate::_q_editingFinished() } -void QComboBoxPrivate::_q_returnPressed() +void QComboBoxPrivate::returnPressed() { Q_Q(QComboBox); // The insertion code below does not apply when the policy is QComboBox::NoInsert. // In case a completer is installed, item activation via the completer is handled - // in _q_completerActivated(). Otherwise _q_editingFinished() updates the current + // in completerActivated(). Otherwise editingFinished() updates the current // index as appropriate. if (insertPolicy == QComboBox::NoInsert) return; @@ -1346,7 +1357,7 @@ void QComboBoxPrivate::_q_returnPressed() } } -void QComboBoxPrivate::_q_itemSelected(const QModelIndex &item) +void QComboBoxPrivate::itemSelected(const QModelIndex &item) { Q_Q(QComboBox); if (item != currentIndex) { @@ -1368,7 +1379,7 @@ void QComboBoxPrivate::emitActivated(const QModelIndex &index) emit q->textActivated(text); } -void QComboBoxPrivate::_q_emitHighlighted(const QModelIndex &index) +void QComboBoxPrivate::emitHighlighted(const QModelIndex &index) { Q_Q(QComboBox); if (!index.isValid()) @@ -1378,7 +1389,7 @@ void QComboBoxPrivate::_q_emitHighlighted(const QModelIndex &index) emit q->textHighlighted(text); } -void QComboBoxPrivate::_q_emitCurrentIndexChanged(const QModelIndex &index) +void QComboBoxPrivate::emitCurrentIndexChanged(const QModelIndex &index) { Q_Q(QComboBox); const QString text = itemText(index); @@ -1411,8 +1422,7 @@ QComboBox::~QComboBox() Q_D(QComboBox); QT_TRY { - disconnect(d->model, SIGNAL(destroyed()), - this, SLOT(_q_modelDestroyed())); + d->disconnectModel(); } QT_CATCH(...) { ; // objects can't throw in destructor } @@ -1801,13 +1811,18 @@ void QComboBox::setLineEdit(QLineEdit *edit) #endif if (d->lineEdit->parent() != this) d->lineEdit->setParent(this); - connect(d->lineEdit, SIGNAL(returnPressed()), this, SLOT(_q_returnPressed())); - connect(d->lineEdit, SIGNAL(editingFinished()), this, SLOT(_q_editingFinished())); - connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(editTextChanged(QString))); - connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(currentTextChanged(QString))); - connect(d->lineEdit, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(updateMicroFocus())); - connect(d->lineEdit, SIGNAL(selectionChanged()), this, SLOT(updateMicroFocus())); - connect(d->lineEdit->d_func()->control, SIGNAL(updateMicroFocus()), this, SLOT(updateMicroFocus())); + QObjectPrivate::connect(d->lineEdit, &QLineEdit::returnPressed, + d, &QComboBoxPrivate::returnPressed); + QObjectPrivate::connect(d->lineEdit, &QLineEdit::editingFinished, + d, &QComboBoxPrivate::editingFinished); + connect(d->lineEdit, &QLineEdit::textChanged, this, &QComboBox::editTextChanged); + connect(d->lineEdit, &QLineEdit::textChanged, this, &QComboBox::currentTextChanged); + QObjectPrivate::connect(d->lineEdit, &QLineEdit::cursorPositionChanged, + d, &QComboBoxPrivate::updateMicroFocus); + QObjectPrivate::connect(d->lineEdit, &QLineEdit::selectionChanged, + d, &QComboBoxPrivate::updateMicroFocus); + QObjectPrivate::connect(d->lineEdit->d_func()->control, &QWidgetLineControl::updateMicroFocus, + d, &QComboBoxPrivate::updateMicroFocus); d->lineEdit->setFrame(false); d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu); d->updateFocusPolicy(); @@ -1909,7 +1924,8 @@ void QComboBox::setCompleter(QCompleter *c) } d->lineEdit->setCompleter(c); if (c) { - connect(c, SIGNAL(activated(QModelIndex)), this, SLOT(_q_completerActivated(QModelIndex))); + QObjectPrivate::connect(c, QOverload::of(&QCompleter::activated), + d, &QComboBoxPrivate::completerActivated); c->setWidget(this); } } @@ -2003,51 +2019,20 @@ void QComboBox::setModel(QAbstractItemModel *model) if (d->lineEdit && d->lineEdit->completer()) d->lineEdit->completer()->setModel(model); #endif - if (d->model) { - disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(_q_dataChanged(QModelIndex,QModelIndex))); - disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_updateIndexBeforeChange())); - disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(_q_rowsInserted(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_updateIndexBeforeChange())); - disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_rowsRemoved(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(destroyed()), - this, SLOT(_q_modelDestroyed())); - disconnect(d->model, SIGNAL(modelAboutToBeReset()), - this, SLOT(_q_updateIndexBeforeChange())); - disconnect(d->model, SIGNAL(modelReset()), - this, SLOT(_q_modelReset())); - if (d->model->QObject::parent() == this) - delete d->model; + d->disconnectModel(); + if (d->model && d->model->QObject::parent() == this) { + delete d->model; + d->model = nullptr; } d->model = model; - - connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(_q_dataChanged(QModelIndex,QModelIndex))); - connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_updateIndexBeforeChange())); - connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(_q_rowsInserted(QModelIndex,int,int))); - connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_updateIndexBeforeChange())); - connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_rowsRemoved(QModelIndex,int,int))); - connect(model, SIGNAL(destroyed()), - this, SLOT(_q_modelDestroyed())); - connect(model, SIGNAL(modelAboutToBeReset()), - this, SLOT(_q_updateIndexBeforeChange())); - connect(model, SIGNAL(modelReset()), - this, SLOT(_q_modelReset())); + d->connectModel(); if (d->container) { d->container->itemView()->setModel(model); - connect(d->container->itemView()->selectionModel(), - SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(_q_emitHighlighted(QModelIndex)), Qt::UniqueConnection); + QObjectPrivate::connect(d->container->itemView()->selectionModel(), + &QItemSelectionModel::currentChanged, + d, &QComboBoxPrivate::emitHighlighted, Qt::UniqueConnection); } setRootModelIndex(QModelIndex()); @@ -2056,6 +2041,37 @@ void QComboBox::setModel(QAbstractItemModel *model) d->modelChanged(); } +void QComboBoxPrivate::connectModel() +{ + if (!model) + return; + + modelConnections = { + QObjectPrivate::connect(model, &QAbstractItemModel::dataChanged, + this, &QComboBoxPrivate::dataChanged), + QObjectPrivate::connect(model, &QAbstractItemModel::rowsAboutToBeInserted, + this, &QComboBoxPrivate::updateIndexBeforeChange), + QObjectPrivate::connect(model, &QAbstractItemModel::rowsInserted, + this, &QComboBoxPrivate::rowsInserted), + QObjectPrivate::connect(model, &QAbstractItemModel::rowsAboutToBeRemoved, + this, &QComboBoxPrivate::updateIndexBeforeChange), + QObjectPrivate::connect(model, &QAbstractItemModel::rowsRemoved, + this, &QComboBoxPrivate::rowsRemoved), + QObjectPrivate::connect(model, &QObject::destroyed, + this, &QComboBoxPrivate::modelDestroyed), + QObjectPrivate::connect(model, &QAbstractItemModel::modelAboutToBeReset, + this, &QComboBoxPrivate::updateIndexBeforeChange), + QObjectPrivate::connect(model, &QAbstractItemModel::modelReset, + this, &QComboBoxPrivate::modelReset) + }; +} + +void QComboBoxPrivate::disconnectModel() +{ + for (auto &connection : modelConnections) + QObject::disconnect(connection); +} + /*! Returns the root model item index for the items in the combobox. @@ -2149,7 +2165,7 @@ void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi) if (indexChanged || modelResetToEmpty) { q->update(); - _q_emitCurrentIndexChanged(currentIndex); + emitCurrentIndexChanged(currentIndex); } } @@ -2278,7 +2294,7 @@ void QComboBox::insertItem(int index, const QIcon &icon, const QString &text, co if (!values.isEmpty()) d->model->setItemData(item, values); } d->inserting = false; - d->_q_rowsInserted(d->root, index, index); + d->rowsInserted(d->root, index, index); ++itemCount; } else { d->inserting = false; @@ -2326,7 +2342,7 @@ void QComboBox::insertItems(int index, const QStringList &list) d->model->setData(item, list.at(i), Qt::EditRole); } d->inserting = false; - d->_q_rowsInserted(d->root, index, index + insertCount - 1); + d->rowsInserted(d->root, index, index + insertCount - 1); } else { d->inserting = false; } @@ -2858,7 +2874,7 @@ void QComboBoxPrivate::doHidePopup() if (container && container->isVisible()) container->hide(); - _q_resetButton(); + resetButton(); } void QComboBoxPrivate::updateCurrentText(const QString &text) diff --git a/src/widgets/widgets/qcombobox.h b/src/widgets/widgets/qcombobox.h index be28ce7173..1689d0fa1e 100644 --- a/src/widgets/widgets/qcombobox.h +++ b/src/widgets/widgets/qcombobox.h @@ -204,21 +204,6 @@ protected: private: Q_DECLARE_PRIVATE(QComboBox) Q_DISABLE_COPY(QComboBox) - Q_PRIVATE_SLOT(d_func(), void _q_itemSelected(const QModelIndex &item)) - Q_PRIVATE_SLOT(d_func(), void _q_emitHighlighted(const QModelIndex &)) - Q_PRIVATE_SLOT(d_func(), void _q_emitCurrentIndexChanged(const QModelIndex &index)) - Q_PRIVATE_SLOT(d_func(), void _q_editingFinished()) - Q_PRIVATE_SLOT(d_func(), void _q_returnPressed()) - Q_PRIVATE_SLOT(d_func(), void _q_resetButton()) - Q_PRIVATE_SLOT(d_func(), void _q_dataChanged(const QModelIndex &, const QModelIndex &)) - Q_PRIVATE_SLOT(d_func(), void _q_updateIndexBeforeChange()) - Q_PRIVATE_SLOT(d_func(), void _q_rowsInserted(const QModelIndex & parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(const QModelIndex & parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed()) - Q_PRIVATE_SLOT(d_func(), void _q_modelReset()) -#if QT_CONFIG(completer) - Q_PRIVATE_SLOT(d_func(), void _q_completerActivated(const QModelIndex &index)) -#endif }; inline void QComboBox::addItem(const QString &atext, const QVariant &auserData) diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h index e094b29a1f..6ea0065d8c 100644 --- a/src/widgets/widgets/qcombobox_p.h +++ b/src/widgets/widgets/qcombobox_p.h @@ -183,6 +183,7 @@ class Q_WIDGETS_EXPORT QComboBoxPrivateContainer : public QFrame public: QComboBoxPrivateContainer(QAbstractItemView *itemView, QComboBox *parent); + ~QComboBoxPrivateContainer(); QAbstractItemView *itemView() const; void setItemView(QAbstractItemView *itemView); int spacing() const; @@ -318,24 +319,25 @@ public: QComboBoxPrivateContainer* viewContainer(); void updateLineEditGeometry(); Qt::MatchFlags matchFlags() const; - void _q_editingFinished(); - void _q_returnPressed(); - void _q_complete(); - void _q_itemSelected(const QModelIndex &item); + void editingFinished(); + void returnPressed(); + void complete(); + void itemSelected(const QModelIndex &item); bool contains(const QString &text, int role); void emitActivated(const QModelIndex &index); - void _q_emitHighlighted(const QModelIndex &index); - void _q_emitCurrentIndexChanged(const QModelIndex &index); - void _q_modelDestroyed(); - void _q_modelReset(); + void emitHighlighted(const QModelIndex &index); + void emitCurrentIndexChanged(const QModelIndex &index); + void modelDestroyed(); + void modelReset(); + void updateMicroFocus() { q_func()->updateMicroFocus(); } // PMF connect doesn't handle default args #if QT_CONFIG(completer) - void _q_completerActivated(const QModelIndex &index); + void completerActivated(const QModelIndex &index); #endif - void _q_resetButton(); - void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - void _q_updateIndexBeforeChange(); - void _q_rowsInserted(const QModelIndex &parent, int start, int end); - void _q_rowsRemoved(const QModelIndex &parent, int start, int end); + void resetButton(); + void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void updateIndexBeforeChange(); + void rowsInserted(const QModelIndex &parent, int start, int end); + void rowsRemoved(const QModelIndex &parent, int start, int end); void updateArrow(QStyle::StateFlag state); bool updateHoverControl(const QPoint &pos); void trySetValidIndex(); @@ -357,6 +359,8 @@ public: void showPopupFromMouseEvent(QMouseEvent *e); void doHidePopup(); void updateCurrentText(const QString &text); + void connectModel(); + void disconnectModel(); #ifdef Q_OS_MAC void cleanupNativePopup(); @@ -373,6 +377,7 @@ public: }; #endif + std::array modelConnections; QAbstractItemModel *model = nullptr; QLineEdit *lineEdit = nullptr; QComboBoxPrivateContainer *container = nullptr; -- cgit v1.2.3