From f3138e9d533d8db723cf6f325ad8f84902a021f1 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Wed, 21 Jul 2021 16:31:29 +0200 Subject: [PATCH] Sync default action when checking tool button programmatically QAbstractButton::setChecked is not virtual, so QToolButton cannot override to synchronize the default action's checked state. This resulted in button and default action not being in sync when the checked state of the button was changed programmatically, while changing the checked state on the action kept the button in sync. Connect to the button's own toggled signal instead to keep the state of the default action in sync. Make it a unique connection to allow multiple calls to setDefaultAction, which are used by QToolButton to keep the button updated if properties of the default action change. Add a test that confirms that button and action are synchronized both ways, and that we only get single signal emissions when changing either programmatically. Fixes: QTBUG-95255 Change-Id: I0e027faf1da763ef1878e46e85bfa70073c8bf82 Reviewed-by: Mitch Curtis (cherry picked from commit 188d739400e10fc8571bbf2ec86d5cd338b04a5d) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/widgets/qtoolbutton.cpp | 6 ++ .../widgets/qtoolbutton/tst_qtoolbutton.cpp | 59 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp index 1b04f3df72b..81b2998849e 100644 --- a/src/widgets/widgets/qtoolbutton.cpp +++ b/src/widgets/widgets/qtoolbutton.cpp @@ -963,6 +963,12 @@ void QToolButton::setDefaultAction(QAction *action) } #endif setCheckable(action->isCheckable()); + if (action->isCheckable()) { + connect(this, &QAbstractButton::toggled, this, [this](bool checked) { + if (defaultAction()) + defaultAction()->setChecked(checked); + }, Qt::UniqueConnection); + } setChecked(action->isChecked()); setEnabled(action->isEnabled()); if (action->d_func()->fontSet) diff --git a/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp index d6142dfcdcb..12a9ec3de0c 100644 --- a/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp +++ b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp @@ -56,6 +56,7 @@ private slots: void task176137_autoRepeatOfAction(); void qtbug_26956_popupTimerDone(); void qtbug_34759_sizeHintResetWhenSettingMenu(); + void defaultActionSynced(); protected slots: void sendMouseClick(); @@ -280,5 +281,63 @@ void tst_QToolButton::qtbug_34759_sizeHintResetWhenSettingMenu() QTRY_COMPARE(button1.sizeHint(), button2.sizeHint()); } +void tst_QToolButton::defaultActionSynced() +{ + QAction a; + a.setCheckable(true); + + QToolButton tb; + tb.setDefaultAction(&a); + QVERIFY(tb.isCheckable()); + + QSignalSpy tbSpy(&tb, SIGNAL(toggled(bool))); + QSignalSpy aSpy(&a, SIGNAL(toggled(bool))); + + int tbToggledCount = 0; + int aToggledCount = 0; + + tb.setChecked(true); + QVERIFY(a.isChecked()); + QCOMPARE(tbSpy.count(), ++tbToggledCount); + QCOMPARE(aSpy.count(), ++aToggledCount); + tb.setChecked(false); + QVERIFY(!a.isChecked()); + QCOMPARE(tbSpy.count(), ++tbToggledCount); + QCOMPARE(aSpy.count(), ++aToggledCount); + + a.setChecked(true); + QVERIFY(tb.isChecked()); + QCOMPARE(tbSpy.count(), ++tbToggledCount); + QCOMPARE(aSpy.count(), ++aToggledCount); + a.setChecked(false); + QVERIFY(!tb.isChecked()); + QCOMPARE(tbSpy.count(), ++tbToggledCount); + QCOMPARE(aSpy.count(), ++aToggledCount); + + QAction b; + QSignalSpy bSpy(&b, SIGNAL(toggled(bool))); + int bToggledCount = 0; + tb.setDefaultAction(&b); + QVERIFY(!tb.isCheckable()); + b.setCheckable(true); + QVERIFY(tb.isCheckable()); + + tb.setChecked(true); + QVERIFY(!a.isChecked()); + QVERIFY(b.isChecked()); + + QCOMPARE(tbSpy.count(), ++tbToggledCount); + QCOMPARE(aSpy.count(), aToggledCount); + QCOMPARE(bSpy.count(), ++bToggledCount); + + tb.click(); + QVERIFY(!a.isChecked()); + QVERIFY(!tb.isChecked()); + QVERIFY(!b.isChecked()); + QCOMPARE(tbSpy.count(), ++tbToggledCount); + QCOMPARE(aSpy.count(), aToggledCount); + QCOMPARE(bSpy.count(), ++bToggledCount); +} + QTEST_MAIN(tst_QToolButton) #include "tst_qtoolbutton.moc"