diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp index ee4825d3e5..046acfeea9 100644 --- a/src/widgets/widgets/qlabel.cpp +++ b/src/widgets/widgets/qlabel.cpp @@ -963,7 +963,9 @@ bool QLabel::event(QEvent *e) if (type == QEvent::Shortcut) { QShortcutEvent *se = static_cast(e); if (se->shortcutId() == d->shortcutId) { - QWidget * w = d->buddy; + QWidget *w = d->buddy; + if (!w) + return QFrame::event(e); if (w->focusPolicy() != Qt::NoFocus) w->setFocus(Qt::ShortcutFocusReason); #if QT_CONFIG(abstractbutton) @@ -1163,7 +1165,15 @@ void QLabelPrivate::updateLabel() void QLabel::setBuddy(QWidget *buddy) { Q_D(QLabel); + + if (d->buddy) + disconnect(d->buddy, SIGNAL(destroyed()), this, SLOT(_q_buddyDeleted())); + d->buddy = buddy; + + if (buddy) + connect(buddy, SIGNAL(destroyed()), this, SLOT(_q_buddyDeleted())); + if (d->isTextLabel) { if (d->shortcutId) releaseShortcut(d->shortcutId); @@ -1204,6 +1214,13 @@ void QLabelPrivate::updateShortcut() shortcutId = q->grabShortcut(QKeySequence::mnemonic(text)); } + +void QLabelPrivate::_q_buddyDeleted() +{ + Q_Q(QLabel); + q->setBuddy(nullptr); +} + #endif // QT_NO_SHORTCUT #if QT_CONFIG(movie) diff --git a/src/widgets/widgets/qlabel.h b/src/widgets/widgets/qlabel.h index e1cc333a1c..2f5db5a7d3 100644 --- a/src/widgets/widgets/qlabel.h +++ b/src/widgets/widgets/qlabel.h @@ -158,6 +158,9 @@ private: #endif Q_PRIVATE_SLOT(d_func(), void _q_linkHovered(const QString &)) +#ifndef QT_NO_SHORTCUT + Q_PRIVATE_SLOT(d_func(), void _q_buddyDeleted()) +#endif friend class QTipLabel; friend class QMessageBoxPrivate; friend class QBalloonTip; diff --git a/src/widgets/widgets/qlabel_p.h b/src/widgets/widgets/qlabel_p.h index e05a5b5c35..59188563a9 100644 --- a/src/widgets/widgets/qlabel_p.h +++ b/src/widgets/widgets/qlabel_p.h @@ -89,6 +89,7 @@ public: #endif #ifndef QT_NO_SHORTCUT void updateShortcut(); + void _q_buddyDeleted(); #endif inline bool needTextControl() const { return isTextLabel diff --git a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp index 500ec2e1fa..84071962bc 100644 --- a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp +++ b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp @@ -178,9 +178,11 @@ void tst_QLabel::setBuddy() test_label= new QLabel( test_box ); test_label->setText( "&Test with a buddy" ); QWidget *test_edit = new QLineEdit( test_box ); + QWidget *test_edit2 = new QLineEdit( test_box ); QVBoxLayout *layout = new QVBoxLayout(test_box); layout->addWidget(test_label); layout->addWidget(test_edit); + layout->addWidget(test_edit2); test_box->show(); qApp->setActiveWindow(test_box); QVERIFY(test_box->isActiveWindow()); @@ -190,6 +192,16 @@ void tst_QLabel::setBuddy() QVERIFY( !test_edit->hasFocus() ); QTest::keyClick( test_box, 't', Qt::AltModifier ); QVERIFY( test_edit->hasFocus() ); + + // Setting a new buddy should disconnect the old one's destroyed() signal + test_label->setBuddy(test_edit2); + delete test_edit; + QCOMPARE(test_label->buddy(), test_edit2); + + // And deleting our own buddy should disconnect and not crash + delete test_edit2; + QTest::keyClick(test_box, 't', Qt::AltModifier ); + delete test_box; } #endif