Make hierarchy of actions in menubars more consistent.

There is an assumption that the interface returned from iface->parent()
would have iface as one of its children (thus,
parent->indexOfChild(iface)
should always return an integer != -1, indicating that it is a child.

This is a good assumption, otherwise an hierarchy would be presented
differently depending on how it is traversed.

However, a QMenu created like this:
QMenu *menu = new QMenu("weird parent", mainWindow);
mainWindow->menuBar()->addMenu(menu);

will have a different ancestor sequence than a menu created like this:

mainWindow->menuBar()->addMenu("ok parent");

This is because it will walk up the QObject hierarchy.

This patch tries to deal with that by looking at which widgets the
action of the menu is associated with before determining which should
be the accessible parent.

Change-Id: I00dad8a94463f772d7b1f5d66fdb36b2e8d3aea2
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>
This commit is contained in:
Jan Arve Saether 2012-12-20 16:09:39 +01:00 committed by The Qt Project
parent fb4aef9c70
commit e17dddfd3b
2 changed files with 19 additions and 5 deletions

View File

@ -104,9 +104,16 @@ QAccessibleInterface *QAccessibleMenu::child(int index) const
QAccessibleInterface *QAccessibleMenu::parent() const
{
QWidget *parent = menu()->parentWidget();
if (qobject_cast<QMenu*>(parent) || qobject_cast<QMenuBar*>(parent)) {
return new QAccessibleMenuItem(parent, menu()->menuAction());
if (QAction *menuAction = menu()->menuAction()) {
QList<QWidget *> parentCandidates;
parentCandidates << menu()->parentWidget();
parentCandidates << menuAction->associatedWidgets();
foreach (QWidget *w, parentCandidates) {
if (qobject_cast<QMenu*>(w) || qobject_cast<QMenuBar*>(w)) {
if (w->actions().indexOf(menuAction) != -1)
return new QAccessibleMenuItem(w, menuAction);
}
}
}
return QAccessibleWidget::parent();
}

View File

@ -1265,14 +1265,21 @@ void tst_QAccessibility::menuTest()
mw.menuBar()->addAction("Action!");
QMenu *childOfMainWindow = new QMenu(QStringLiteral("&Tools"), &mw);
childOfMainWindow->addAction("&Options");
mw.menuBar()->addMenu(childOfMainWindow);
mw.show(); // triggers layout
QTest::qWait(100);
QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw.menuBar());
QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&mw);
QCOMPARE(verifyHierarchy(interface), 0);
delete interface;
interface = QAccessible::queryAccessibleInterface(mw.menuBar());
QVERIFY(interface);
QCOMPARE(interface->childCount(), 5);
QCOMPARE(interface->childCount(), 6);
QCOMPARE(interface->role(), QAccessible::MenuBar);
QAccessibleInterface *iFile = interface->child(0);