summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Weghorn <[email protected]>2024-07-15 16:53:58 +0200
committerMichael Weghorn <[email protected]>2024-07-19 07:37:16 +0200
commitb8b7c58402740204da72e1b1f4ea7321b7bfa540 (patch)
tree16abcedc50c2a89c790283f2eea5cd7cb1c3e247
parent59133b16cd3adffc70833bb2b81332c9649fa51e (diff)
a11y: Add property for QWidget's accessible ID
9ec1de2528b871099d416d15592fcc5ef9242a64 added an Identifier role to QAccessible that can be used to provide an identfier for reliable identification by assistive technologies, e.g. in automated tests. As discussed in that commit's Gerrit change, add a corresponding accessibleIdentifier property to QWidget to allow easily setting a specific identifier for widgets, in the same way that an accessible name or description can be set. This provides more flexibility than the default logic that generates an identifier to be used in platform bridges that is based on the object or class names of the objects in the widget's subtree. (The only alternative so far to set a particular ID not including the "object path" would have been to provide a custom QAccessibleInterface implementation with a corresponding QAccessibleInterface::text implementation.) Add an autotest testing both, the default platform bridge logic and that the the newly added property overrides that. [ChangeLog][QtWidgets][QWidget] Add an accessibleId property that allows to easily set a particular accessible identifier for QWidgets that can be used by assistive technologies to identify the widget. Change-Id: If24e138c7d8fe4c78f25d3f0629a9520c352bacc Reviewed-by: Volker Hilsheimer <[email protected]>
-rw-r--r--src/widgets/accessible/qaccessiblewidget.cpp3
-rw-r--r--src/widgets/kernel/qwidget.cpp26
-rw-r--r--src/widgets/kernel/qwidget.h3
-rw-r--r--src/widgets/kernel/qwidget_p.h1
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp29
5 files changed, 62 insertions, 0 deletions
diff --git a/src/widgets/accessible/qaccessiblewidget.cpp b/src/widgets/accessible/qaccessiblewidget.cpp
index b0bb12ea86a..df1c8994567 100644
--- a/src/widgets/accessible/qaccessiblewidget.cpp
+++ b/src/widgets/accessible/qaccessiblewidget.cpp
@@ -383,6 +383,9 @@ QString QAccessibleWidget::text(QAccessible::Text t) const
str = widget()->toolTip();
#endif
break;
+ case QAccessible::Identifier:
+ str = widget()->accessibleIdentifier();
+ break;
case QAccessible::Help:
#if QT_CONFIG(whatsthis)
str = widget()->whatsThis();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 514a2f21d5a..afa3438b682 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -11841,6 +11841,32 @@ QString QWidget::accessibleDescription() const
Q_D(const QWidget);
return d->accessibleDescription;
}
+
+/*!
+ \property QWidget::accessibleIdentifier
+
+ \brief the widget's identifier as seen by assistive technologies
+
+ If set, the accessible identifier of a widget can be used by assistive
+ technologies in order to identify a specific widget, e.g. in automated
+ tests.
+
+ \since 6.9
+*/
+void QWidget::setAccessibleIdentifier(const QString &identifier)
+{
+ Q_D(QWidget);
+ d->accessibleIdentifier = identifier;
+ QAccessibleEvent event(this, QAccessible::IdentifierChanged);
+ QAccessible::updateAccessibility(&event);
+}
+
+QString QWidget::accessibleIdentifier() const
+{
+ Q_D(const QWidget);
+ return d->accessibleIdentifier;
+}
+
#endif // QT_CONFIG(accessibility)
#ifndef QT_NO_SHORTCUT
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
index e5e83a43f2e..7ee4412d881 100644
--- a/src/widgets/kernel/qwidget.h
+++ b/src/widgets/kernel/qwidget.h
@@ -166,6 +166,7 @@ class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice
#if QT_CONFIG(accessibility)
Q_PROPERTY(QString accessibleName READ accessibleName WRITE setAccessibleName)
Q_PROPERTY(QString accessibleDescription READ accessibleDescription WRITE setAccessibleDescription)
+ Q_PROPERTY(QString accessibleIdentifier READ accessibleIdentifier WRITE setAccessibleIdentifier)
#endif
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
QDOC_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
@@ -406,6 +407,8 @@ public:
void setAccessibleName(const QString &name);
QString accessibleDescription() const;
void setAccessibleDescription(const QString &description);
+ QString accessibleIdentifier() const;
+ void setAccessibleIdentifier(const QString &identifier);
#endif
void setLayoutDirection(Qt::LayoutDirection direction);
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index b27ffdb1be6..f02aa3f9d2b 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -683,6 +683,7 @@ public:
#if QT_CONFIG(accessibility)
QString accessibleName;
QString accessibleDescription;
+ QString accessibleIdentifier;
#endif
// Other variables.
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index e1452282042..5eb331b9300 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -20,6 +20,7 @@
#ifdef Q_OS_WIN
#include <QtCore/private/qfunctions_win_p.h>
#endif
+#include <QtGui/private/qaccessiblebridgeutils_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
@@ -221,6 +222,7 @@ private slots:
void dockWidgetTest();
void comboBoxTest();
void accessibleName();
+ void accessibleIdentifier();
#if QT_CONFIG(shortcut)
void labelTest();
void relationTest();
@@ -644,6 +646,33 @@ void tst_QAccessibility::accessibleName()
QTestAccessibility::clearEvents();
}
+void tst_QAccessibility::accessibleIdentifier()
+{
+ const QString objectName("button_objectname");
+ const QString id("mybutton");
+
+ QMainWindow mainWindow;
+ QPushButton button("a button", &mainWindow);
+ button.setObjectName(objectName);
+ mainWindow.show();
+
+ // verify that default implementation for platform bridges generates
+ // an accessible ID that's based on (i.e. somehow contains) the object name
+ QAccessibleInterface* accessible = QAccessible::queryAccessibleInterface(&button);
+ QVERIFY(QAccessibleBridgeUtils::accessibleId(accessible).contains(objectName));
+
+ // explicitly set an accessible ID, verify event and that the ID is set to
+ // that exact string (not only containing it) afterwards
+ QTestAccessibility::clearEvents();
+ button.setAccessibleIdentifier(id);
+ QAccessibleEvent event(&button, QAccessible::IdentifierChanged);
+ QVERIFY(QTestAccessibility::containsEvent(&event));
+ QCOMPARE(button.accessibleIdentifier(), id);
+ QCOMPARE(QAccessibleBridgeUtils::accessibleId(accessible), id);
+
+ QTestAccessibility::clearEvents();
+}
+
// note: color should probably always be part of the attributes
void tst_QAccessibility::textAttributes_data()
{