Only instantiate QAccessibleWidget after trying inherited classes

The plugin should try each class name from the meta object
in succession instead of giving up right away and just using
QWidget.

This improves the handling of the itemviews and makes many sub-classes
of QWidget outside of Qt work.

Change-Id: Id81017c648fe229c3eb85d6d9ae6696d5f16a1ef
Reviewed-by: Jan Arve Sæther <jan-arve.saether@digia.com>
bb10
Frederik Gladhorn 2013-03-18 16:02:06 +01:00 committed by The Qt Project
parent f4609b2022
commit 4e07286a30
3 changed files with 106 additions and 51 deletions

View File

@ -172,12 +172,11 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec
iface = new QAccessibleMenu(widget);
#endif
#ifndef QT_NO_ITEMVIEWS
} else if (classname == QLatin1String("QAbstractItemView")) {
if (qobject_cast<const QTreeView*>(widget)) {
iface = new QAccessibleTree(widget);
} else {
iface = new QAccessibleTable(widget);
}
} else if (classname == QLatin1String("QTreeView")) {
iface = new QAccessibleTree(widget);
} else if (classname == QLatin1String("QTableView") || classname == QLatin1String("QListView")) {
iface = new QAccessibleTable(widget);
// ### This should be cleaned up. We return the parent for the scrollarea to hide it.
} else if (classname == QLatin1String("QWidget")
&& widget->objectName() == QLatin1String("qt_scrollarea_viewport")
&& qobject_cast<QAbstractItemView*>(widget->parentWidget())) {
@ -254,7 +253,7 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec
} else if (classname == QLatin1String("QDesktopScreenWidget")) {
iface = 0;
} else {
} else if (classname == QLatin1String("QWidget")) {
iface = new QAccessibleWidget(widget);
}

View File

@ -24,11 +24,12 @@
"QPlainTextEdit",
"QMenuBar",
"QMenu",
"QHeaderView",
"QTabBar",
"QToolBar",
"QSizeGrip",
"QAbstractItemView",
"QListView",
"QTreeView",
"QTableView",
"QWidget",
"QSplitter",
"QSplitterHandle",
@ -47,7 +48,6 @@
"QScrollArea",
"QCalendarWidget",
"QDockWidget",
"QAccessibleWidget",
"QDesktopScreenWidget"
]
}

View File

