Add IAccessible2 table2 implementation.

Implement the IAccessible table2 interface for itemviews.
This is simpler than what we have in complexwidgets.
For now it is only used on Linux.

The new table2 interface is ifdef'ed to only be used on X11.
Improve handling of accessible events and clean up.

There are two xfails for the Table and Tree where sibling
navigation is not implemented yet.

Reviewed-by: Gabi
(cherry picked from commit e797ba558dddd45522b5a317316e497e9efc44a8)
(cherry picked from commit eff5ecc5d8f65fa25d6cfd6ed96a9d2a00d0c663)
(cherry picked from commit d29876008fad400bca8d6b37e5d5f61dd1bcb39d)
(cherry picked from commit 2a326fdc8f8bf2bd2c5764394616100906d9db2d)
(cherry picked from commit 9b72e79e20d0d3560e0b064b8b0d75e35feb720e)
(cherry picked from commit 075b0f744363842ed4179c644d933d461389544f)

Change-Id: I654f74991830ae1fc7df7cc91d930390fb88b2a4
Reviewed-on: http://codereview.qt.nokia.com/3274
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@nokia.com>
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
bb10
Frederik Gladhorn 2011-06-27 16:28:50 +02:00 committed by Qt by Nokia
parent 15575fb280
commit 1b7b337797
18 changed files with 2055 additions and 37 deletions

View File

