diff --git a/src/widgets/accessible/qaccessiblewidgetfactory.cpp b/src/widgets/accessible/qaccessiblewidgetfactory.cpp index c0a025e0481..01ada3a5c55 100644 --- a/src/widgets/accessible/qaccessiblewidgetfactory.cpp +++ b/src/widgets/accessible/qaccessiblewidgetfactory.cpp @@ -85,7 +85,7 @@ QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *obje } else if (classname == "QDialog"_L1) { iface = new QAccessibleWidget(widget, QAccessible::Dialog); } else if (classname == "QMessageBox"_L1) { - iface = new QAccessibleWidget(widget, QAccessible::AlertMessage); + iface = new QAccessibleMessageBox(widget); #if QT_CONFIG(mainwindow) } else if (classname == "QMainWindow"_L1) { iface = new QAccessibleMainWindow(widget); diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp index f149bad1706..bb0f8401d32 100644 --- a/src/widgets/accessible/simplewidgets.cpp +++ b/src/widgets/accessible/simplewidgets.cpp @@ -43,6 +43,8 @@ #ifndef QT_NO_PICTURE #include #endif +#include +#include #include #include #include @@ -951,6 +953,47 @@ QWindowContainer *QAccessibleWindowContainer::container() const return static_cast(widget()); } +/*! + \internal + Implements QAccessibleWidget for QMessageBox +*/ +QAccessibleMessageBox::QAccessibleMessageBox(QWidget *widget) + : QAccessibleWidget(widget, QAccessible::AlertMessage) +{ + Q_ASSERT(qobject_cast(widget)); +} + +QMessageBox *QAccessibleMessageBox::messageBox() const +{ + return static_cast(widget()); +} + +QString QAccessibleMessageBox::text(QAccessible::Text t) const +{ + QString str; + + switch (t) { + case QAccessible::Name: + str = QAccessibleWidget::text(t); + if (str.isEmpty()) // implies no title text is set + str = messageBox()->text(); + break; + case QAccessible::Description: + str = widget()->accessibleDescription(); + break; + case QAccessible::Value: + str = messageBox()->text(); + break; + case QAccessible::Help: + str = messageBox()->informativeText(); + break; + default: + break; + } + + return str; +} + #endif // QT_CONFIG(accessibility) QT_END_NAMESPACE diff --git a/src/widgets/accessible/simplewidgets_p.h b/src/widgets/accessible/simplewidgets_p.h index 3d0a76c078f..027d3c7bbc2 100644 --- a/src/widgets/accessible/simplewidgets_p.h +++ b/src/widgets/accessible/simplewidgets_p.h @@ -27,6 +27,7 @@ class QAbstractButton; class QLineEdit; class QToolButton; class QGroupBox; +class QMessageBox; class QProgressBar; #if QT_CONFIG(abstractbutton) @@ -189,6 +190,16 @@ private: QWindowContainer *container() const; }; +class QAccessibleMessageBox : public QAccessibleWidget +{ +public: + explicit QAccessibleMessageBox(QWidget *widget); + + QString text(QAccessible::Text t) const override; + + QMessageBox *messageBox() const; +}; + #endif // QT_CONFIG(accessibility) QT_END_NAMESPACE diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 779e5021e1e..de0942ba085 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -21,6 +21,8 @@ #include #include +#include + #if defined(Q_OS_WIN) && defined(interface) # undef interface #endif @@ -219,6 +221,9 @@ private slots: void bridgeTest(); void focusChild(); + void messageBoxTest_data(); + void messageBoxTest(); + protected slots: void onClicked(); private: @@ -4196,6 +4201,105 @@ void tst_QAccessibility::focusChild() } } +void tst_QAccessibility::messageBoxTest_data() +{ + QTest::addColumn("icon"); + QTest::addColumn("buttons"); + QTest::addColumn("title"); + QTest::addColumn("text"); + QTest::addColumn("infoText"); + QTest::addColumn("details"); + QTest::addColumn("checkbox"); + QTest::addColumn("textInteractive"); + + QTest::addRow("Information") << QMessageBox::Information + << QMessageBox::StandardButtons(QMessageBox::Ok) + << "Information" + << "Here, have some information." + << QString() + << QString() + << false + << false; + + QTest::addRow("Warning") << QMessageBox::Warning + << QMessageBox::StandardButtons(QMessageBox::Ok | QMessageBox::Cancel) + << "Warning" + << "This is a dangerous operation!" + << "Ok or Cancel?" + << QString() + << true + << false; + + QTest::addRow("Error") << QMessageBox::Critical + << QMessageBox::StandardButtons(QMessageBox::Abort | QMessageBox::Retry | QMessageBox::Ignore) + << "Error" + << "Operation failed for http://example.com" + << "You have to decide what to do" + << "Detailed log output" + << false + << true; +} + +void tst_QAccessibility::messageBoxTest() +{ + QFETCH(QMessageBox::Icon, icon); + QFETCH(QMessageBox::StandardButtons, buttons); + QFETCH(QString, title); + QFETCH(QString, text); + QFETCH(QString, infoText); + QFETCH(QString, details); + QFETCH(bool, checkbox); + QFETCH(bool, textInteractive); + + QMessageBox box(icon, title, text, buttons); + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box); + QVERIFY(iface); + QCOMPARE(iface->role(), QAccessible::AlertMessage); +#ifndef Q_OS_DARWIN // macOS message boxes show no title + QCOMPARE(iface->text(QAccessible::Name), title); +#endif + QCOMPARE(iface->text(QAccessible::Value), text); + + int expectedChildCount = 3; + QCOMPARE(iface->childCount(), expectedChildCount); + + if (textInteractive) + box.setTextInteractionFlags(Qt::TextBrowserInteraction); + + if (!infoText.isEmpty()) { + box.setInformativeText(infoText); + QCOMPARE(iface->childCount(), ++expectedChildCount); + } + QCOMPARE(iface->text(QAccessible::Help), infoText); + + if (!details.isEmpty()) { + box.setDetailedText(details); + QCOMPARE(iface->childCount(), ++expectedChildCount); + } + if (checkbox) { + box.setCheckBox(new QCheckBox("Don't show again")); + QCOMPARE(iface->childCount(), ++expectedChildCount); + } + + QTestAccessibility::clearEvents(); + + QDialogPrivate *boxPrivate = static_cast(QDialogPrivate::get(&box)); + if (!boxPrivate->canBeNativeDialog()) { + // platforms that use a native message box will not emit accessibility events + box.show(); + + QAccessibleEvent showEvent(&box, QAccessible::DialogStart); + QVERIFY(QTestAccessibility::containsEvent(&showEvent)); + + box.hide(); + + QAccessibleEvent hideEvent(&box, QAccessible::DialogEnd); + QVERIFY(QTestAccessibility::containsEvent(&hideEvent)); + } + + QTestAccessibility::clearEvents(); +} QTEST_MAIN(tst_QAccessibility) #include "tst_qaccessibility.moc"