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 <m.weghorn@posteo.de>
Reviewed-by: Liang Qi <liang.qi@qt.io>
This commit is contained in:
Axel Spoerl 2023-09-27 22:16:18 +02:00
parent e20328d84f
commit d8e1100548
3 changed files with 124 additions and 118 deletions

View File

@ -48,6 +48,7 @@
#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
#include <array>
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<const QModelIndex &>::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)

View File

@ -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)

View File

@ -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<QMetaObject::Connection, 8> modelConnections;
QAbstractItemModel *model = nullptr;
QLineEdit *lineEdit = nullptr;
QComboBoxPrivateContainer *container = nullptr;