@ -1047,6 +1047,11 @@ const QAccessibleInterface *other, int otherChild) const
\internal
*/
/*!
\fn QAccessibleTable2Interface *QAccessibleInterface::table2Interface()
\internal
*/
/*!
\fn QAccessibleActionInterface *QAccessibleInterface::actionInterface()
\internal

View File

@ -151,6 +151,7 @@ public:
ReadOnly = 0x00000040,
HotTracked = 0x00000080,
DefaultButton = 0x00000100,
// #### Qt5 Expandable
Expanded = 0x00000200,
Collapsed = 0x00000400,
Busy = 0x00000800,
@ -178,6 +179,8 @@ public:
HasPopup = 0x40000000,
Modal = 0x80000000,
// #### Qt5 ManagesDescendants
// #### Qt5 remove HasInvokeExtension
HasInvokeExtension = 0x10000000 // internal
};
Q_DECLARE_FLAGS(State, StateFlag)
@ -348,7 +351,8 @@ namespace QAccessible2
ValueInterface,
TableInterface,
ActionInterface,
ImageInterface
ImageInterface,
Table2Interface
};
}
@ -359,6 +363,7 @@ class QAccessibleValueInterface;
class QAccessibleTableInterface;
class QAccessibleActionInterface;
class QAccessibleImageInterface;
class QAccessibleTable2Interface;
class Q_GUI_EXPORT QAccessibleInterface : public QAccessible
{
@ -422,6 +427,9 @@ public:
inline QAccessibleImageInterface *imageInterface()
{ return reinterpret_cast<QAccessibleImageInterface *>(cast_helper(QAccessible2::ImageInterface)); }
inline QAccessibleTable2Interface *table2Interface()
{ return reinterpret_cast<QAccessibleTable2Interface *>(cast_helper(QAccessible2::Table2Interface)); }
private:
QAccessible2Interface *cast_helper(QAccessible2::InterfaceType);
};

View File

@ -52,6 +52,8 @@ QT_MODULE(Gui)
#ifndef QT_NO_ACCESSIBILITY
class QModelIndex;
namespace QAccessible2
{
enum CoordinateType
@ -68,6 +70,24 @@ namespace QAccessible2
LineBoundary,
NoBoundary
};
enum TableModelChangeType {
TableModelChangeInsert,
TableModelChangeDelete,
TableModelChangeUpdate
};
struct TableModelChange {
int firstColumn;
int firstRow;
int lastColumn;
int lastRow;
TableModelChangeType type;
TableModelChange()
: firstColumn(0), firstRow(0), lastColumn(0), lastRow(0), type(TableModelChangeUpdate)
{}
};
}
class Q_GUI_EXPORT QAccessible2Interface
@ -83,6 +103,7 @@ inline QAccessible2Interface *qAccessibleEditableTextCastHelper() { return 0; }
inline QAccessible2Interface *qAccessibleTableCastHelper() { return 0; }
inline QAccessible2Interface *qAccessibleActionCastHelper() { return 0; }
inline QAccessible2Interface *qAccessibleImageCastHelper() { return 0; }
inline QAccessible2Interface *qAccessibleTable2CastHelper() { return 0; }
#define Q_ACCESSIBLE_OBJECT \
public: \
@ -101,6 +122,8 @@ inline QAccessible2Interface *qAccessibleImageCastHelper() { return 0; }
return qAccessibleActionCastHelper(); \
case QAccessible2::ImageInterface: \
return qAccessibleImageCastHelper(); \
case QAccessible2::Table2Interface: \
return qAccessibleTable2CastHelper(); \
} \
return 0; \
} \
@ -214,6 +237,95 @@ public:
int *columnSpan, bool *isSelected) = 0;
};
class Q_GUI_EXPORT QAccessibleTable2CellInterface: public QAccessibleInterface
{
public:
// Returns the number of columns occupied by this cell accessible.
virtual int columnExtent() const = 0;
// Returns the column headers as an array of cell accessibles.
virtual QList<QAccessibleInterface*> columnHeaderCells() const = 0;
// Translates this cell accessible into the corresponding column index.
virtual int columnIndex() const = 0;
// Returns the number of rows occupied by this cell accessible.
virtual int rowExtent() const = 0;
// Returns the row headers as an array of cell accessibles.
virtual QList<QAccessibleInterface*> rowHeaderCells() const = 0;
// Translates this cell accessible into the corresponding row index.
virtual int rowIndex() const = 0;
// Returns a boolean value indicating whether this cell is selected.
virtual bool isSelected() const = 0;
// Gets the row and column indexes and extents of this cell accessible and whether or not it is selected.
virtual void rowColumnExtents(int *row, int *column, int *rowExtents, int *columnExtents, bool *selected) const = 0;
// Returns a reference to the accessbile of the containing table.
virtual QAccessibleTable2Interface* table() const = 0;
// #### Qt5 this should not be here but part of the state
virtual bool isExpandable() const = 0;
};
class Q_GUI_EXPORT QAccessibleTable2Interface: public QAccessible2Interface
{
public:
inline QAccessible2Interface *qAccessibleTable2CastHelper() { return this; }
// Returns the cell at the specified row and column in the table.
virtual QAccessibleTable2CellInterface *cellAt (int row, int column) const = 0;
// Returns the caption for the table.
virtual QAccessibleInterface *caption() const = 0;
// Returns the description text of the specified column in the table.
virtual QString columnDescription(int column) const = 0;
// Returns the total number of columns in table.
virtual int columnCount() const = 0;
// Returns the total number of rows in table.
virtual int rowCount() const = 0;
// Returns the total number of selected cells.
virtual int selectedCellCount() const = 0;
// Returns the total number of selected columns.
virtual int selectedColumnCount() const = 0;
// Returns the total number of selected rows.
virtual int selectedRowCount() const = 0;
// Returns the description text of the specified row in the table.
virtual QString rowDescription(int row) const = 0;
// Returns a list of accessibles currently selected.
virtual QList<QAccessibleTable2CellInterface*> selectedCells() const = 0;
// Returns a list of column indexes currently selected (0 based).
virtual QList<int> selectedColumns() const = 0;
// Returns a list of row indexes currently selected (0 based).
virtual QList<int> selectedRows() const = 0;
// Returns the summary description of the table.
virtual QAccessibleInterface *summary() const = 0;
// Returns a boolean value indicating whether the specified column is completely selected.
virtual bool isColumnSelected(int column) const = 0;
// Returns a boolean value indicating whether the specified row is completely selected.
virtual bool isRowSelected(int row) const = 0;
// Selects a row and unselects all previously selected rows.
virtual bool selectRow(int row) = 0;
// Selects a column and unselects all previously selected columns.
virtual bool selectColumn(int column) = 0;
// Unselects one row, leaving other selected rows selected (if any).
virtual bool unselectRow(int row) = 0;
// Unselects one column, leaving other selected columns selected (if any).
virtual bool unselectColumn(int column) = 0;
// Returns the type and extents describing how a table changed.
virtual QAccessible2::TableModelChange modelChange() const = 0;
protected:
// These functions are called when the model changes.
virtual void modelReset() = 0;
virtual void rowsInserted(const QModelIndex &parent, int first, int last) = 0;
virtual void rowsRemoved(const QModelIndex &parent, int first, int last) = 0;
virtual void columnsInserted(const QModelIndex &parent, int first, int last) = 0;
virtual void columnsRemoved(const QModelIndex &parent, int first, int last) = 0;
virtual void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row) = 0;
virtual void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column) = 0;
friend class QAbstractItemView;
friend class QAbstractItemViewPrivate;
};
class Q_GUI_EXPORT QAccessibleActionInterface : public QAccessible2Interface
{
public:

View File

@ -103,6 +103,17 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
if (!iface)
return;
// updates for List/Table/Tree should send child
if (who) {
QAccessibleInterface *child;
iface->navigate(QAccessible::Child, who, &child);
if (child) {
delete iface;
iface = child;
who = 0;
}
}
for (int i = 0; i < bridges()->count(); ++i)
bridges()->at(i)->notifyAccessibilityUpdate(reason, iface, who);
delete iface;

View File

@ -60,6 +60,7 @@
#include <private/qabstractitemmodel_p.h>
#ifndef QT_NO_ACCESSIBILITY
#include <qaccessible.h>
#include <qaccessible2.h>
#endif
#include <private/qsoftkeymanager_p.h>
#ifndef QT_NO_GESTURE
@ -682,6 +683,8 @@ void QAbstractItemView::setModel(QAbstractItemModel *model)
this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
@ -712,6 +715,8 @@ void QAbstractItemView::setModel(QAbstractItemModel *model)
this, SLOT(_q_headerDataChanged()));
connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(rowsInserted(QModelIndex,int,int)));
connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
connect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
@ -1095,6 +1100,14 @@ void QAbstractItemView::reset()
setRootIndex(QModelIndex());
if (d->selectionModel)
d->selectionModel->reset();
#ifndef QT_NO_ACCESSIBILITY
#ifdef Q_WS_X11
if (QAccessible::isActive()) {
QAccessible::queryAccessibleInterface(this)->table2Interface()->modelReset();
QAccessible::updateAccessibility(this, 0, QAccessible::TableModelChanged);
}
#endif
#endif
}
/*!
@ -2849,7 +2862,7 @@ void QAbstractItemView::editorDestroyed(QObject *editor)
*/
void QAbstractItemView::setHorizontalStepsPerItem(int steps)
{
Q_UNUSED(steps);
Q_UNUSED(steps)
// do nothing
}
@ -2878,7 +2891,7 @@ int QAbstractItemView::horizontalStepsPerItem() const
*/
void QAbstractItemView::setVerticalStepsPerItem(int steps)
{
Q_UNUSED(steps);
Q_UNUSED(steps)
// do nothing
}
@ -3311,12 +3324,24 @@ void QAbstractItemView::rowsAboutToBeRemoved(const QModelIndex &parent, int star
rows are those under the given \a parent from \a start to \a end
inclusive.
*/
void QAbstractItemViewPrivate::_q_rowsRemoved(const QModelIndex &, int, int)
void QAbstractItemViewPrivate::_q_rowsRemoved(const QModelIndex &index, int start, int end)
{
Q_UNUSED(index)
Q_UNUSED(start)
Q_UNUSED(end)
Q_Q(QAbstractItemView);
if (q->isVisible())
q->updateEditorGeometries();
q->setState(QAbstractItemView::NoState);
#ifndef QT_NO_ACCESSIBILITY
#ifdef Q_WS_X11
if (QAccessible::isActive()) {
QAccessible::queryAccessibleInterface(q)->table2Interface()->rowsRemoved(index, start, end);
QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged);
}
#endif
#endif
}
/*!
@ -3379,28 +3404,73 @@ void QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &par
rows are those under the given \a parent from \a start to \a end
inclusive.
*/
void QAbstractItemViewPrivate::_q_columnsRemoved(const QModelIndex &, int, int)
void QAbstractItemViewPrivate::_q_columnsRemoved(const QModelIndex &index, int start, int end)
{
Q_UNUSED(index)
Q_UNUSED(start)
Q_UNUSED(end)
Q_Q(QAbstractItemView);
if (q->isVisible())
q->updateEditorGeometries();
q->setState(QAbstractItemView::NoState);
#ifndef QT_NO_ACCESSIBILITY
#ifdef Q_WS_X11
if (QAccessible::isActive()) {
QAccessible::queryAccessibleInterface(q)->table2Interface()->columnsRemoved(index, start, end);
QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged);
}
#endif
#endif
}
/*!
\internal
This slot is called when rows have been inserted.
*/
void QAbstractItemViewPrivate::_q_columnsInserted(const QModelIndex &, int, int)
void QAbstractItemViewPrivate::_q_rowsInserted(const QModelIndex &index, int start, int end)
{
Q_UNUSED(index)
Q_UNUSED(start)
Q_UNUSED(end)
Q_Q(QAbstractItemView);
#ifndef QT_NO_ACCESSIBILITY
#ifdef Q_WS_X11
if (QAccessible::isActive()) {
QAccessible::queryAccessibleInterface(q)->table2Interface()->rowsInserted(index, start, end);
QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged);
}
#endif
#endif
}
/*!
\internal
This slot is called when columns have been inserted.
*/
void QAbstractItemViewPrivate::_q_columnsInserted(const QModelIndex &index, int start, int end)
{
Q_UNUSED(index)
Q_UNUSED(start)
Q_UNUSED(end)
Q_Q(QAbstractItemView);
if (q->isVisible())
q->updateEditorGeometries();
#ifndef QT_NO_ACCESSIBILITY
#ifdef Q_WS_X11
if (QAccessible::isActive()) {
QAccessible::queryAccessibleInterface(q)->table2Interface()->columnsInserted(index, start, end);
QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged);
}
#endif
#endif
}
/*!
\internal
*/
@ -3417,7 +3487,16 @@ void QAbstractItemViewPrivate::_q_modelDestroyed()
*/
void QAbstractItemViewPrivate::_q_layoutChanged()
{
Q_Q(QAbstractItemView);
doDelayedItemsLayout();
#ifndef QT_NO_ACCESSIBILITY
#ifdef Q_WS_X11
if (QAccessible::isActive()) {
QAccessible::queryAccessibleInterface(q)->table2Interface()->modelReset();
QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged);
}
#endif
#endif
}
/*!
@ -3742,7 +3821,7 @@ QItemSelectionModel::SelectionFlags QAbstractItemView::selectionCommand(const QM
QItemSelectionModel::SelectionFlags QAbstractItemViewPrivate::multiSelectionCommand(
const QModelIndex &index, const QEvent *event) const
{
Q_UNUSED(index);
Q_UNUSED(index)
if (event) {
switch (event->type()) {

View File

@ -355,6 +355,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeRemoved(const QModelIndex&, int, int))
Q_PRIVATE_SLOT(d_func(), void _q_columnsRemoved(const QModelIndex&, int, int))
Q_PRIVATE_SLOT(d_func(), void _q_columnsInserted(const QModelIndex&, int, int))
Q_PRIVATE_SLOT(d_func(), void _q_rowsInserted(const QModelIndex&, int, int))
Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(const QModelIndex&, int, int))
Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed())
Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged())

View File

@ -108,6 +108,7 @@ public:
void init();
virtual void _q_rowsRemoved(const QModelIndex &parent, int start, int end);
virtual void _q_rowsInserted(const QModelIndex &parent, int start, int end);
virtual void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
virtual void _q_columnsRemoved(const QModelIndex &parent, int start, int end);
virtual void _q_columnsInserted(const QModelIndex &parent, int start, int end);

View File

@ -3168,7 +3168,11 @@ void QListView::currentChanged(const QModelIndex &current, const QModelIndex &pr
if (QAccessible::isActive()) {
if (current.isValid()) {
int entry = visualIndex(current) + 1;
#ifdef Q_WS_X11
QAccessible::updateAccessibility(this, entry, QAccessible::Focus);
#else
QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus);
#endif
}
}
#endif
@ -3187,12 +3191,20 @@ void QListView::selectionChanged(const QItemSelection &selected,
QModelIndex sel = selected.indexes().value(0);
if (sel.isValid()) {
int entry = visualIndex(sel) + 1;
#ifdef Q_WS_X11
QAccessible::updateAccessibility(this, entry, QAccessible::Selection);
#else
QAccessible::updateAccessibility(viewport(), entry, QAccessible::Selection);
#endif
}
QModelIndex desel = deselected.indexes().value(0);
if (desel.isValid()) {
int entry = visualIndex(desel) + 1;
#ifdef Q_WS_X11
QAccessible::updateAccessibility(this, entry, QAccessible::SelectionRemove);
#else
QAccessible::updateAccessibility(viewport(), entry, QAccessible::SelectionRemove);
#endif
}
}
#endif

View File

@ -3164,10 +3164,16 @@ void QTableView::currentChanged(const QModelIndex &current, const QModelIndex &p
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive()) {
if (current.isValid()) {
#ifdef Q_WS_X11
Q_D(QTableView);
int entry = d->accessibleTable2Index(current);
QAccessible::updateAccessibility(this, entry, QAccessible::Focus);
#else
int entry = visualIndex(current) + 1;
if (horizontalHeader())
++entry;
QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus);
#endif
}
}
#endif
@ -3180,22 +3186,33 @@ void QTableView::currentChanged(const QModelIndex &current, const QModelIndex &p
void QTableView::selectionChanged(const QItemSelection &selected,
const QItemSelection &deselected)
{
Q_D(QTableView);
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive()) {
// ### does not work properly for selection ranges.
QModelIndex sel = selected.indexes().value(0);
if (sel.isValid()) {
#ifdef Q_WS_X11
int entry = d->accessibleTable2Index(sel);
QAccessible::updateAccessibility(this, entry, QAccessible::Selection);
#else
int entry = visualIndex(sel);
if (horizontalHeader())
++entry;
QAccessible::updateAccessibility(viewport(), entry, QAccessible::Selection);
#endif
}
QModelIndex desel = deselected.indexes().value(0);
if (desel.isValid()) {
#ifdef Q_WS_X11
int entry = d->accessibleTable2Index(sel);
QAccessible::updateAccessibility(this, entry, QAccessible::SelectionRemove);
#else
int entry = visualIndex(sel);
if (horizontalHeader())
++entry;
QAccessible::updateAccessibility(viewport(), entry, QAccessible::SelectionRemove);
#endif
}
}
#endif

View File

@ -167,6 +167,11 @@ public:
return horizontalHeader->logicalIndex(visualCol);
}
inline int accessibleTable2Index(const QModelIndex &index) const {
return (index.row() + (horizontalHeader ? 1 : 0)) * (index.model()->columnCount() + (verticalHeader ? 1 : 0))
+ index.column() + (verticalHeader ? 1 : 0) + 1;
}
int sectionSpanEndLogical(const QHeaderView *header, int logical, int span) const;
int sectionSpanSize(const QHeaderView *header, int logical, int span) const;
bool spanContainsSection(const QHeaderView *header, int logical, int spanLogical, int span) const;

View File

@ -54,6 +54,7 @@
#include <qdebug.h>
#ifndef QT_NO_ACCESSIBILITY
#include <qaccessible.h>
#include <qaccessible2.h>
#endif
#include <private/qtreeview_p.h>
@ -2883,20 +2884,36 @@ void QTreeViewPrivate::expand(int item, bool emitSignal)
void QTreeViewPrivate::insertViewItems(int pos, int count, const QTreeViewItem &viewItem)
{
Q_Q(QTreeView);
viewItems.insert(pos, count, viewItem);
QTreeViewItem *items = viewItems.data();
for (int i = pos + count; i < viewItems.count(); i++)
if (items[i].parentItem >= pos)
items[i].parentItem += count;
#ifndef QT_NO_ACCESSIBILITY
#ifdef Q_WS_X11
if (QAccessible::isActive()) {
QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged);
}
#endif
#endif
}
void QTreeViewPrivate::removeViewItems(int pos, int count)
{
Q_Q(QTreeView);
viewItems.remove(pos, count);
QTreeViewItem *items = viewItems.data();
for (int i = pos; i < viewItems.count(); i++)
if (items[i].parentItem >= pos)
items[i].parentItem -= count;
#ifndef QT_NO_ACCESSIBILITY
#ifdef Q_WS_X11
if (QAccessible::isActive()) {
QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged);
}
#endif
#endif
}
#if 0
@ -3687,14 +3704,6 @@ void QTreeViewPrivate::_q_sortIndicatorChanged(int column, Qt::SortOrder order)
*/
void QTreeView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
{
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive()) {
int entry = visualIndex(current) + 1;
if (header())
++entry;
QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus);
}
#endif
QAbstractItemView::currentChanged(current, previous);
if (allColumnsShowFocus()) {
@ -3711,6 +3720,19 @@ void QTreeView::currentChanged(const QModelIndex &current, const QModelIndex &pr
viewport()->update(currentRect);
}
}
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive() && current.isValid()) {
#ifdef Q_WS_X11
int entry = (visualIndex(current) + (header()?1:0))*current.model()->columnCount()+current.column() + 1;
QAccessible::updateAccessibility(this, entry, QAccessible::Focus);
#else
int entry = visualIndex(current) + 1;
if (header())
++entry;
QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus);
#endif
}
#endif
}
/*!
@ -3719,26 +3741,38 @@ void QTreeView::currentChanged(const QModelIndex &current, const QModelIndex &pr
void QTreeView::selectionChanged(const QItemSelection &selected,
const QItemSelection &deselected)
{
QAbstractItemView::selectionChanged(selected, deselected);
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive()) {
// ### does not work properly for selection ranges.
QModelIndex sel = selected.indexes().value(0);
if (sel.isValid()) {
#ifdef Q_WS_X11
int entry = (visualIndex(sel) + (header()?1:0))*sel.model()->columnCount()+sel.column() + 1;
Q_ASSERT(entry > 0);
QAccessible::updateAccessibility(this, entry, QAccessible::Selection);
#else
int entry = visualIndex(sel) + 1;
if (header())
++entry;
QAccessible::updateAccessibility(viewport(), entry, QAccessible::Selection);
#endif
}
QModelIndex desel = deselected.indexes().value(0);
if (desel.isValid()) {
#ifdef Q_WS_X11
int entry = (visualIndex(desel) + (header()?1:0))*desel.model()->columnCount()+desel.column() + 1;
Q_ASSERT(entry > 0);
QAccessible::updateAccessibility(this, entry, QAccessible::SelectionRemove);
#else
int entry = visualIndex(desel) + 1;
if (header())
++entry;
QAccessible::updateAccessibility(viewport(), entry, QAccessible::SelectionRemove);
#endif
}
}
#endif
QAbstractItemView::selectionChanged(selected, deselected);
}
int QTreeView::visualIndex(const QModelIndex &index) const

View File

@ -219,6 +219,9 @@ protected:
private:
friend class QAccessibleItemView;
friend class QAccessibleTable2;
friend class QAccessibleTree;
friend class QAccessibleTable2Cell;
int visualIndex(const QModelIndex &index) const;
Q_DECLARE_PRIVATE(QTreeView)

View File

@ -78,7 +78,7 @@ struct QTreeViewItem
Q_DECLARE_TYPEINFO(QTreeViewItem, Q_MOVABLE_TYPE);
class QTreeViewPrivate : public QAbstractItemViewPrivate
class Q_GUI_EXPORT QTreeViewPrivate : public QAbstractItemViewPrivate
{
Q_DECLARE_PUBLIC(QTreeView)
public:
@ -223,6 +223,10 @@ public:
inline void invalidateHeightCache(int item) const
{ viewItems[item].height = 0; }
inline int accessibleTable2Index(const QModelIndex &index) const {
return (viewIndex(index) + (header ? 1 : 0)) * model->columnCount()+index.column() + 1;
}
// used for spanning rows
QVector<QPersistentModelIndex> spanningIndexes;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,319 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef ACCESSIBLE_ITEMVIEWS_H
#define ACCESSIBLE_ITEMVIEWS_H
#include <QtGui/qabstractitemview.h>
#include <QtGui/qheaderview.h>
#include <QtGui/qaccessible.h>
#include <QtGui/qaccessible2.h>
#include <QtGui/qaccessiblewidget.h>
QT_BEGIN_NAMESPACE
#ifndef QT_NO_ACCESSIBILITY
#ifndef QT_NO_ITEMVIEWS
class QAccessibleTable2Cell;
class QAccessibleTable2HeaderCell;
class QAccessibleTable2: public QAccessibleTable2Interface, public QAccessibleObjectEx
{
Q_ACCESSIBLE_OBJECT
public:
explicit QAccessibleTable2(QWidget *w);
virtual ~QAccessibleTable2();
QObject *object() const { return view; }
Role role(int child) const;
State state(int child) const;
QString text(Text t, int child) const;
QRect rect(int child) const;
int childAt(int x, int y) const;
int childCount() const;
int indexOfChild(const QAccessibleInterface *) const;
int navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const;
Relation relationTo(int child, const QAccessibleInterface *other, int otherChild) const;
#ifndef QT_NO_ACTION
int userActionCount(int child) const;
QString actionText(int action, Text t, int child) const;
bool doAction(int action, int child, const QVariantList &params);
#endif
QVariant invokeMethodEx(Method, int, const QVariantList &) { return QVariant(); }
// table2 interface
virtual QAccessibleTable2CellInterface *cellAt(int row, int column) const;
virtual QAccessibleInterface *caption() const;
virtual QAccessibleInterface *summary() const;
virtual QString columnDescription(int column) const;
virtual QString rowDescription(int row) const;
virtual int columnCount() const;
virtual int rowCount() const;
virtual QAccessible2::TableModelChange modelChange() const;
// selection
virtual int selectedCellCount() const;
virtual int selectedColumnCount() const;
virtual int selectedRowCount() const;
virtual QList<QAccessibleTable2CellInterface*> selectedCells() const;
virtual QList<int> selectedColumns() const;
virtual QList<int> selectedRows() const;
virtual bool isColumnSelected(int column) const;
virtual bool isRowSelected(int row) const;
virtual bool selectRow(int row);
virtual bool selectColumn(int column);
virtual bool unselectRow(int row);
virtual bool unselectColumn(int column);
protected:
virtual void modelReset();
virtual void rowsInserted(const QModelIndex &parent, int first, int last);
virtual void rowsRemoved(const QModelIndex &parent, int first, int last);
virtual void columnsInserted(const QModelIndex &parent, int first, int last);
virtual void columnsRemoved(const QModelIndex &parent, int first, int last);
virtual void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row);
virtual void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column);
protected:
QAbstractItemView* view;
QAccessible2::TableModelChange lastChange;
inline QAccessibleTable2Cell *cell(const QModelIndex &index) const;
inline QAccessible::Role cellRole() const {
switch (m_role) {
case QAccessible::List:
return QAccessible::ListItem;
case QAccessible::Table:
return QAccessible::Cell;
case QAccessible::Tree:
return QAccessible::TreeItem;
default:
Q_ASSERT(0);
}
return QAccessible::NoRole;
}
QHeaderView *horizontalHeader() const;
QHeaderView *verticalHeader() const;
private:
// the child index for a model index
inline int logicalIndex(const QModelIndex &index) const;
// the model index from the child index
QAccessibleInterface *childFromLogical(int logicalIndex) const;
QAccessible::Role m_role;
};
class QAccessibleTree :public QAccessibleTable2
{
public:
explicit QAccessibleTree(QWidget *w)
: QAccessibleTable2(w)
{}
virtual ~QAccessibleTree() {}
int childAt(int x, int y) const;
int childCount() const;
int indexOfChild(const QAccessibleInterface *) const;
int rowCount() const;
int navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const;
Relation relationTo(int child, const QAccessibleInterface *other, int otherChild) const;
// table2 interface
QAccessibleTable2CellInterface *cellAt(int row, int column) const;
QString rowDescription(int row) const;
bool isRowSelected(int row) const;
bool selectRow(int row);
private:
QModelIndex indexFromLogical(int row, int column = 0) const;
};
class QAccessibleTable2Cell: public QAccessibleTable2CellInterface /*), public QAccessibleTextInterface, public QAccessibleSimpleEditableTextInterface*/
{
public:
QAccessibleTable2Cell(QAbstractItemView *view, const QModelIndex &m_index, QAccessible::Role role);
QObject *object() const { return 0; }
Role role(int child) const;
State state(int child) const;
QRect rect(int child) const;
bool isValid() const;
int childAt(int, int) const { return 0; }
int childCount() const { return 0; }
int indexOfChild(const QAccessibleInterface *) const { return -1; }
QString text(Text t, int child) const;
void setText(Text t, int child, const QString &text);
int navigate(RelationFlag relation, int m_index, QAccessibleInterface **iface) const;
Relation relationTo(int child, const QAccessibleInterface *other, int otherChild) const;
bool isExpandable() const;
#ifndef QT_NO_ACTION
int userActionCount(int child) const;
QString actionText(int action, Text t, int child) const;
bool doAction(int action, int child, const QVariantList &params);
#endif
// cell interface
virtual int columnExtent() const;
virtual QList<QAccessibleInterface*> columnHeaderCells() const;
virtual int columnIndex() const;
virtual int rowExtent() const;
virtual QList<QAccessibleInterface*> rowHeaderCells() const;
virtual int rowIndex() const;
virtual bool isSelected() const;
virtual void rowColumnExtents(int *row, int *column, int *rowExtents, int *columnExtents, bool *selected) const;
virtual QAccessibleTable2Interface* table() const;
private:
QHeaderView *verticalHeader() const;
QHeaderView *horizontalHeader() const;
QAbstractItemView *view;
QModelIndex m_index;
QAccessible::Role m_role;
friend class QAccessibleTable2;
friend class QAccessibleTree;
};
class QAccessibleTable2HeaderCell: public QAccessibleInterface /*), public QAccessibleTextInterface, public QAccessibleSimpleEditableTextInterface*/
{
public:
// For header cells, pass the header view in addition
QAccessibleTable2HeaderCell(QAbstractItemView *view, int index, Qt::Orientation orientation);
QObject *object() const { return 0; }
Role role(int child) const;
State state(int child) const;
QRect rect(int child) const;
bool isValid() const;
int childAt(int, int) const { return 0; }
int childCount() const { return 0; }
int indexOfChild(const QAccessibleInterface *) const { return -1; }
QString text(Text t, int child) const;
void setText(Text t, int child, const QString &text);
int navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const;
Relation relationTo(int child, const QAccessibleInterface *other, int otherChild) const;
#ifndef QT_NO_ACTION
int userActionCount(int child) const;
QString actionText(int action, Text t, int child) const;
bool doAction(int action, int child, const QVariantList &params);
#endif
private:
QAbstractItemView *view;
int index;
Qt::Orientation orientation;
friend class QAccessibleTable2;
friend class QAccessibleTree;
};
// This is the corner button on the top left of a table.
// It can be used to select all cells or it is not active at all.
// For now it is ignored.
class QAccessibleTable2CornerButton: public QAccessibleInterface
{
public:
QAccessibleTable2CornerButton(QAbstractItemView *view_)
:view(view_)
{}
QObject *object() const { return 0; }
Role role(int child) const { Q_ASSERT(child == 0); return QAccessible::Pane; }
State state(int child) const { Q_ASSERT(child == 0); return QAccessible::Normal; }
QRect rect(int child) const { Q_ASSERT(child == 0); return QRect(); }
bool isValid() const { return true; }
int childAt(int, int) const { return 0; }
int childCount() const { return 0; }
int indexOfChild(const QAccessibleInterface *) const { return -1; }
QString text(Text, int) const { return QString(); }
void setText(Text, int, const QString &) {}
int navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const
{
if (relation == QAccessible::Ancestor && index == 1) {
*iface = QAccessible::queryAccessibleInterface(view);
return 0;
}
return -1;
}
Relation relationTo(int, const QAccessibleInterface *, int) const
{
return QAccessible::Unrelated;
}
#ifndef QT_NO_ACTION
int userActionCount(int) const { return 0; }
QString actionText(int, Text, int) const { return QString(); }
bool doAction(int, int, const QVariantList &) { return false; }
#endif
private:
QAbstractItemView *view;
};
#endif
#endif // QT_NO_ACCESSIBILITY
QT_END_NAMESPACE
#endif // ACCESSIBLE_ITEMVIEWS_H

