aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Eftevaag <oliver.eftevaag@qt.io>2023-10-20 07:57:07 +0200
committerOliver Eftevaag <oliver.eftevaag@qt.io>2023-12-10 02:50:58 +0100
commit8dd68783642e6ea42e9a7b32e1671424d1d0eeed (patch)
tree675f318671e177f88bdf2a0fb771ed25925f1714
parent97485da9feb3093f3160de1def206d310415b6c6 (diff)
MessageDialog: make QQuickAbstractDialog::result return button pressed
The widgets QMessageBox returns either the StandardButton value of the last button pressed, or the index, in the case of custom buttons. This differs from how we did things in quick, where we'd always return either 0 or 1 (Accepted or Rejected). The documentation even states the following: MessageDialog sets the result to the value of the clicked standard button instead of using the standard result codes Which was incorrect, since the result property functioned the same, regardless of dialog type. The goal of this patch is to make the result property for MessageDialog behave the same as QMessageBox, without changing the behavior for other dialog types. In order to accomplish this, the type has to be changed from StandardCode to int, since the result value can either be a StandardCode value, or a StandardButton value. The widget QMessageBox also differs in that it will not emit rejected when the user presses a button with a role that isn't NoRole or RejectRole. I've decided to make the MessageDialog behave the same way. [ChangeLog][QtQuick][Dialogs][Important Behavior Changes] The MessageDialog will no longer emit rejected when the user presses a button that doesn't have the role NoRole or RejectedRole. Task-number: QTBUG-118445 Task-number: QTBUG-118689 Task-number: QTBUG-118212 Change-Id: I7084a889210027f5c057f5c22eee2e08867ce741 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
-rw-r--r--src/quickdialogs/quickdialogs/qquickabstractdialog.cpp16
-rw-r--r--src/quickdialogs/quickdialogs/qquickabstractdialog_p.h11
-rw-r--r--src/quickdialogs/quickdialogs/qquickmessagedialog.cpp17
-rw-r--r--src/quickdialogs/quickdialogs/qquickmessagedialog_p.h2
-rw-r--r--src/quickdialogs/quickdialogsquickimpl/qquickmessagedialogimpl.cpp18
-rw-r--r--tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialogWithButtons.qml19
-rw-r--r--tests/auto/quickdialogs/qquickmessagedialogimpl/tst_qquickmessagedialogimpl.cpp97
7 files changed, 153 insertions, 27 deletions
diff --git a/src/quickdialogs/quickdialogs/qquickabstractdialog.cpp b/src/quickdialogs/quickdialogs/qquickabstractdialog.cpp
index 857a75c7bd..f48d223df9 100644
--- a/src/quickdialogs/quickdialogs/qquickabstractdialog.cpp
+++ b/src/quickdialogs/quickdialogs/qquickabstractdialog.cpp
@@ -248,7 +248,7 @@ void QQuickAbstractDialog::setVisible(bool visible)
}
/*!
- \qmlproperty StandardCode QtQuick.Dialogs::Dialog::result
+ \qmlproperty int QtQuick.Dialogs::Dialog::result
This property holds the result code.
@@ -259,12 +259,12 @@ void QQuickAbstractDialog::setVisible(bool visible)
\note MessageDialog sets the result to the value of the clicked standard
button instead of using the standard result codes.
*/
-QQuickAbstractDialog::StandardCode QQuickAbstractDialog::result() const
+int QQuickAbstractDialog::result() const
{
return m_result;
}
-void QQuickAbstractDialog::setResult(StandardCode result)
+void QQuickAbstractDialog::setResult(int result)
{
if (m_result == result)
return;
@@ -312,9 +312,9 @@ void QQuickAbstractDialog::close()
m_visible = false;
emit visibleChanged();
- if (m_result == Accepted)
+ if (dialogCode() == Accepted)
emit accepted();
- else // if (m_result == Rejected)
+ else if (dialogCode() == Rejected)
emit rejected();
}
@@ -343,13 +343,13 @@ void QQuickAbstractDialog::reject()
}
/*!
- \qmlmethod void QtQuick.Dialogs::Dialog::done(StandardCode result)
+ \qmlmethod void QtQuick.Dialogs::Dialog::done(int result)
Closes the dialog and sets the \a result.
\sa accept(), reject(), result
*/
-void QQuickAbstractDialog::done(StandardCode result)
+void QQuickAbstractDialog::done(int result)
{
setResult(result);
close();
@@ -461,6 +461,8 @@ void QQuickAbstractDialog::onHide(QPlatformDialogHelper *dialog)
Q_UNUSED(dialog);
}
+int QQuickAbstractDialog::dialogCode() const { return m_result; }
+
QWindow *QQuickAbstractDialog::findParentWindow() const
{
QObject *obj = parent();
diff --git a/src/quickdialogs/quickdialogs/qquickabstractdialog_p.h b/src/quickdialogs/quickdialogs/qquickabstractdialog_p.h
index 2d9272da6e..a4036d2258 100644
--- a/src/quickdialogs/quickdialogs/qquickabstractdialog_p.h
+++ b/src/quickdialogs/quickdialogs/qquickabstractdialog_p.h
@@ -42,7 +42,7 @@ class Q_QUICKDIALOGS2_PRIVATE_EXPORT QQuickAbstractDialog : public QObject, publ
Q_PROPERTY(Qt::WindowFlags flags READ flags WRITE setFlags NOTIFY flagsChanged FINAL)
Q_PROPERTY(Qt::WindowModality modality READ modality WRITE setModality NOTIFY modalityChanged FINAL)
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL)
- Q_PROPERTY(StandardCode result READ result WRITE setResult NOTIFY resultChanged FINAL)
+ Q_PROPERTY(int result READ result WRITE setResult NOTIFY resultChanged FINAL)
Q_CLASSINFO("DefaultProperty", "data")
Q_MOC_INCLUDE(<QtGui/qwindow.h>)
QML_ANONYMOUS
@@ -74,15 +74,15 @@ public:
enum StandardCode { Rejected, Accepted };
Q_ENUM(StandardCode)
- StandardCode result() const;
- void setResult(StandardCode result);
+ int result() const;
+ void setResult(int result);
public Q_SLOTS:
void open();
void close();
virtual void accept();
virtual void reject();
- virtual void done(StandardCode result);
+ virtual void done(int result);
Q_SIGNALS:
void accepted();
@@ -105,6 +105,7 @@ protected:
virtual void onCreate(QPlatformDialogHelper *dialog);
virtual void onShow(QPlatformDialogHelper *dialog);
virtual void onHide(QPlatformDialogHelper *dialog);
+ virtual int dialogCode() const;
QWindow *findParentWindow() const;
@@ -112,7 +113,7 @@ protected:
bool m_visible = false;
bool m_complete = false;
bool m_firstShow = true;
- StandardCode m_result = Rejected;
+ int m_result = Rejected;
QWindow *m_parentWindow = nullptr;
QString m_title;
Qt::WindowFlags m_flags = Qt::Dialog;
diff --git a/src/quickdialogs/quickdialogs/qquickmessagedialog.cpp b/src/quickdialogs/quickdialogs/qquickmessagedialog.cpp
index 3e71a9ac4c..7e16cfb9dd 100644
--- a/src/quickdialogs/quickdialogs/qquickmessagedialog.cpp
+++ b/src/quickdialogs/quickdialogs/qquickmessagedialog.cpp
@@ -218,8 +218,9 @@ void QQuickMessageDialog::setButtons(QPlatformDialogHelper::StandardButtons butt
void QQuickMessageDialog::handleClick(QPlatformDialogHelper::StandardButton button,
QPlatformDialogHelper::ButtonRole role)
{
+ m_roleOfLastButtonPressed = role;
emit buttonClicked(button, role);
- close();
+ done(button);
}
void QQuickMessageDialog::onCreate(QPlatformDialogHelper *dialog)
@@ -241,6 +242,20 @@ void QQuickMessageDialog::onShow(QPlatformDialogHelper *dialog)
messageDialog->setOptions(m_options); // setOptions only assigns a member and isn't virtual
}
+int QQuickMessageDialog::dialogCode() const
+{
+ switch (m_roleOfLastButtonPressed) {
+ case QPlatformDialogHelper::AcceptRole:
+ case QPlatformDialogHelper::YesRole:
+ return Accepted;
+ case QPlatformDialogHelper::RejectRole:
+ case QPlatformDialogHelper::NoRole:
+ return Rejected;
+ default:
+ return QQuickAbstractDialog::dialogCode();
+ }
+}
+
QT_END_NAMESPACE
#include "moc_qquickmessagedialog_p.cpp"
diff --git a/src/quickdialogs/quickdialogs/qquickmessagedialog_p.h b/src/quickdialogs/quickdialogs/qquickmessagedialog_p.h
index 84840e5d40..edb4f253f4 100644
--- a/src/quickdialogs/quickdialogs/qquickmessagedialog_p.h
+++ b/src/quickdialogs/quickdialogs/qquickmessagedialog_p.h
@@ -63,9 +63,11 @@ private Q_SLOTS:
protected:
void onCreate(QPlatformDialogHelper *dialog) override;
void onShow(QPlatformDialogHelper *dialog) override;
+ int dialogCode() const override;
private:
QSharedPointer<QMessageDialogOptions> m_options;
+ QPlatformDialogHelper::ButtonRole m_roleOfLastButtonPressed = QPlatformDialogHelper::NoRole;
};
QT_END_NAMESPACE
diff --git a/src/quickdialogs/quickdialogsquickimpl/qquickmessagedialogimpl.cpp b/src/quickdialogs/quickdialogsquickimpl/qquickmessagedialogimpl.cpp
index d80011d127..578da61559 100644
--- a/src/quickdialogs/quickdialogsquickimpl/qquickmessagedialogimpl.cpp
+++ b/src/quickdialogs/quickdialogsquickimpl/qquickmessagedialogimpl.cpp
@@ -21,8 +21,6 @@ void QQuickMessageDialogImplPrivate::handleClick(QQuickAbstractButton *button)
emit q->buttonClicked(standardButton, role);
}
-
- QQuickDialogPrivate::handleClick(button);
}
QQuickMessageDialogImplAttached *QQuickMessageDialogImplPrivate::attachedOrWarn()
@@ -125,13 +123,9 @@ void QQuickMessageDialogImplAttached::setButtonBox(QQuickDialogButtonBox *button
QQuickMessageDialogImpl *messageDialogImpl =
qobject_cast<QQuickMessageDialogImpl *>(parent());
if (messageDialogImpl) {
- auto dialogPrivate = QQuickDialogPrivate::get(messageDialogImpl);
- QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::accepted,
- dialogPrivate, &QQuickDialogPrivate::handleAccept);
- QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::rejected,
- dialogPrivate, &QQuickDialogPrivate::handleReject);
+ auto dialogPrivate = QQuickMessageDialogImplPrivate::get(messageDialogImpl);
QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::clicked, dialogPrivate,
- &QQuickDialogPrivate::handleClick);
+ &QQuickMessageDialogImplPrivate::handleClick);
}
}
@@ -141,13 +135,9 @@ void QQuickMessageDialogImplAttached::setButtonBox(QQuickDialogButtonBox *button
QQuickMessageDialogImpl *messageDialogImpl =
qobject_cast<QQuickMessageDialogImpl *>(parent());
if (messageDialogImpl) {
- auto dialogPrivate = QQuickDialogPrivate::get(messageDialogImpl);
- QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::accepted, dialogPrivate,
- &QQuickDialogPrivate::handleAccept);
- QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::rejected, dialogPrivate,
- &QQuickDialogPrivate::handleReject);
+ auto dialogPrivate = QQuickMessageDialogImplPrivate::get(messageDialogImpl);
QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::clicked, dialogPrivate,
- &QQuickDialogPrivate::handleClick);
+ &QQuickMessageDialogImplPrivate::handleClick);
}
}
diff --git a/tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialogWithButtons.qml b/tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialogWithButtons.qml
new file mode 100644
index 0000000000..af3264430b
--- /dev/null
+++ b/tests/auto/quickdialogs/qquickmessagedialogimpl/data/messageDialogWithButtons.qml
@@ -0,0 +1,19 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+
+ApplicationWindow {
+ width: 640
+ height: 480
+
+ property alias dialog: dialog
+
+ MessageDialog {
+ id: dialog
+ objectName: "MessageDialog"
+ buttons: MessageDialog.Yes | MessageDialog.No | MessageDialog.Discard | MessageDialog.Apply
+ }
+}
diff --git a/tests/auto/quickdialogs/qquickmessagedialogimpl/tst_qquickmessagedialogimpl.cpp b/tests/auto/quickdialogs/qquickmessagedialogimpl/tst_qquickmessagedialogimpl.cpp
index b2f3d6456c..4bd9398c74 100644
--- a/tests/auto/quickdialogs/qquickmessagedialogimpl/tst_qquickmessagedialogimpl.cpp
+++ b/tests/auto/quickdialogs/qquickmessagedialogimpl/tst_qquickmessagedialogimpl.cpp
@@ -8,6 +8,7 @@
#include <QtQuickDialogs2QuickImpl/private/qquickmessagedialogimpl_p.h>
#include <QtQuickTest/quicktest.h>
#include <QtQuickControls2/qquickstyle.h>
+#include <QtQuickTemplates2/private/qquickdialog_p_p.h>
#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
#include <QtQuickControlsTestUtils/private/dialogstestutils_p.h>
@@ -39,6 +40,7 @@ private slots:
void changeInformativeText();
void changeStandardButtons();
void detailedText();
+ void resultReflectsLastStandardButtonPressed();
};
// We don't want to fail on warnings until QTBUG-98964 is fixed,
@@ -269,6 +271,101 @@ void tst_QQuickMessageDialogImpl::detailedText()
dialogHelper.dialog->close();
}
+void tst_QQuickMessageDialogImpl::resultReflectsLastStandardButtonPressed()
+{
+ DialogTestHelper<QQuickMessageDialog, QQuickMessageDialogImpl> dialogHelper(
+ this, "messageDialogWithButtons.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ QSignalSpy acceptedSpy(dialogHelper.dialog, SIGNAL(accepted()));
+ QSignalSpy rejectedSpy(dialogHelper.dialog, SIGNAL(rejected()));
+ QSignalSpy resultChangedSpy(dialogHelper.dialog, SIGNAL(resultChanged()));
+
+ auto buttonBox = dialogHelper.quickDialog->findChild<QQuickDialogButtonBox *>("buttonBox");
+ QVERIFY(buttonBox);
+
+ QQuickTest::qWaitForPolish(dialogHelper.window());
+
+ bool yesFound = false;
+ bool noFound = false;
+ bool discardFound = false;
+ bool applyFound = false;
+
+ int expectedNumberOfAcceptedSignals = 0;
+ int expectedNumberOfRejectedSignals = 0;
+
+ // The dialogButtonBox has different layouts depending on platform. This tries to account for all possible layouts.
+ // If the role of a button is YesRole, AcceptRole, NoRole or RejectRole, then pressing that button should emit accepted, or rejected.
+ // And since this is a MessageDialog, the result property should reflect the last button pressed, rather than the StandardCode.
+ for (int i = 0; i < buttonBox->count(); ++i) {
+ auto button = qobject_cast<QQuickAbstractButton *>(buttonBox->itemAt(i));
+ switch (QQuickDialogPrivate::buttonRole(button)) {
+ case QPlatformDialogHelper::YesRole:
+ yesFound = true;
+ expectedNumberOfAcceptedSignals++;
+
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, button->mapToScene({ button->width() / 2, button->height() / 2 }).toPoint());
+ QTRY_VERIFY(!dialogHelper.isQuickDialogOpen());
+
+ QCOMPARE(dialogHelper.dialog->result(), QPlatformDialogHelper::StandardButton::Yes);
+ QCOMPARE(resultChangedSpy.count(), i + 1);
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+ break;
+ case QPlatformDialogHelper::NoRole:
+ noFound = true;
+ expectedNumberOfRejectedSignals++;
+
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, button->mapToScene({ button->width() / 2, button->height() / 2 }).toPoint());
+ QTRY_VERIFY(!dialogHelper.isQuickDialogOpen());
+
+ QCOMPARE(dialogHelper.dialog->result(), QPlatformDialogHelper::StandardButton::No);
+ QCOMPARE(resultChangedSpy.count(), i + 1);
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+ break;
+ case QPlatformDialogHelper::DestructiveRole:
+ discardFound = true;
+
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, button->mapToScene({ button->width() / 2, button->height() / 2 }).toPoint());
+ QTRY_VERIFY(!dialogHelper.isQuickDialogOpen());
+
+ QCOMPARE(dialogHelper.dialog->result(), QPlatformDialogHelper::StandardButton::Discard);
+ QCOMPARE(resultChangedSpy.count(), i + 1);
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+ break;
+ case QPlatformDialogHelper::ApplyRole:
+ applyFound = true;
+
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, button->mapToScene({ button->width() / 2, button->height() / 2 }).toPoint());
+ QTRY_VERIFY(!dialogHelper.isQuickDialogOpen());
+
+ QCOMPARE(dialogHelper.dialog->result(), QPlatformDialogHelper::StandardButton::Apply);
+ QCOMPARE(resultChangedSpy.count(), i + 1);
+
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+ break;
+ default:
+ QFAIL(qPrintable(QStringLiteral("Unexpected role %1").arg(QQuickDialogPrivate::buttonRole(button))));
+ }
+ }
+
+ QVERIFY2(yesFound && noFound && discardFound && applyFound, "A button that was expected to be present, wasn't found when iterating over all of them.");
+ QCOMPARE(acceptedSpy.count(), expectedNumberOfAcceptedSignals);
+ QCOMPARE(rejectedSpy.count(), expectedNumberOfRejectedSignals);
+
+ dialogHelper.dialog->close();
+}
+
QTEST_MAIN(tst_QQuickMessageDialogImpl)
#include "tst_qquickmessagedialogimpl.moc"