@ -236,6 +236,7 @@ private slots:
void eventTest();
void customWidget();
void deletedWidget();
void subclassedWidget();
void statesStructTest();
void navigateHierarchy();
@ -294,38 +295,6 @@ QAccessible::State state(QWidget * const widget)
return iface->state();
}
class QtTestAccessibleWidget: public QWidget
{
Q_OBJECT
public:
QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent)
{
setObjectName(name);
QPalette pal;
pal.setColor(backgroundRole(), Qt::black);//black is beautiful
setPalette(pal);
setFixedSize(5, 5);
}
};
class QtTestAccessibleWidgetIface: public QAccessibleWidget
{
public:
QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {}
QString text(QAccessible::Text t) const
{
if (t == QAccessible::Help)
return QString::fromLatin1("Help yourself");
return QAccessibleWidget::text(t);
}
static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o)
{
if (key == "QtTestAccessibleWidget")
return new QtTestAccessibleWidgetIface(static_cast<QtTestAccessibleWidget*>(o));
return 0;
}
};
tst_QAccessibility::tst_QAccessibility()
{
click_count = 0;
@ -343,7 +312,6 @@ void tst_QAccessibility::onClicked()
void tst_QAccessibility::initTestCase()
{
QTestAccessibility::initialize();
QAccessible::installFactory(QtTestAccessibleWidgetIface::ifaceFactory);
}
void tst_QAccessibility::cleanupTestCase()
@ -398,24 +366,95 @@ void tst_QAccessibility::eventTest()
delete button;
}
class QtTestAccessibleWidget: public QWidget
{
Q_OBJECT
public:
QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent)
{
setObjectName(name);
}
};
class QtTestAccessibleWidgetIface: public QAccessibleWidget
{
public:
QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {}
QString text(QAccessible::Text t) const
{
if (t == QAccessible::Help)
return QString::fromLatin1("Help yourself");
return QAccessibleWidget::text(t);
}
static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o)
{
if (key == "QtTestAccessibleWidget")
return new QtTestAccessibleWidgetIface(static_cast<QtTestAccessibleWidget*>(o));
return 0;
}
};
class QtTestAccessibleWidgetSubclass: public QtTestAccessibleWidget
{
Q_OBJECT
public:
QtTestAccessibleWidgetSubclass(QWidget *parent, const char *name): QtTestAccessibleWidget(parent, name)
{}
};
void tst_QAccessibility::customWidget()
{
{
QtTestAccessibleWidget* widget = new QtTestAccessibleWidget(0, "Heinz");
widget->show();
QTest::qWaitForWindowExposed(widget);
// By default we create QAccessibleWidget
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
QVERIFY(iface != 0);
QVERIFY(iface->isValid());
QCOMPARE(iface->object(), (QObject*)widget);
QCOMPARE(iface->object()->objectName(), QString("Heinz"));
QCOMPARE(iface->text(QAccessible::Help), QString("Help yourself"));
QCOMPARE(iface->rect().height(), widget->height());
QCOMPARE(iface->text(QAccessible::Help), QString());
QCOMPARE(iface->rect().height(), widget->height());
delete iface;
delete widget;
}
{
QAccessible::installFactory(QtTestAccessibleWidgetIface::ifaceFactory);
QtTestAccessibleWidget* widget = new QtTestAccessibleWidget(0, "Heinz");
widget->show();
QTest::qWaitForWindowExposed(widget);
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
QVERIFY(iface != 0);
QVERIFY(iface->isValid());
QCOMPARE(iface->object(), (QObject*)widget);
QCOMPARE(iface->object()->objectName(), QString("Heinz"));
QCOMPARE(iface->rect().height(), widget->height());
// The help text is only set if our factory works
QCOMPARE(iface->text(QAccessible::Help), QString("Help yourself"));
delete iface;
delete widget;
}
{
// A subclass of any class should still get the right QAccessibleInterface
QtTestAccessibleWidgetSubclass* subclassedWidget = new QtTestAccessibleWidgetSubclass(0, "Hans");
QAccessibleInterface *subIface = QAccessible::queryAccessibleInterface(subclassedWidget);
QVERIFY(subIface != 0);
QVERIFY(subIface->isValid());
QCOMPARE(subIface->object(), (QObject*)subclassedWidget);
QCOMPARE(subIface->text(QAccessible::Help), QString("Help yourself"));
delete subIface;
delete subclassedWidget;
}
QTestAccessibility::clearEvents();
}
void tst_QAccessibility::deletedWidget()
{
QtTestAccessibleWidget *widget = new QtTestAccessibleWidget(0, "Ralf");
QAccessible::installFactory(QtTestAccessibleWidgetIface::ifaceFactory);
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
QVERIFY(iface != 0);
QVERIFY(iface->isValid());
@ -427,6 +466,25 @@ void tst_QAccessibility::deletedWidget()
delete iface;
}
class KFooButton: public QPushButton
{
Q_OBJECT
public:
KFooButton(const QString &text, QWidget* parent = 0) : QPushButton(text, parent)
{}
};
void tst_QAccessibility::subclassedWidget()
{
KFooButton button("Ploink", 0);
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&button);
QVERIFY(iface);
QCOMPARE(iface->object(), (QObject*)&button);
QCOMPARE(iface->text(QAccessible::Name), button.text());
delete iface;
QTestAccessibility::clearEvents();
}
void tst_QAccessibility::statesStructTest()
{
QAccessible::State s1;
@ -598,10 +656,8 @@ void tst_QAccessibility::accessibleName()
{
QWidget *toplevel = createWidgets();
toplevel->show();
#if defined(Q_OS_UNIX)
QCoreApplication::processEvents();
QTest::qWait(100);
#endif
QVERIFY(QTest::qWaitForWindowExposed(toplevel));
QLayout *lout = toplevel->layout();
for (int i = 0; i < lout->count(); i++) {
QLayoutItem *item = lout->itemAt(i);
@ -610,12 +666,12 @@ void tst_QAccessibility::accessibleName()
QString name = tr("Widget Name %1").arg(i);
child->setAccessibleName(name);
QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(child);
QVERIFY(acc);
QCOMPARE(acc->text(QAccessible::Name), name);
QString desc = tr("Widget Description %1").arg(i);
child->setAccessibleDescription(desc);
QCOMPARE(acc->text(QAccessible::Description), desc);
}
delete toplevel;