View File

@ -44,11 +44,13 @@
#include "simplewidgets.h"
#include "rangecontrols.h"
#include "complexwidgets.h"
#include "itemviews.h"
#include <qaccessibleplugin.h>
#include <qplugin.h>
#include <qpushbutton.h>
#include <qtoolbutton.h>
#include <qtreeview.h>
#include <qvariant.h>
#include <qaccessible.h>
@ -56,6 +58,7 @@
QT_BEGIN_NAMESPACE
class AccessibleFactory : public QAccessiblePlugin
{
public:
@ -251,6 +254,22 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec
iface = new QAccessibleMenu(widget);
#endif
#ifndef QT_NO_ITEMVIEWS
#ifdef Q_WS_X11
} else if (classname == QLatin1String("QAbstractItemView")) {
if (qobject_cast<const QTreeView*>(widget)) {
iface = new QAccessibleTree(widget);
} else {
iface = new QAccessibleTable2(widget);
}
} else if (classname == QLatin1String("QWidget")
&& widget->objectName() == QLatin1String("qt_scrollarea_viewport")
&& qobject_cast<QAbstractItemView*>(widget->parentWidget())) {
if (qobject_cast<const QTreeView*>(widget->parentWidget())) {
iface = new QAccessibleTree(widget->parentWidget());
} else {
iface = new QAccessibleTable2(widget->parentWidget());
}
#else
} else if (classname == QLatin1String("QHeaderView")) {
iface = new QAccessibleHeader(widget);
} else if (classname == QLatin1String("QAbstractItemView")) {
@ -259,7 +278,8 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec
&& widget->objectName() == QLatin1String("qt_scrollarea_viewport")
&& qobject_cast<QAbstractItemView*>(widget->parentWidget())) {
iface = new QAccessibleItemView(widget);
#endif
#endif // Q_WS_X11
#endif // QT_NO_ITEMVIEWS
#ifndef QT_NO_TABBAR
} else if (classname == QLatin1String("QTabBar")) {
iface = new QAccessibleTabBar(widget);

View File

@ -8,14 +8,18 @@ DESTDIR = $$QT.gui.plugins/accessible
QTDIR_build:REQUIRES += "contains(QT_CONFIG, accessibility)"
SOURCES += main.cpp \
simplewidgets.cpp \
rangecontrols.cpp \
complexwidgets.cpp \
qaccessiblewidgets.cpp \
qaccessiblemenu.cpp
simplewidgets.cpp \
rangecontrols.cpp \
complexwidgets.cpp \
qaccessiblewidgets.cpp \
qaccessiblemenu.cpp \
itemviews.cpp
HEADERS += qaccessiblewidgets.h \
simplewidgets.h \
rangecontrols.h \
complexwidgets.h \
qaccessiblemenu.h
simplewidgets.h \
rangecontrols.h \
complexwidgets.h \
qaccessiblemenu.h \
itemviews.h

View File

@ -187,7 +187,8 @@ static int verifyHierarchy(QAccessibleInterface *iface)
if (middleChild) {
entry = if2->navigate(QAccessible::Sibling, middle, &if3);
EXPECT(entry == 0 && if3->object() == middleChild->object());
delete if3;
if (entry == 0)
delete if3;
EXPECT(iface->indexOfChild(middleChild) == middle);
}
@ -258,6 +259,9 @@ private slots:
void scrollAreaTest();
void tableWidgetTest();
void tableViewTest();
void table2ListTest();
void table2TreeTest();
void table2TableTest();
void calendarWidgetTest();
void dockWidgetTest();
void comboBoxTest();
@ -288,6 +292,10 @@ QString eventName(const int ev)
case 0x0012: return "ScrollingStart";
case 0x0013: return "ScrollingEnd";
case 0x0018: return "MenuCommand";
case 0x0116: return "TableModelChanged";
case 0x011B: return "TextCaretMoved";
case 0x8000: return "ObjectCreated";
case 0x8001: return "ObjectDestroyed";
case 0x8002: return "ObjectShow";
@ -957,18 +965,21 @@ void tst_QAccessibility::applicationTest()
void tst_QAccessibility::mainWindowTest()
{
QMainWindow mw;
mw.resize(300, 200);
mw.show(); // triggers layout
QMainWindow *mw = new QMainWindow;
mw->resize(300, 200);
mw->show(); // triggers layout
QLatin1String name = QLatin1String("I am the main window");
mw.setWindowTitle(name);
QTest::qWaitForWindowShown(&mw);
mw->setWindowTitle(name);
QTest::qWaitForWindowShown(mw);
QVERIFY_EVENT(mw, 0, QAccessible::ObjectShow);
QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&mw);
QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw);
QCOMPARE(interface->text(QAccessible::Name, 0), name);
QCOMPARE(interface->role(0), QAccessible::Window);
delete interface;
delete mw;
QTestAccessibility::clearEvents();
}
class CounterButton : public QPushButton {
@ -1728,6 +1739,9 @@ void tst_QAccessibility::textBrowserTest()
void tst_QAccessibility::listViewTest()
{
#if defined(Q_WS_X11)
QSKIP( "Accessible table1 interface is no longer supported on X11.", SkipAll);
#else
{
QListView listView;
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView);
@ -1793,6 +1807,7 @@ void tst_QAccessibility::listViewTest()
}
QTestAccessibility::clearEvents();
#endif
}
@ -2041,9 +2056,11 @@ void tst_QAccessibility::lineEditTest()
le3->deselect();
le3->setCursorPosition(3);
QCOMPARE(textIface->cursorPosition(), 3);
QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le3, 0, QAccessible::TextCaretMoved)));
QCOMPARE(textIface->selectionCount(), 0);
int start, end;
QTestAccessibility::clearEvents();
int start, end;
QCOMPARE(textIface->text(0, 8), QString::fromLatin1("I always"));
QCOMPARE(textIface->textAtOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("I"));
QCOMPARE(start, 0);
@ -2086,6 +2103,7 @@ void tst_QAccessibility::lineEditTest()
delete iface;
delete toplevel;
QTestAccessibility::clearEvents();
}
void tst_QAccessibility::workspaceTest()
@ -2496,6 +2514,9 @@ void tst_QAccessibility::scrollAreaTest()
void tst_QAccessibility::tableWidgetTest()
{
#if defined(Q_WS_X11)
QSKIP( "Accessible table1 interface is no longer supported on X11.", SkipAll);
#else
{
QWidget *topLevel = new QWidget;
QTableWidget *w = new QTableWidget(8,4,topLevel);
@ -2535,6 +2556,7 @@ void tst_QAccessibility::tableWidgetTest()
delete topLevel;
}
QTestAccessibility::clearEvents();
#endif
}
class QtTestTableModel: public QAbstractTableModel
@ -2617,6 +2639,9 @@ public:
void tst_QAccessibility::tableViewTest()
{
#if defined(Q_WS_X11)
QSKIP( "Accessible table1 interface is no longer supported on X11.", SkipAll);
#else
{
QtTestTableModel *model = new QtTestTableModel(3, 4);
QTableView *w = new QTableView();
@ -2696,6 +2721,331 @@ void tst_QAccessibility::tableViewTest()
delete model;
}
QTestAccessibility::clearEvents();
#endif
}
void tst_QAccessibility::table2ListTest()
{
#if !defined(Q_WS_X11)
QSKIP( "Accessible table2 interface is currently only supported on X11.", SkipAll);
#else
QListWidget *listView = new QListWidget;
listView->addItem("Oslo");
listView->addItem("Berlin");
listView->addItem("Brisbane");
listView->resize(400,400);
listView->show();
QTest::qWait(1); // Need this for indexOfchild to work.
#if defined(Q_WS_X11)
qt_x11_wait_for_window_manager(listView);
QTest::qWait(100);
#endif
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView);
QCOMPARE(verifyHierarchy(iface), 0);
QCOMPARE((int)iface->role(0), (int)QAccessible::List);
QCOMPARE(iface->childCount(), 3);
QAccessibleInterface *child1 = 0;
QCOMPARE(iface->navigate(QAccessible::Child, 1, &child1), 0);
QVERIFY(child1);
QCOMPARE(iface->indexOfChild(child1), 1);
QCOMPARE(child1->text(QAccessible::Name, 0), QString("Oslo"));
QCOMPARE(child1->role(0), QAccessible::ListItem);
delete child1;
QAccessibleInterface *child2 = 0;
QCOMPARE(iface->navigate(QAccessible::Child, 2, &child2), 0);
QVERIFY(child2);
QCOMPARE(iface->indexOfChild(child2), 2);
QCOMPARE(child2->text(QAccessible::Name, 0), QString("Berlin"));
delete child2;
QAccessibleInterface *child3 = 0;
QCOMPARE(iface->navigate(QAccessible::Child, 3, &child3), 0);
QVERIFY(child3);
QCOMPARE(iface->indexOfChild(child3), 3);
QCOMPARE(child3->text(QAccessible::Name, 0), QString("Brisbane"));
delete child3;
QTestAccessibility::clearEvents();
// Check for events
QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(1)).center());
QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Selection)));
QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Focus)));
QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(2)).center());
QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Selection)));
QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Focus)));
listView->addItem("Munich");
QCOMPARE(iface->childCount(), 4);
// table 2
QAccessibleTable2Interface *table2 = iface->table2Interface();
QVERIFY(table2);
QCOMPARE(table2->columnCount(), 1);
QCOMPARE(table2->rowCount(), 4);
QAccessibleTable2CellInterface *cell1;
QVERIFY(cell1 = table2->cellAt(0,0));
QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Oslo"));
QAccessibleTable2CellInterface *cell4;
QVERIFY(cell4 = table2->cellAt(3,0));
QCOMPARE(cell4->text(QAccessible::Name, 0), QString("Munich"));
QCOMPARE(cell4->role(0), QAccessible::ListItem);
QCOMPARE(cell4->rowIndex(), 3);
QCOMPARE(cell4->columnIndex(), 0);
QVERIFY(!cell4->isExpandable());
delete cell4;
delete cell1;
delete iface;
delete listView;
QTestAccessibility::clearEvents();
#endif
}
void tst_QAccessibility::table2TreeTest()
{
#if !defined(Q_WS_X11)
QSKIP( "Accessible table2 interface is currently only supported on X11.", SkipAll);
#else
QTreeWidget *treeView = new QTreeWidget;
treeView->setColumnCount(2);
QTreeWidgetItem *header = new QTreeWidgetItem;
header->setText(0, "Artist");
header->setText(1, "Work");
treeView->setHeaderItem(header);
QTreeWidgetItem *root1 = new QTreeWidgetItem;
root1->setText(0, "Spain");
treeView->addTopLevelItem(root1);
QTreeWidgetItem *item1 = new QTreeWidgetItem;
item1->setText(0, "Picasso");
item1->setText(1, "Guernica");
root1->addChild(item1);
QTreeWidgetItem *item2 = new QTreeWidgetItem;
item2->setText(0, "Tapies");
item2->setText(1, "Ambrosia");
root1->addChild(item2);
QTreeWidgetItem *root2 = new QTreeWidgetItem;
root2->setText(0, "Austria");
treeView->addTopLevelItem(root2);
QTreeWidgetItem *item3 = new QTreeWidgetItem;
item3->setText(0, "Klimt");
item3->setText(1, "The Kiss");
root2->addChild(item3);
treeView->resize(400,400);
treeView->show();
QTest::qWait(1); // Need this for indexOfchild to work.
#if defined(Q_WS_X11)
qt_x11_wait_for_window_manager(treeView);
QTest::qWait(100);
#endif
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(treeView);
QEXPECT_FAIL("", "Implement Sibling navigation for table2 cells.", Continue);
QCOMPARE(verifyHierarchy(iface), 0);
QCOMPARE((int)iface->role(0), (int)QAccessible::Tree);
// header and 2 rows (the others are not expanded, thus not visible)
QCOMPARE(iface->childCount(), 6);
QAccessibleInterface *header1 = 0;
QCOMPARE(iface->navigate(QAccessible::Child, 1, &header1), 0);
QVERIFY(header1);
QCOMPARE(iface->indexOfChild(header1), 1);
QCOMPARE(header1->text(QAccessible::Name, 0), QString("Artist"));
QCOMPARE(header1->role(0), QAccessible::ColumnHeader);
delete header1;
QAccessibleInterface *child1 = 0;
QCOMPARE(iface->navigate(QAccessible::Child, 3, &child1), 0);
QVERIFY(child1);
QCOMPARE(iface->indexOfChild(child1), 3);
QCOMPARE(child1->text(QAccessible::Name, 0), QString("Spain"));
QCOMPARE(child1->role(0), QAccessible::TreeItem);
QVERIFY(!(child1->state(0) & QAccessible::Expanded));
delete child1;
QAccessibleInterface *child2 = 0;
QCOMPARE(iface->navigate(QAccessible::Child, 5, &child2), 0);
QVERIFY(child2);
QCOMPARE(iface->indexOfChild(child2), 5);
QCOMPARE(child2->text(QAccessible::Name, 0), QString("Austria"));
delete child2;
QTestAccessibility::clearEvents();
// table 2
QAccessibleTable2Interface *table2 = iface->table2Interface();
QVERIFY(table2);
QCOMPARE(table2->columnCount(), 2);
QCOMPARE(table2->rowCount(), 2);
QAccessibleTable2CellInterface *cell1;
QVERIFY(cell1 = table2->cellAt(0,0));
QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Spain"));
QAccessibleTable2CellInterface *cell2;
QVERIFY(cell2 = table2->cellAt(1,0));
QCOMPARE(cell2->text(QAccessible::Name, 0), QString("Austria"));
QCOMPARE(cell2->role(0), QAccessible::TreeItem);
QCOMPARE(cell2->rowIndex(), 1);
QCOMPARE(cell2->columnIndex(), 0);
QVERIFY(cell2->isExpandable());
QCOMPARE(iface->indexOfChild(cell2), 5);
QVERIFY(!(cell2->state(0) & QAccessible::Expanded));
QCOMPARE(table2->columnDescription(1), QString("Work"));
delete cell2;
delete cell1;
treeView->expandAll();
QTest::qWait(1); // Need this for indexOfchild to work.
#if defined(Q_WS_X11)
qt_x11_wait_for_window_manager(treeView);
QTest::qWait(100);
#endif
QCOMPARE(table2->columnCount(), 2);
QCOMPARE(table2->rowCount(), 5);
cell1 = table2->cellAt(1,0);
QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Picasso"));
QCOMPARE(iface->indexOfChild(cell1), 5); // 1 based + 2 header + 2 for root item
cell2 = table2->cellAt(4,0);
QCOMPARE(cell2->text(QAccessible::Name, 0), QString("Klimt"));
QCOMPARE(cell2->role(0), QAccessible::TreeItem);
QCOMPARE(cell2->rowIndex(), 4);
QCOMPARE(cell2->columnIndex(), 0);
QVERIFY(!cell2->isExpandable());
QCOMPARE(iface->indexOfChild(cell2), 11);
QCOMPARE(table2->columnDescription(0), QString("Artist"));
QCOMPARE(table2->columnDescription(1), QString("Work"));
delete iface;
QTestAccessibility::clearEvents();
#endif
}
void tst_QAccessibility::table2TableTest()
{
#if !defined(Q_WS_X11)
QSKIP( "Accessible table2 interface is currently only supported on X11.", SkipAll);
#else
QTableWidget *tableView = new QTableWidget(3, 3);
tableView->setColumnCount(3);
QStringList hHeader;
hHeader << "h1" << "h2" << "h3";
tableView->setHorizontalHeaderLabels(hHeader);
QStringList vHeader;
vHeader << "v1" << "v2" << "v3";
tableView->setVerticalHeaderLabels(vHeader);
for (int i = 0; i<9; ++i) {
QTableWidgetItem *item = new QTableWidgetItem;
item->setText(QString::number(i/3) + QString(".") + QString::number(i%3));
tableView->setItem(i/3, i%3, item);
}
tableView->resize(600,600);
tableView->show();
QTest::qWait(1); // Need this for indexOfchild to work.
#if defined(Q_WS_X11)
qt_x11_wait_for_window_manager(tableView);
QTest::qWait(100);
#endif
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(tableView);
QEXPECT_FAIL("", "Implement Sibling navigation for table2 cells.", Continue);
QCOMPARE(verifyHierarchy(iface), 0);
QCOMPARE((int)iface->role(0), (int)QAccessible::Table);
// header and 2 rows (the others are not expanded, thus not visible)
QCOMPARE(iface->childCount(), 9+3+3+1); // cell+headers+topleft button
QAccessibleInterface *cornerButton = 0;
QCOMPARE(iface->navigate(QAccessible::Child, 1, &cornerButton), 0);
QVERIFY(cornerButton);
QCOMPARE(iface->indexOfChild(cornerButton), 1);
QCOMPARE(cornerButton->role(0), QAccessible::Pane);
delete cornerButton;
QAccessibleInterface *child1 = 0;
QCOMPARE(iface->navigate(QAccessible::Child, 3, &child1), 0);
QVERIFY(child1);
QCOMPARE(iface->indexOfChild(child1), 3);
QCOMPARE(child1->text(QAccessible::Name, 0), QString("h2"));
QCOMPARE(child1->role(0), QAccessible::ColumnHeader);
QVERIFY(!(child1->state(0) & QAccessible::Expanded));
delete child1;
QAccessibleInterface *child2 = 0;
QCOMPARE(iface->navigate(QAccessible::Child, 11, &child2), 0);
QVERIFY(child2);
QCOMPARE(iface->indexOfChild(child2), 11);
QCOMPARE(child2->text(QAccessible::Name, 0), QString("1.1"));
QAccessibleTable2CellInterface *cell2Iface = static_cast<QAccessibleTable2CellInterface*>(child2);
QCOMPARE(cell2Iface->rowIndex(), 1);
QCOMPARE(cell2Iface->columnIndex(), 1);
delete child2;
QAccessibleInterface *child3 = 0;
QCOMPARE(iface->navigate(QAccessible::Child, 12, &child3), 0);
QCOMPARE(iface->indexOfChild(child3), 12);
QCOMPARE(child3->text(QAccessible::Name, 0), QString("1.2"));
delete child3;
QTestAccessibility::clearEvents();
// table 2
QAccessibleTable2Interface *table2 = iface->table2Interface();
QVERIFY(table2);
QCOMPARE(table2->columnCount(), 3);
QCOMPARE(table2->rowCount(), 3);
QAccessibleTable2CellInterface *cell1;
QVERIFY(cell1 = table2->cellAt(0,0));
QCOMPARE(cell1->text(QAccessible::Name, 0), QString("0.0"));
QCOMPARE(iface->indexOfChild(cell1), 6);
QAccessibleTable2CellInterface *cell2;
QVERIFY(cell2 = table2->cellAt(0,1));
QCOMPARE(cell2->text(QAccessible::Name, 0), QString("0.1"));
QCOMPARE(cell2->role(0), QAccessible::Cell);
QCOMPARE(cell2->rowIndex(), 0);
QCOMPARE(cell2->columnIndex(), 1);
QCOMPARE(iface->indexOfChild(cell2), 7);
delete cell2;
QAccessibleTable2CellInterface *cell3;
QVERIFY(cell3 = table2->cellAt(1,2));
QCOMPARE(cell3->text(QAccessible::Name, 0), QString("1.2"));
QCOMPARE(cell3->role(0), QAccessible::Cell);
QCOMPARE(cell3->rowIndex(), 1);
QCOMPARE(cell3->columnIndex(), 2);
QCOMPARE(iface->indexOfChild(cell3), 12);
delete cell3;
QCOMPARE(table2->columnDescription(0), QString("h1"));
QCOMPARE(table2->columnDescription(1), QString("h2"));
QCOMPARE(table2->columnDescription(2), QString("h3"));
QCOMPARE(table2->rowDescription(0), QString("v1"));
QCOMPARE(table2->rowDescription(1), QString("v2"));
QCOMPARE(table2->rowDescription(2), QString("v3"));
delete iface;
delete tableView;
QTestAccessibility::clearEvents();
#endif
}
void tst_QAccessibility::calendarWidgetTest()
@ -2912,6 +3262,9 @@ void tst_QAccessibility::comboBoxTest()
void tst_QAccessibility::treeWidgetTest()
{
#if defined(Q_WS_X11)
QSKIP( "Accessible table1 interface is no longer supported on X11.", SkipAll);
#else
QWidget *w = new QWidget;
QTreeWidget *tree = new QTreeWidget(w);
QHBoxLayout *l = new QHBoxLayout(w);
@ -2969,6 +3322,7 @@ void tst_QAccessibility::treeWidgetTest()
delete w;
QTestAccessibility::clearEvents();
#endif
}
void tst_QAccessibility::labelTest()