summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/dialogs/qdialog.cpp48
-rw-r--r--src/widgets/dialogs/qdialog_p.h3
-rw-r--r--src/widgets/dialogs/qmessagebox.cpp42
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp95
4 files changed, 173 insertions, 15 deletions
diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp
index 6f96018f3e..1fb5e61301 100644
--- a/src/widgets/dialogs/qdialog.cpp
+++ b/src/widgets/dialogs/qdialog.cpp
@@ -145,6 +145,41 @@ bool QDialogPrivate::canBeNativeDialog() const
return false;
}
+/*!
+ \internal
+
+ Properly hides dialog and sets the \p resultCode
+ */
+void QDialogPrivate::hide(int resultCode)
+{
+ Q_Q(QDialog);
+
+ q->setResult(resultCode);
+ q->hide();
+
+ close_helper(QWidgetPrivate::CloseNoEvent);
+ resetModalitySetByOpen();
+}
+
+/*!
+ \internal
+
+ Emits finished() signal with \p resultCode. If the \p dialogCode
+ is equal to 0 emits rejected(), if the \p dialogCode is equal to
+ 1 emits accepted().
+ */
+void QDialogPrivate::finalize(int resultCode, int dialogCode)
+{
+ Q_Q(QDialog);
+
+ if (dialogCode == QDialog::Accepted)
+ emit q->accepted();
+ else if (dialogCode == QDialog::Rejected)
+ emit q->rejected();
+
+ emit q->finished(resultCode);
+}
+
QWindow *QDialogPrivate::transientParentWindow() const
{
Q_Q(const QDialog);
@@ -593,17 +628,8 @@ int QDialog::exec()
void QDialog::done(int r)
{
Q_D(QDialog);
- setResult(r);
- hide();
-
- d->close_helper(QWidgetPrivate::CloseNoEvent);
- d->resetModalitySetByOpen();
-
- emit finished(r);
- if (r == Accepted)
- emit accepted();
- else if (r == Rejected)
- emit rejected();
+ d->hide(r);
+ d->finalize(r, r);
}
/*!
diff --git a/src/widgets/dialogs/qdialog_p.h b/src/widgets/dialogs/qdialog_p.h
index b1de56188c..92634f6793 100644
--- a/src/widgets/dialogs/qdialog_p.h
+++ b/src/widgets/dialogs/qdialog_p.h
@@ -122,6 +122,9 @@ public:
QPlatformDialogHelper *platformHelper() const;
virtual bool canBeNativeDialog() const;
+ void hide(int resultCode);
+ void finalize(int resultCode, int dialogCode);
+
private:
virtual void initHelper(QPlatformDialogHelper *) {}
virtual void helperPrepareShow(QPlatformDialogHelper *) {}
diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp
index ffbbe82856..ce918b8a74 100644
--- a/src/widgets/dialogs/qmessagebox.cpp
+++ b/src/widgets/dialogs/qmessagebox.cpp
@@ -209,6 +209,7 @@ public:
void setupLayout();
void _q_buttonClicked(QAbstractButton *);
void _q_clicked(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole role);
+ void setClickedButton(QAbstractButton *button);
QAbstractButton *findButton(int button0, int button1, int button2, int flags);
void addOldButtons(int button0, int button1, int button2);
@@ -216,6 +217,8 @@ public:
QAbstractButton *abstractButtonForId(int id) const;
int execReturnCode(QAbstractButton *button);
+ int dialogCodeForButton(QAbstractButton *button) const;
+
void detectEscapeButton();
void updateSize();
int layoutMinimumWidth();
@@ -466,6 +469,27 @@ int QMessageBoxPrivate::execReturnCode(QAbstractButton *button)
return ret;
}
+/*!
+ \internal
+
+ Returns 0 for RejectedRole and NoRole, 1 for AcceptedRole and YesRole, -1 otherwise
+ */
+int QMessageBoxPrivate::dialogCodeForButton(QAbstractButton *button) const
+{
+ Q_Q(const QMessageBox);
+
+ switch (q->buttonRole(button)) {
+ case QMessageBox::AcceptRole:
+ case QMessageBox::YesRole:
+ return QDialog::Accepted;
+ case QMessageBox::RejectRole:
+ case QMessageBox::NoRole:
+ return QDialog::Rejected;
+ default:
+ return -1;
+ }
+}
+
void QMessageBoxPrivate::_q_buttonClicked(QAbstractButton *button)
{
Q_Q(QMessageBox);
@@ -477,20 +501,30 @@ void QMessageBoxPrivate::_q_buttonClicked(QAbstractButton *button)
} else
#endif
{
- clickedButton = button;
- q->done(execReturnCode(button)); // does not trigger closeEvent
- emit q->buttonClicked(button);
+ setClickedButton(button);
if (receiverToDisconnectOnClose) {
QObject::disconnect(q, signalToDisconnectOnClose, receiverToDisconnectOnClose,
memberToDisconnectOnClose);
- receiverToDisconnectOnClose = 0;
+ receiverToDisconnectOnClose = nullptr;
}
signalToDisconnectOnClose.clear();
memberToDisconnectOnClose.clear();
}
}
+void QMessageBoxPrivate::setClickedButton(QAbstractButton *button)
+{
+ Q_Q(QMessageBox);
+
+ clickedButton = button;
+ emit q->buttonClicked(clickedButton);
+
+ auto resultCode = execReturnCode(button);
+ hide(resultCode);
+ finalize(resultCode, dialogCodeForButton(button));
+}
+
void QMessageBoxPrivate::_q_clicked(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole role)
{
Q_Q(QMessageBox);
diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
index 3b31a74adf..eeda17074b 100644
--- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
+++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
@@ -110,6 +110,10 @@ private slots:
void setInformativeText();
void iconPixmap();
+ // QTBUG-44131
+ void acceptedRejectedSignals();
+ void acceptedRejectedSignals_data();
+
void cleanup();
};
@@ -717,5 +721,96 @@ void tst_QMessageBox::iconPixmap()
QCOMPARE(messageBox.iconPixmap(), QPixmap());
}
+using SignalSignature = void(QDialog::*)();
+Q_DECLARE_METATYPE(SignalSignature);
+Q_DECLARE_METATYPE(QMessageBox::ButtonRole)
+
+using ButtonsCreator = std::function<QVector<QPushButton*>(QMessageBox &)>;
+Q_DECLARE_METATYPE(ButtonsCreator);
+
+using RoleSet = QSet<QMessageBox::ButtonRole>;
+Q_DECLARE_METATYPE(RoleSet);
+
+void tst_QMessageBox::acceptedRejectedSignals()
+{
+ QMessageBox messageBox(QMessageBox::Information, "Test window", "Test text");
+
+ QFETCH(ButtonsCreator, buttonsCreator);
+ QVERIFY(buttonsCreator);
+
+ const auto buttons = buttonsCreator(messageBox);
+ QVERIFY(!buttons.isEmpty());
+
+ QFETCH(RoleSet, roles);
+ QFETCH(SignalSignature, signalSignature);
+ for (auto button: buttons) {
+ QVERIFY(button);
+
+ messageBox.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&messageBox));
+
+ QSignalSpy spy(&messageBox, signalSignature);
+ QVERIFY(spy.isValid());
+ button->click();
+
+ if (roles.contains(messageBox.buttonRole(button)))
+ QCOMPARE(spy.count(), 1);
+ else
+ QVERIFY(spy.isEmpty());
+ }
+}
+
+static void addAcceptedRow(const char *title, ButtonsCreator bc)
+{
+ QTest::newRow(title) << (RoleSet() << QMessageBox::AcceptRole << QMessageBox::YesRole)
+ << &QDialog::accepted << bc;
+}
+
+static void addRejectedRow(const char *title, ButtonsCreator bc)
+{
+ QTest::newRow(title) << (RoleSet() << QMessageBox::RejectRole << QMessageBox::NoRole)
+ << &QDialog::rejected << bc;
+}
+
+static void addCustomButtonsData()
+{
+ ButtonsCreator buttonsCreator = [](QMessageBox &messageBox) {
+ QVector<QPushButton*> buttons(QMessageBox::NRoles);
+ for (int i = QMessageBox::AcceptRole; i < QMessageBox::NRoles; ++i) {
+ buttons[i] = messageBox.addButton(
+ QString("Button role: %1").arg(i), QMessageBox::ButtonRole(i));
+ }
+
+ return buttons;
+ };
+
+ addAcceptedRow("Accepted_CustomButtons", buttonsCreator);
+ addRejectedRow("Rejected_CustomButtons", buttonsCreator);
+}
+
+static void addStandardButtonsData()
+{
+ ButtonsCreator buttonsCreator = [](QMessageBox &messageBox) {
+ QVector<QPushButton*> buttons;
+ for (int i = QMessageBox::FirstButton; i <= QMessageBox::LastButton; i <<= 1)
+ buttons << messageBox.addButton(QMessageBox::StandardButton(i));
+
+ return buttons;
+ };
+
+ addAcceptedRow("Accepted_StandardButtons", buttonsCreator);
+ addRejectedRow("Rejected_StandardButtons", buttonsCreator);
+}
+
+void tst_QMessageBox::acceptedRejectedSignals_data()
+{
+ QTest::addColumn<RoleSet>("roles");
+ QTest::addColumn<SignalSignature>("signalSignature");
+ QTest::addColumn<ButtonsCreator>("buttonsCreator");
+
+ addStandardButtonsData();
+ addCustomButtonsData();
+}
+
QTEST_MAIN(tst_QMessageBox)
#include "tst_qmessagebox.moc"