summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <[email protected]>2024-02-28 17:48:17 +0100
committerQt Cherry-pick Bot <[email protected]>2024-03-15 05:20:33 +0000
commitf5de357837bc38362642488fe21b321b7e9ea1cc (patch)
treeab56676c4d0b382b8ebc8492a5b90cf4fd5742a5
parent92b32225c2f72481131a58a84fcdcb3bb894e9c8 (diff)
QMessageBox: Respect explicit accept/reject after closing dialog
If the dialog is closed by pressing a button, the button will be reflected via clickedButton(), and the result() will reflect either the QMessageBox::StandardButton value, or an opaque value for custom buttons. Depending on the role if the buttons, the accepted or rejected signals are emitted. If the user called accept() or rejecct() on a dialog that had already been closed by a button, we would as a result of 1f70c073d4325bc0eb9b0cec5156c3b89ce1b4df emit a signal based on the original button that was clicked, instead of respecting the newly triggered function. It's a questionable use-case, as the clickedButton() is still the original button e.g., but we should still avoid regressing this, so we now emit the signals based on the newly stored result code instead of using the clicked button as the source of truth. To allow this we had to change the opaque result() value for custom buttons to stay out of the QDialog::DialogCode enum, but this should be fine as the documentation explicitly says that this is an opaque value. Fixes: QTBUG-118226 Change-Id: Ia2966cecc6694efce66493c401854402658332b4 Reviewed-by: Axel Spoerl <[email protected]> (cherry picked from commit b30121041c07b1b8613eaf624c9aa55a51001aef) Reviewed-by: Qt Cherry-pick Bot <[email protected]> (cherry picked from commit 8a8481f7eb5479df2944f3238d6fac6d8fde5512) (cherry picked from commit 4266bf601cf08ebab89aea11efa84ce71fd41478)
-rw-r--r--src/widgets/dialogs/qmessagebox.cpp28
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp56
2 files changed, 73 insertions, 11 deletions
diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp
index 08cf212af4c..01759275552 100644
--- a/src/widgets/dialogs/qmessagebox.cpp
+++ b/src/widgets/dialogs/qmessagebox.cpp
@@ -440,20 +440,34 @@ static int oldButton(int button)
int QMessageBoxPrivate::execReturnCode(QAbstractButton *button)
{
- int ret = buttonBox->standardButton(button);
- if (ret == QMessageBox::NoButton) {
- ret = customButtonList.indexOf(button); // if button == 0, correctly sets ret = -1
- } else if (compatMode) {
- ret = oldButton(ret);
+ if (int standardButton = buttonBox->standardButton(button)) {
+ // When using a QMessageBox with standard buttons, the return
+ // code is a StandardButton value indicating the standard button
+ // that was clicked.
+ if (compatMode)
+ return oldButton(standardButton);
+ else
+ return standardButton;
+ } else {
+ // When using QMessageBox with custom buttons, the return code
+ // is an opaque value, and the user is expected to use clickedButton()
+ // to determine which button was clicked. We make sure to keep the opaque
+ // value out of the QDialog::DialogCode range, so we can distinguish them.
+ auto customButtonIndex = customButtonList.indexOf(button);
+ if (customButtonIndex >= 0)
+ return QDialog::DialogCode::Accepted + customButtonIndex + 1;
+ else
+ return customButtonIndex; // Not found, return -1
}
- return ret;
}
int QMessageBoxPrivate::dialogCode() const
{
Q_Q(const QMessageBox);
- if (clickedButton) {
+ if (rescode <= QDialog::Accepted) {
+ return rescode;
+ } else if (clickedButton) {
switch (q->buttonRole(clickedButton)) {
case QMessageBox::AcceptRole:
case QMessageBox::YesRole:
diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
index 02e3cfd05a0..158081fa69b 100644
--- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
+++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
@@ -60,6 +60,8 @@ private slots:
void hideNativeByDestruction();
+ void explicitDoneAfterButtonClicked();
+
void cleanup();
};
@@ -435,7 +437,7 @@ void tst_QMessageBox::shortcut()
msgBox.addButton("&Maybe", QMessageBox::YesRole);
ExecCloseHelper closeHelper;
closeHelper.start(Qt::Key_M, &msgBox);
- QCOMPARE(msgBox.exec(), 2);
+ QCOMPARE(msgBox.exec(), 4);
}
#endif
@@ -514,7 +516,7 @@ QT_WARNING_DISABLE_DEPRECATED
// the button text versions
closeHelper.start(Qt::Key_Enter);
ret = QMessageBox::information(nullptr, "title", "text", "Yes", "No", QString(), 1);
- COMPARE(ret, 1);
+ COMPARE(ret, 3); // Custom button opaque result
QVERIFY(closeHelper.done());
if (0) { // don't run these tests since the dialog won't close!
@@ -555,9 +557,9 @@ void tst_QMessageBox::instanceSourceCompat()
#ifndef Q_OS_MAC
// mnemonics are not used on OS X
closeHelper.start(QKeyCombination(Qt::ALT | Qt::Key_R).toCombined(), &mb);
- QCOMPARE(mb.exec(), 0);
+ QCOMPARE(mb.exec(), 2);
closeHelper.start(QKeyCombination(Qt::ALT | Qt::Key_Z).toCombined(), &mb);
- QCOMPARE(mb.exec(), 1);
+ QCOMPARE(mb.exec(), 3);
#endif
}
@@ -818,5 +820,51 @@ void tst_QMessageBox::hideNativeByDestruction()
QVERIFY(QTest::qWaitFor(windowActive));
}
+void tst_QMessageBox::explicitDoneAfterButtonClicked()
+{
+ QMessageBox msgBox;
+ auto *standardButton = msgBox.addButton(QMessageBox::Ok);
+ auto *customButton = msgBox.addButton("Custom", QMessageBox::RejectRole);
+
+ QSignalSpy acceptedSpy(&msgBox, &QDialog::accepted);
+ QSignalSpy rejectedSpy(&msgBox, &QDialog::rejected);
+
+ msgBox.setDefaultButton(standardButton);
+ ExecCloseHelper closeHelper;
+ closeHelper.start(Qt::Key_Enter, &msgBox);
+ msgBox.exec();
+ QCOMPARE(msgBox.clickedButton(), standardButton);
+ QCOMPARE(msgBox.result(), QMessageBox::Ok);
+ QCOMPARE(acceptedSpy.size(), 1);
+ QCOMPARE(rejectedSpy.size(), 0);
+
+ msgBox.accept();
+ QCOMPARE(msgBox.result(), QDialog::Accepted);
+ QCOMPARE(acceptedSpy.size(), 2);
+ QCOMPARE(rejectedSpy.size(), 0);
+ msgBox.reject();
+ QCOMPARE(msgBox.result(), QDialog::Rejected);
+ QCOMPARE(acceptedSpy.size(), 2);
+ QCOMPARE(rejectedSpy.size(), 1);
+
+ msgBox.setDefaultButton(customButton);
+ closeHelper.start(Qt::Key_Enter, &msgBox);
+ msgBox.exec();
+ QCOMPARE(msgBox.clickedButton(), customButton);
+ QVERIFY(msgBox.result() != QDialog::Accepted);
+ QVERIFY(msgBox.result() != QDialog::Rejected);
+ QCOMPARE(acceptedSpy.size(), 2);
+ QCOMPARE(rejectedSpy.size(), 2);
+
+ msgBox.accept();
+ QCOMPARE(msgBox.result(), QDialog::Accepted);
+ QCOMPARE(acceptedSpy.size(), 3);
+ QCOMPARE(rejectedSpy.size(), 2);
+ msgBox.reject();
+ QCOMPARE(msgBox.result(), QDialog::Rejected);
+ QCOMPARE(acceptedSpy.size(), 3);
+ QCOMPARE(rejectedSpy.size(), 3);
+}
+
QTEST_MAIN(tst_QMessageBox)
#include "tst_qmessagebox.moc"