From d6e0a50e443f869c4ced17453f0ea269a86ca453 Mon Sep 17 00:00:00 2001 From: miniak Date: Mon, 11 Jul 2011 10:34:14 +0200 Subject: QProgressBar: transparent background on Windows Vista (partId: PP_BAR -> PP_TRANSPARENTBAR) Merge-request: 2616 Reviewed-by: Jens Bache-Wiig --- src/gui/styles/qwindowsvistastyle.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index da484ba..b894eb4 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -76,6 +76,10 @@ static const int windowsRightBorder = 15; // right border on windows # define CMDLGS_PRESSED 3 # define CMDLGS_DISABLED 4 #endif +#ifndef PP_TRANSPARENTBAR +# define PP_TRANSPARENTBAR 11 +# define PP_TRANSPARENTBARVERT 12 +#endif // Runtime resolved theme engine function calls @@ -1059,6 +1063,19 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } break; #ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarGroove: + { + Qt::Orientation orient = Qt::Horizontal; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(option)) + orient = pb2->orientation; + partId = (orient == Qt::Horizontal) ? PP_TRANSPARENTBAR : PP_TRANSPARENTBARVERT; + name = QLatin1String("PROGRESS"); + stateId = 1; + + XPThemeData theme(widget, painter, name, partId, stateId, rect); + d->drawBackground(theme); + } + break; case CE_ProgressBarContents: if (const QStyleOptionProgressBar *bar = qstyleoption_cast(option)) { -- cgit v0.12 From 8be3168aa2f300f9a93a53b417704f3f10b1dc8b Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 30 Jun 2011 17:31:36 +0200 Subject: Use name for combobox on Unix. This is more conforming to the AT-SPI specs. Also we have working relations for the label when a buddy is set. Reviewed-by: Gabi --- src/gui/widgets/qcombobox.cpp | 18 ++++++++++++++++++ src/plugins/accessible/widgets/complexwidgets.cpp | 12 +++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 621cae9..41394e3 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -80,6 +80,9 @@ #if defined(Q_WS_S60) #include "private/qt_s60_p.h" #endif +#ifndef QT_NO_ACCESSIBILITY +#include "qaccessible.h" +#endif QT_BEGIN_NAMESPACE @@ -1018,6 +1021,9 @@ void QComboBoxPrivate::_q_dataChanged(const QModelIndex &topLeft, const QModelIn } q->update(); } +#ifndef QT_NO_ACCESSIBILITY + QAccessible::updateAccessibility(q, 0, QAccessible::NameChanged); +#endif } void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int end) @@ -1271,6 +1277,9 @@ void QComboBoxPrivate::_q_emitCurrentIndexChanged(const QModelIndex &index) Q_Q(QComboBox); emit q->currentIndexChanged(index.row()); emit q->currentIndexChanged(itemText(index)); +#ifndef QT_NO_ACCESSIBILITY + QAccessible::updateAccessibility(q, 0, QAccessible::NameChanged); +#endif } QString QComboBoxPrivate::itemText(const QModelIndex &index) const @@ -2635,6 +2644,9 @@ void QComboBox::clear() { Q_D(QComboBox); d->model->removeRows(0, d->model->rowCount(d->root), d->root); +#ifndef QT_NO_ACCESSIBILITY + QAccessible::updateAccessibility(this, 0, QAccessible::NameChanged); +#endif } /*! @@ -2651,6 +2663,9 @@ void QComboBox::clearEditText() Q_D(QComboBox); if (d->lineEdit) d->lineEdit->clear(); +#ifndef QT_NO_ACCESSIBILITY + QAccessible::updateAccessibility(this, 0, QAccessible::NameChanged); +#endif } /*! @@ -2661,6 +2676,9 @@ void QComboBox::setEditText(const QString &text) Q_D(QComboBox); if (d->lineEdit) d->lineEdit->setText(text); +#ifndef QT_NO_ACCESSIBILITY + QAccessible::updateAccessibility(this, 0, QAccessible::NameChanged); +#endif } /*! diff --git a/src/plugins/accessible/widgets/complexwidgets.cpp b/src/plugins/accessible/widgets/complexwidgets.cpp index 8843d3e..563d3b9 100644 --- a/src/plugins/accessible/widgets/complexwidgets.cpp +++ b/src/plugins/accessible/widgets/complexwidgets.cpp @@ -1776,16 +1776,12 @@ QString QAccessibleComboBox::text(Text t, int child) const switch (t) { case Name: +#ifndef Q_WS_X11 // on Linux we use relations for this, name is text (fall through to Value) if (child == OpenList) str = QComboBox::tr("Open"); else str = QAccessibleWidgetEx::text(t, 0); break; -#ifndef QT_NO_SHORTCUT - case Accelerator: - if (child == OpenList) - str = (QString)QKeySequence(Qt::Key_Down); - // missing break? #endif case Value: if (comboBox()->isEditable()) @@ -1793,6 +1789,12 @@ QString QAccessibleComboBox::text(Text t, int child) const else str = comboBox()->currentText(); break; +#ifndef QT_NO_SHORTCUT + case Accelerator: + if (child == OpenList) + str = (QString)QKeySequence(Qt::Key_Down); + break; +#endif default: break; } -- cgit v0.12 From 3d98456fbaae83e504856df8611ccda5a16e8a90 Mon Sep 17 00:00:00 2001 From: Pierre Rossi Date: Tue, 12 Jul 2011 17:29:46 +0200 Subject: Fix a crash with QGraphicsScene. It happened when the scene gets deleted after ~QApplication has been called. test case: int main(int argc, char *argv[]) { QApplication a(argc, argv); QGraphicsScene *scene = new QGraphicsScene(&a); return 0; } Reviewed-by: Gabi --- src/gui/graphicsview/qgraphicsscene.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 655725b..1551944 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1639,7 +1639,8 @@ QGraphicsScene::~QGraphicsScene() Q_D(QGraphicsScene); // Remove this scene from qApp's global scene list. - qApp->d_func()->scene_list.removeAll(this); + if (!QApplicationPrivate::is_app_closing) + qApp->d_func()->scene_list.removeAll(this); clear(); -- cgit v0.12 From e797ba558dddd45522b5a317316e497e9efc44a8 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 27 Jun 2011 16:28:50 +0200 Subject: 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. Reviewed-by: Gabi --- src/gui/accessible/qaccessible.cpp | 5 + src/gui/accessible/qaccessible.h | 10 +- src/gui/accessible/qaccessible2.h | 112 +++ src/gui/accessible/qaccessible_unix.cpp | 11 + src/gui/itemviews/qabstractitemview.cpp | 95 +- src/gui/itemviews/qabstractitemview.h | 1 + src/gui/itemviews/qabstractitemview_p.h | 1 + src/gui/itemviews/qlistview.cpp | 12 + src/gui/itemviews/qtableview.cpp | 17 + src/gui/itemviews/qtableview_p.h | 5 + src/gui/itemviews/qtreeview.cpp | 52 +- src/gui/itemviews/qtreeview.h | 3 + src/gui/itemviews/qtreeview_p.h | 6 +- src/plugins/accessible/widgets/itemviews.cpp | 1029 ++++++++++++++++++++++ src/plugins/accessible/widgets/itemviews.h | 319 +++++++ src/plugins/accessible/widgets/main.cpp | 22 +- src/plugins/accessible/widgets/widgets.pro | 22 +- tests/auto/qaccessibility/tst_qaccessibility.cpp | 308 +++++++ 18 files changed, 2001 insertions(+), 29 deletions(-) create mode 100644 src/plugins/accessible/widgets/itemviews.cpp create mode 100644 src/plugins/accessible/widgets/itemviews.h diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 337bb99..10e5785 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -1048,6 +1048,11 @@ const QAccessibleInterface *other, int otherChild) const */ /*! + \fn QAccessibleTable2Interface *QAccessibleInterface::table2Interface() + \internal +*/ + +/*! \fn QAccessibleActionInterface *QAccessibleInterface::actionInterface() \internal */ diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index fc03e1c..16869bb 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -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(cast_helper(QAccessible2::ImageInterface)); } + inline QAccessibleTable2Interface *table2Interface() + { return reinterpret_cast(cast_helper(QAccessible2::Table2Interface)); } + private: QAccessible2Interface *cast_helper(QAccessible2::InterfaceType); }; diff --git a/src/gui/accessible/qaccessible2.h b/src/gui/accessible/qaccessible2.h index 5cb0323..106b69e 100644 --- a/src/gui/accessible/qaccessible2.h +++ b/src/gui/accessible/qaccessible2.h @@ -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 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 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 selectedCells() const = 0; + // Returns a list of column indexes currently selected (0 based). + virtual QList selectedColumns() const = 0; + // Returns a list of row indexes currently selected (0 based). + virtual QList 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: diff --git a/src/gui/accessible/qaccessible_unix.cpp b/src/gui/accessible/qaccessible_unix.cpp index a6b7ec3..19fbe78 100644 --- a/src/gui/accessible/qaccessible_unix.cpp +++ b/src/gui/accessible/qaccessible_unix.cpp @@ -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; diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index f53705b..ded4d63 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -60,6 +60,7 @@ #include #ifndef QT_NO_ACCESSIBILITY #include +#include #endif #include @@ -645,6 +646,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)), @@ -675,6 +678,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)), @@ -1058,6 +1063,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 } /*! @@ -2805,7 +2818,7 @@ void QAbstractItemView::editorDestroyed(QObject *editor) */ void QAbstractItemView::setHorizontalStepsPerItem(int steps) { - Q_UNUSED(steps); + Q_UNUSED(steps) // do nothing } @@ -2834,7 +2847,7 @@ int QAbstractItemView::horizontalStepsPerItem() const */ void QAbstractItemView::setVerticalStepsPerItem(int steps) { - Q_UNUSED(steps); + Q_UNUSED(steps) // do nothing } @@ -3267,12 +3280,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 } /*! @@ -3335,27 +3360,72 @@ 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); - if (q->isVisible()) - q->updateEditorGeometries(); +#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 @@ -3373,7 +3443,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 } /*! @@ -3698,7 +3777,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()) { diff --git a/src/gui/itemviews/qabstractitemview.h b/src/gui/itemviews/qabstractitemview.h index cb7b78d..1d0c36e 100644 --- a/src/gui/itemviews/qabstractitemview.h +++ b/src/gui/itemviews/qabstractitemview.h @@ -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()) diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 3ba7227..04babde 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -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); diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index a234fde..a0955d2 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -3168,7 +3168,11 @@ void QListView::currentChanged(const QModelIndex ¤t, 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 diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 617409f..6f532eb 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -3164,10 +3164,16 @@ void QTableView::currentChanged(const QModelIndex ¤t, 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 ¤t, 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 diff --git a/src/gui/itemviews/qtableview_p.h b/src/gui/itemviews/qtableview_p.h index f973acf..dce0ed0 100644 --- a/src/gui/itemviews/qtableview_p.h +++ b/src/gui/itemviews/qtableview_p.h @@ -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; diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 6a992db..9228ac8 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -54,6 +54,7 @@ #include #ifndef QT_NO_ACCESSIBILITY #include +#include #endif #include @@ -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 ¤t, 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 ¤t, 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 ¤t, 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 diff --git a/src/gui/itemviews/qtreeview.h b/src/gui/itemviews/qtreeview.h index 26c7315..b77da4e 100644 --- a/src/gui/itemviews/qtreeview.h +++ b/src/gui/itemviews/qtreeview.h @@ -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) diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h index b6d8458..a9dc452 100644 --- a/src/gui/itemviews/qtreeview_p.h +++ b/src/gui/itemviews/qtreeview_p.h @@ -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 spanningIndexes; diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/plugins/accessible/widgets/itemviews.cpp new file mode 100644 index 0000000..d7432e9 --- /dev/null +++ b/src/plugins/accessible/widgets/itemviews.cpp @@ -0,0 +1,1029 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "itemviews.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifndef QT_NO_ACCESSIBILITY + +QT_BEGIN_NAMESPACE + +QString Q_GUI_EXPORT qt_accStripAmp(const QString &text); + +#ifndef QT_NO_ITEMVIEWS +/* +Implementation of the IAccessible2 table2 interface. Much simpler than +the other table interfaces since there is only the main table and cells: + +TABLE/LIST/TREE + |- HEADER CELL + |- CELL + |- CELL + ... +*/ + +int QAccessibleTable2::logicalIndex(const QModelIndex &index) const +{ + if (!index.isValid()) + return -1; + int vHeader = verticalHeader() ? 1 : 0; + int hHeader = horizontalHeader() ? 1 : 0; + // row * number columns + column + 1 for one based counting + return (index.row() + hHeader)*(index.model()->columnCount() + vHeader) + (index.column() + vHeader) + 1; +} + +QAccessibleInterface *QAccessibleTable2::childFromLogical(int logicalIndex) const +{ + logicalIndex--; // one based counting ftw + int vHeader = verticalHeader() ? 1 : 0; + int hHeader = horizontalHeader() ? 1 : 0; + + int columns = view->model()->columnCount() + vHeader; + + int row = logicalIndex / columns; + int column = logicalIndex % columns; + + if (vHeader) { + if (column == 0) { + if (row == 0) { + return new QAccessibleTable2CornerButton(view); + } + return new QAccessibleTable2HeaderCell(view, row-1, Qt::Vertical); + } + --column; + } + if (hHeader) { + if (row == 0) { + return new QAccessibleTable2HeaderCell(view, column, Qt::Horizontal); + } + --row; + } + return new QAccessibleTable2Cell(view, view->model()->index(row, column), cellRole()); +} + +QAccessibleTable2::QAccessibleTable2(QWidget *w) + : QAccessibleObjectEx(w) +{ + view = qobject_cast(w); + Q_ASSERT(view); + + if (qobject_cast(view)) { + m_role = QAccessible::Table; + } else if (qobject_cast(view)) { + m_role = QAccessible::Tree; + } else if (qobject_cast(view)) { + m_role = QAccessible::List; + } else { + // is this our best guess? + m_role = QAccessible::Table; + } +} + +QAccessibleTable2::~QAccessibleTable2() +{ +} + +QHeaderView *QAccessibleTable2::horizontalHeader() const +{ + QHeaderView *header = 0; + if (false) { +#ifndef QT_NO_TABLEVIEW + } else if (const QTableView *tv = qobject_cast(view)) { + header = tv->horizontalHeader(); +#endif +#ifndef QT_NO_TREEVIEW + } else if (const QTreeView *tv = qobject_cast(view)) { + header = tv->header(); +#endif + } + return header; +} + +QHeaderView *QAccessibleTable2::verticalHeader() const +{ + QHeaderView *header = 0; + if (false) { +#ifndef QT_NO_TABLEVIEW + } else if (const QTableView *tv = qobject_cast(view)) { + header = tv->verticalHeader(); +#endif + } + return header; +} + +void QAccessibleTable2::modelReset() +{} + +void QAccessibleTable2::rowsInserted(const QModelIndex &, int first, int last) +{ + lastChange.firstRow = first; + lastChange.lastRow = last; + lastChange.firstColumn = 0; + lastChange.lastColumn = 0; + lastChange.type = QAccessible2::TableModelChangeInsert; +} + +void QAccessibleTable2::rowsRemoved(const QModelIndex &, int first, int last) +{ + lastChange.firstRow = first; + lastChange.lastRow = last; + lastChange.firstColumn = 0; + lastChange.lastColumn = 0; + lastChange.type = QAccessible2::TableModelChangeDelete; +} + +void QAccessibleTable2::columnsInserted(const QModelIndex &, int first, int last) +{ + lastChange.firstRow = 0; + lastChange.lastRow = 0; + lastChange.firstColumn = first; + lastChange.lastColumn = last; + lastChange.type = QAccessible2::TableModelChangeInsert; +} + +void QAccessibleTable2::columnsRemoved(const QModelIndex &, int first, int last) +{ + lastChange.firstRow = 0; + lastChange.lastRow = 0; + lastChange.firstColumn = first; + lastChange.lastColumn = last; + lastChange.type = QAccessible2::TableModelChangeDelete; +} + +void QAccessibleTable2::rowsMoved( const QModelIndex &, int, int, const QModelIndex &, int) +{ + lastChange.firstRow = 0; + lastChange.lastRow = 0; + lastChange.firstColumn = 0; + lastChange.lastColumn = 0; + lastChange.type = QAccessible2::TableModelChangeUpdate; +} + +void QAccessibleTable2::columnsMoved( const QModelIndex &, int, int, const QModelIndex &, int) +{ + lastChange.firstRow = 0; + lastChange.lastRow = 0; + lastChange.firstColumn = 0; + lastChange.lastColumn = 0; + lastChange.type = QAccessible2::TableModelChangeUpdate; +} + +QAccessibleTable2Cell *QAccessibleTable2::cell(const QModelIndex &index) const +{ + if (index.isValid()) + return new QAccessibleTable2Cell(view, index, cellRole()); + return 0; +} + +QAccessibleTable2CellInterface *QAccessibleTable2::cellAt(int row, int column) const +{ + Q_ASSERT(role(0) != QAccessible::Tree); + QModelIndex index = view->model()->index(row, column); + //Q_ASSERT(index.isValid()); + if (!index.isValid()) { + qWarning() << "QAccessibleTable2::cellAt: invalid index: " << index << " for " << view; + return 0; + } + return cell(index); +} + +QAccessibleInterface *QAccessibleTable2::caption() const +{ + return 0; +} + +QString QAccessibleTable2::columnDescription(int column) const +{ + return view->model()->headerData(column, Qt::Horizontal).toString(); +} + +int QAccessibleTable2::columnCount() const +{ + return view->model()->columnCount(); +} + +int QAccessibleTable2::rowCount() const +{ + return view->model()->rowCount(); +} + +int QAccessibleTable2::selectedCellCount() const +{ + return view->selectionModel()->selectedIndexes().count(); +} + +int QAccessibleTable2::selectedColumnCount() const +{ + return view->selectionModel()->selectedColumns().count(); +} + +int QAccessibleTable2::selectedRowCount() const +{ + return view->selectionModel()->selectedRows().count(); +} + +QString QAccessibleTable2::rowDescription(int row) const +{ + return view->model()->headerData(row, Qt::Vertical).toString(); +} + +QList QAccessibleTable2::selectedCells() const +{ + QList cells; + Q_FOREACH (const QModelIndex &index, view->selectionModel()->selectedIndexes()) { + cells.append(cell(index)); + } + return cells; +} + +QList QAccessibleTable2::selectedColumns() const +{ + QList columns; + Q_FOREACH(const QModelIndex &index, view->selectionModel()->selectedColumns()) { + columns.append(index.column()); + } + return columns; +} + +QList QAccessibleTable2::selectedRows() const +{ + QList rows; + Q_FOREACH(const QModelIndex &index, view->selectionModel()->selectedRows()) { + rows.append(index.row()); + } + return rows; +} + +QAccessibleInterface *QAccessibleTable2::summary() const +{ + return 0; +} + +bool QAccessibleTable2::isColumnSelected(int column) const +{ + return view->selectionModel()->isColumnSelected(column, QModelIndex()); +} + +bool QAccessibleTable2::isRowSelected(int row) const +{ + return view->selectionModel()->isRowSelected(row, QModelIndex()); +} + +bool QAccessibleTable2::selectRow(int row) +{ + QModelIndex index = view->model()->index(row, 0); + if (!index.isValid() || view->selectionMode() & QAbstractItemView::NoSelection) + return false; + view->selectionModel()->select(index, QItemSelectionModel::Select); + return true; +} + +bool QAccessibleTable2::selectColumn(int column) +{ + QModelIndex index = view->model()->index(0, column); + if (!index.isValid() || view->selectionMode() & QAbstractItemView::NoSelection) + return false; + view->selectionModel()->select(index, QItemSelectionModel::Select); + return true; +} + +bool QAccessibleTable2::unselectRow(int row) +{ + QModelIndex index = view->model()->index(row, 0); + if (!index.isValid() || view->selectionMode() & QAbstractItemView::NoSelection) + return false; + view->selectionModel()->select(index, QItemSelectionModel::Deselect); + return true; +} + +bool QAccessibleTable2::unselectColumn(int column) +{ + QModelIndex index = view->model()->index(0, column); + if (!index.isValid() || view->selectionMode() & QAbstractItemView::NoSelection) + return false; + view->selectionModel()->select(index, QItemSelectionModel::Columns & QItemSelectionModel::Deselect); + return true; +} + +QAccessible2::TableModelChange QAccessibleTable2::modelChange() const +{ + QAccessible2::TableModelChange change; + // FIXME + return change; +} + +QAccessible::Role QAccessibleTable2::role(int child) const +{ + Q_ASSERT(child >= 0); + if (child > 0) + return QAccessible::Cell; + return m_role; +} + +QAccessible::State QAccessibleTable2::state(int child) const +{ + Q_ASSERT(child == 0); + return QAccessible::Normal | HasInvokeExtension; +} + +int QAccessibleTable2::childAt(int x, int y) const +{ + QPoint viewportOffset = view->viewport()->mapTo(view, QPoint(0,0)); + QPoint indexPosition = view->mapFromGlobal(QPoint(x, y) - viewportOffset); + // FIXME: if indexPosition < 0 in one coordinate, return header + + QModelIndex index = view->indexAt(indexPosition); + if (index.isValid()) { + return logicalIndex(index); + } + return -1; +} + +int QAccessibleTable2::childCount() const +{ + int vHeader = verticalHeader() ? 1 : 0; + int hHeader = horizontalHeader() ? 1 : 0; + return (view->model()->rowCount()+hHeader) * (view->model()->columnCount()+vHeader); +} + +int QAccessibleTable2::indexOfChild(const QAccessibleInterface *iface) const +{ + Q_ASSERT(iface->role(0) != QAccessible::TreeItem); // should be handled by tree class + if (iface->role(0) == QAccessible::Cell || iface->role(0) == QAccessible::ListItem) { + const QAccessibleTable2Cell* cell = static_cast(iface); + return logicalIndex(cell->m_index); + } else if (iface->role(0) == QAccessible::ColumnHeader){ + const QAccessibleTable2HeaderCell* cell = static_cast(iface); + return cell->index + (verticalHeader() ? 1 : 0) + 1; + } else if (iface->role(0) == QAccessible::RowHeader){ + const QAccessibleTable2HeaderCell* cell = static_cast(iface); + return (cell->index+1) * (view->model()->rowCount()+1) + 1; + } else if (iface->role(0) == QAccessible::Pane) { + return 1; // corner button + } else { + qWarning() << "WARNING QAccessibleTable2::indexOfChild Fix my children..." + << iface->role(0) << iface->text(QAccessible::Name, 0); + } + // FIXME: we are in denial of our children. this should stop. + return -1; +} + +QString QAccessibleTable2::text(Text t, int child) const +{ + Q_ASSERT(child == 0); + if (t == QAccessible::Description) + return view->accessibleDescription(); + return view->accessibleName(); +} + +QRect QAccessibleTable2::rect(int child) const +{ + Q_ASSERT(!child); + if (!view->isVisible()) + return QRect(); + QPoint pos = view->mapToGlobal(QPoint(0, 0)); + return QRect(pos.x(), pos.y(), view->width(), view->height()); +} + +int QAccessibleTable2::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const +{ + *iface = 0; + switch (relation) { + case Ancestor: { + if (index == 1 && view->parent()) { + *iface = QAccessible::queryAccessibleInterface(view->parent()); + if (*iface) + return 0; + } + break; + } + case QAccessible::Child: { + Q_ASSERT(index > 0); + *iface = childFromLogical(index); + if (*iface) { + return 0; + } + break; + } + default: + break; + } + return -1; +} + +QAccessible::Relation QAccessibleTable2::relationTo(int, const QAccessibleInterface *, int) const +{ + return QAccessible::Unrelated; +} + +#ifndef QT_NO_ACTION +int QAccessibleTable2::userActionCount(int) const +{ + return 0; +} +QString QAccessibleTable2::actionText(int, Text, int) const +{ + return QString(); +} +bool QAccessibleTable2::doAction(int, int, const QVariantList &) +{ + return false; +} +#endif + + +// TREE VIEW + +QModelIndex QAccessibleTree::indexFromLogical(int row, int column) const +{ + const QTreeView *treeView = qobject_cast(view); + QModelIndex modelIndex = treeView->d_func()->viewItems.at(row).index; + + if (modelIndex.isValid() && column > 0) { + modelIndex = view->model()->index(modelIndex.row(), column, modelIndex.parent()); + } + return modelIndex; +} + +int QAccessibleTree::childAt(int x, int y) const +{ + QPoint viewportOffset = view->viewport()->mapTo(view, QPoint(0,0)); + QPoint indexPosition = view->mapFromGlobal(QPoint(x, y) - viewportOffset); + + QModelIndex index = view->indexAt(indexPosition); + if (!index.isValid()) + return -1; + + const QTreeView *treeView = qobject_cast(view); + int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0); + int column = index.column(); + + int i = row * view->model()->columnCount() + column + 1; + Q_ASSERT(i > view->model()->columnCount()); + return i; +} + +int QAccessibleTree::childCount() const +{ + const QTreeView *treeView = qobject_cast(view); + Q_ASSERT(treeView); + if (!view->model()) + return 0; + + int hHeader = horizontalHeader() ? 1 : 0; + return (treeView->d_func()->viewItems.count() + hHeader)* view->model()->columnCount(); +} + +int QAccessibleTree::rowCount() const +{ + const QTreeView *treeView = qobject_cast(view); + Q_ASSERT(treeView); + return treeView->d_func()->viewItems.count(); +} + +int QAccessibleTree::indexOfChild(const QAccessibleInterface *iface) const +{ + if (iface->role(0) == QAccessible::TreeItem) { + const QAccessibleTable2Cell* cell = static_cast(iface); + const QTreeView *treeView = qobject_cast(view); + Q_ASSERT(treeView); + int row = treeView->d_func()->viewIndex(cell->m_index) + (horizontalHeader() ? 1 : 0); + int column = cell->m_index.column(); + + int index = row * view->model()->columnCount() + column + 1; + //qDebug() << "QAccessibleTree::indexOfChild r " << row << " c " << column << "index " << index; + Q_ASSERT(index > treeView->model()->columnCount()); + return index; + } else if (iface->role(0) == QAccessible::ColumnHeader){ + const QAccessibleTable2HeaderCell* cell = static_cast(iface); + //qDebug() << "QAccessibleTree::indexOfChild header " << cell->index << "is: " << cell->index + 1; + return cell->index + 1; + } else { + qWarning() << "WARNING QAccessibleTable2::indexOfChild invalid child" + << iface->role(0) << iface->text(QAccessible::Name, 0); + } + // FIXME: add scrollbars and don't just ignore them + return -1; +} + +int QAccessibleTree::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const +{ + switch (relation) { + case QAccessible::Child: { + Q_ASSERT(index > 0); + --index; + int hHeader = horizontalHeader() ? 1 : 0; + + if (hHeader) { + if (index < view->model()->columnCount()) { + *iface = new QAccessibleTable2HeaderCell(view, index, Qt::Horizontal); + return 0; + } else { + index -= view->model()->columnCount(); + } + } + + int row = index / view->model()->columnCount(); + int column = index % view->model()->columnCount(); + QModelIndex modelIndex = indexFromLogical(row, column); + if (modelIndex.isValid()) { + *iface = cell(modelIndex); + return 0; + } + return -1; + } + default: + break; + } + return QAccessibleTable2::navigate(relation, index, iface); +} + +QAccessible::Relation QAccessibleTree::relationTo(int, const QAccessibleInterface *, int) const +{ + return QAccessible::Unrelated; +} + +QAccessibleTable2CellInterface *QAccessibleTree::cellAt(int row, int column) const +{ + QModelIndex index = indexFromLogical(row, column); + if (!index.isValid()) { + qWarning() << "Requested invalid tree cell: " << row << column; + return 0; + } + return new QAccessibleTable2Cell(view, index, cellRole()); +} + +QString QAccessibleTree::rowDescription(int) const +{ + return QString(); // no headers for rows in trees +} + +bool QAccessibleTree::isRowSelected(int row) const +{ + QModelIndex index = indexFromLogical(row); + return view->selectionModel()->isRowSelected(index.row(), index.parent()); +} + +bool QAccessibleTree::selectRow(int row) +{ + QModelIndex index = indexFromLogical(row); + if (!index.isValid() || view->selectionMode() & QAbstractItemView::NoSelection) + return false; + view->selectionModel()->select(index, QItemSelectionModel::Select); + return true; +} + +// TABLE CELL + +QAccessibleTable2Cell::QAccessibleTable2Cell(QAbstractItemView *view_, const QModelIndex &index_, QAccessible::Role role_) + : /* QAccessibleSimpleEditableTextInterface(this), */ view(view_), m_index(index_), m_role(role_) +{ + Q_ASSERT(index_.isValid()); +} + +int QAccessibleTable2Cell::columnExtent() const { return 1; } +int QAccessibleTable2Cell::rowExtent() const { return 1; } + +QList QAccessibleTable2Cell::rowHeaderCells() const +{ + QList headerCell; + if (verticalHeader()) { + headerCell.append(new QAccessibleTable2HeaderCell(view, m_index.row(), Qt::Vertical)); + } + return headerCell; +} + +QList QAccessibleTable2Cell::columnHeaderCells() const +{ + QList headerCell; + if (horizontalHeader()) { + headerCell.append(new QAccessibleTable2HeaderCell(view, m_index.column(), Qt::Horizontal)); + } + return headerCell; +} + +QHeaderView *QAccessibleTable2Cell::horizontalHeader() const +{ + QHeaderView *header = 0; + + if (false) { +#ifndef QT_NO_TABLEVIEW + } else if (const QTableView *tv = qobject_cast(view)) { + header = tv->horizontalHeader(); +#endif +#ifndef QT_NO_TREEVIEW + } else if (const QTreeView *tv = qobject_cast(view)) { + header = tv->header(); +#endif + } + + return header; +} + +QHeaderView *QAccessibleTable2Cell::verticalHeader() const +{ + QHeaderView *header = 0; +#ifndef QT_NO_TABLEVIEW + if (const QTableView *tv = qobject_cast(view)) + header = tv->verticalHeader(); +#endif + return header; +} + +int QAccessibleTable2Cell::columnIndex() const +{ + return m_index.column(); +} + +int QAccessibleTable2Cell::rowIndex() const +{ + if (role(0) == QAccessible::TreeItem) { + const QTreeView *treeView = qobject_cast(view); + Q_ASSERT(treeView); + int row = treeView->d_func()->viewIndex(m_index); + return row; + } + return m_index.row(); +} + +bool QAccessibleTable2Cell::isSelected() const +{ + return view->selectionModel()->isSelected(m_index); +} + +void QAccessibleTable2Cell::rowColumnExtents(int *row, int *column, int *rowExtents, int *columnExtents, bool *selected) const +{ + *row = m_index.row(); + *column = m_index.column(); + *rowExtents = 1; + *columnExtents = 1; + *selected = isSelected(); +} + +QAccessibleTable2Interface* QAccessibleTable2Cell::table() const +{ + return QAccessible::queryAccessibleInterface(view)->table2Interface(); +} + +QAccessible::Role QAccessibleTable2Cell::role(int child) const +{ + Q_ASSERT(child == 0); + return m_role; +} + +QAccessible::State QAccessibleTable2Cell::state(int child) const +{ + Q_ASSERT(child == 0); + State st = Normal; + + QRect globalRect = view->rect(); + globalRect.translate(view->mapToGlobal(QPoint(0,0))); + if (!globalRect.intersects(rect(0))) + st |= Invisible; + + if (view->selectionModel()->isSelected(m_index)) + st |= Selected; + if (view->selectionModel()->currentIndex() == m_index) + st |= Focused; + if (m_index.model()->data(m_index, Qt::CheckStateRole).toInt() == Qt::Checked) + st |= Checked; + + Qt::ItemFlags flags = m_index.flags(); + if (flags & Qt::ItemIsSelectable) { + st |= Selectable; + st |= Focusable; + if (view->selectionMode() == QAbstractItemView::MultiSelection) + st |= MultiSelectable; + if (view->selectionMode() == QAbstractItemView::ExtendedSelection) + st |= ExtSelectable; + } + if (m_role == QAccessible::TreeItem) { + const QTreeView *treeView = qobject_cast(view); + if (treeView->isExpanded(m_index)) + st |= Expanded; + } + return st; +} + +bool QAccessibleTable2Cell::isExpandable() const +{ + return view->model()->hasChildren(m_index); +} + +QRect QAccessibleTable2Cell::rect(int child) const +{ + Q_ASSERT(child == 0); + + QRect r; + r = view->visualRect(m_index); + + if (!r.isNull()) + r.translate(view->viewport()->mapTo(view, QPoint(0,0))); + r.translate(view->mapToGlobal(QPoint(0, 0))); + return r; +} + +QString QAccessibleTable2Cell::text(Text t, int child) const +{ + Q_ASSERT(child == 0); + QAbstractItemModel *model = view->model(); + QString value; + switch(t) { + case QAccessible::Value: + case QAccessible::Name: + value = model->data(m_index, Qt::AccessibleTextRole).toString(); + if (value.isEmpty()) + value = model->data(m_index, Qt::DisplayRole).toString(); + break; + case QAccessible::Description: + value = model->data(m_index, Qt::AccessibleDescriptionRole).toString(); + break; + default: + break; + } + return value; +} + +void QAccessibleTable2Cell::setText(Text /*t*/, int child, const QString &text) +{ + Q_ASSERT(child == 0); + if (!m_index.flags() & Qt::ItemIsEditable) + return; + view->model()->setData(m_index, text); +} + +bool QAccessibleTable2Cell::isValid() const +{ + if (!m_index.isValid()) { + qDebug() << "Interface is not valid"; + } + + return m_index.isValid(); +} + +int QAccessibleTable2Cell::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const +{ + if (relation == Ancestor && index == 1) { + if (m_role == QAccessible::TreeItem) { + *iface = new QAccessibleTree(view); + } else { + *iface = new QAccessibleTable2(view); + } + return 0; + } + + *iface = 0; + if (!view) + return -1; + + switch (relation) { + + case Child: { + return -1; + } + case Sibling: + if (index > 0) { + QAccessibleInterface *parent = queryAccessibleInterface(view); + int ret = parent->navigate(QAccessible::Child, index, iface); + delete parent; + if (*iface) + return ret; + } + return -1; + +// From table1 implementation: +// case Up: +// case Down: +// case Left: +// case Right: { +// // This is in the "not so nice" category. In order to find out which item +// // is geometrically around, we have to set the current index, navigate +// // and restore the index as well as the old selection +// view->setUpdatesEnabled(false); +// const QModelIndex oldIdx = view->currentIndex(); +// QList kids = children(); +// const QModelIndex currentIndex = index ? kids.at(index - 1) : QModelIndex(row); +// const QItemSelection oldSelection = view->selectionModel()->selection(); +// view->setCurrentIndex(currentIndex); +// const QModelIndex idx = view->moveCursor(toCursorAction(relation), Qt::NoModifier); +// view->setCurrentIndex(oldIdx); +// view->selectionModel()->select(oldSelection, QItemSelectionModel::ClearAndSelect); +// view->setUpdatesEnabled(true); +// if (!idx.isValid()) +// return -1; + +// if (idx.parent() != row.parent() || idx.row() != row.row()) +// *iface = cell(idx); +// return index ? kids.indexOf(idx) + 1 : 0; } + default: + break; + } + + return -1; +} + +QAccessible::Relation QAccessibleTable2Cell::relationTo(int child, const QAccessibleInterface *other, int otherChild) const +{ + Q_ASSERT(child == 0); + Q_ASSERT(otherChild == 0); + // we only check for parent-child relationships in trees + if (m_role == QAccessible::TreeItem && other->role(0) == QAccessible::TreeItem) { + QModelIndex otherIndex = static_cast(other)->m_index; + // is the other our parent? + if (otherIndex.parent() == m_index) + return QAccessible::Ancestor; + // are we the other's child? + if (m_index.parent() == otherIndex) + return QAccessible::Child; + } + return QAccessible::Unrelated; +} + +#ifndef QT_NO_ACTION +int QAccessibleTable2Cell::userActionCount(int) const +{ + return 0; +} + +QString QAccessibleTable2Cell::actionText(int, Text, int) const +{ + return QString(); +} + +bool QAccessibleTable2Cell::doAction(int, int, const QVariantList &) +{ + return false; +} + +QAccessibleTable2HeaderCell::QAccessibleTable2HeaderCell(QAbstractItemView *view_, int index_, Qt::Orientation orientation_) + : view(view_), index(index_), orientation(orientation_) +{ + Q_ASSERT(index_ >= 0); +} + +QAccessible::Role QAccessibleTable2HeaderCell::role(int child) const +{ + Q_ASSERT(child == 0); + if (orientation == Qt::Horizontal) + return QAccessible::ColumnHeader; + return QAccessible::RowHeader; +} + +QAccessible::State QAccessibleTable2HeaderCell::state(int child) const +{ + Q_ASSERT(child == 0); + return QAccessible::Normal; +} + +QRect QAccessibleTable2HeaderCell::rect(int child) const +{ + Q_ASSERT(child == 0); + + QHeaderView *header = 0; + if (false) { +#ifndef QT_NO_TABLEVIEW + } else if (const QTableView *tv = qobject_cast(view)) { + if (orientation == Qt::Horizontal) { + header = tv->horizontalHeader(); + } else { + header = tv->verticalHeader(); + } +#endif +#ifndef QT_NO_TREEVIEW + } else if (const QTreeView *tv = qobject_cast(view)) { + header = tv->header(); +#endif + } + QPoint zero = header->mapToGlobal(QPoint(0, 0)); + int sectionSize = header->sectionSize(index); + int sectionPos = header->sectionPosition(index); + return orientation == Qt::Horizontal + ? QRect(zero.x() + sectionPos, zero.y(), sectionSize, header->height()) + : QRect(zero.x(), zero.y() + sectionPos, header->width(), sectionSize); +} + +QString QAccessibleTable2HeaderCell::text(Text t, int child) const +{ + Q_ASSERT(child == 0); + QAbstractItemModel *model = view->model(); + QString value; + switch (t) { + case QAccessible::Value: + case QAccessible::Name: + value = model->headerData(index, orientation, Qt::AccessibleTextRole).toString(); + if (value.isEmpty()) + value = model->headerData(index, orientation, Qt::DisplayRole).toString(); + break; + case QAccessible::Description: + value = model->headerData(index, orientation, Qt::AccessibleDescriptionRole).toString(); + break; + default: + break; + } + return value; +} + +void QAccessibleTable2HeaderCell::setText(Text, int, const QString &) +{ + return; +} + +bool QAccessibleTable2HeaderCell::isValid() const +{ + return true; +} + +int QAccessibleTable2HeaderCell::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const +{ + if (relation == QAccessible::Ancestor && index == 1) { + if (false) { +#ifndef QT_NO_TREEVIEW + } else if (qobject_cast(view)) { + *iface = new QAccessibleTree(view); + return 0; +#endif + } else { + *iface = new QAccessibleTable2(view); + return 0; + } + } + *iface = 0; + return -1; +} + +QAccessible::Relation QAccessibleTable2HeaderCell::relationTo(int, const QAccessibleInterface *, int) const +{ + return QAccessible::Unrelated; +} + +#ifndef QT_NO_ACTION +int QAccessibleTable2HeaderCell::userActionCount(int) const +{ + return 0; +} + +QString QAccessibleTable2HeaderCell::actionText(int, Text, int) const +{ + return QString(); +} + +bool QAccessibleTable2HeaderCell::doAction(int, int, const QVariantList &) +{ + return false; +} +#endif + + + +#endif + +#endif // QT_NO_ITEMVIEWS + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/accessible/widgets/itemviews.h b/src/plugins/accessible/widgets/itemviews.h new file mode 100644 index 0000000..c8492e3 --- /dev/null +++ b/src/plugins/accessible/widgets/itemviews.h @@ -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 +#include +#include +#include +#include + + +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 ¶ms); +#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 selectedCells() const; + virtual QList selectedColumns() const; + virtual QList 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 ¶ms); +#endif + + // cell interface + virtual int columnExtent() const; + virtual QList columnHeaderCells() const; + virtual int columnIndex() const; + virtual int rowExtent() const; + virtual QList 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 ¶ms); +#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 diff --git a/src/plugins/accessible/widgets/main.cpp b/src/plugins/accessible/widgets/main.cpp index aa5459c..cd17a6e 100644 --- a/src/plugins/accessible/widgets/main.cpp +++ b/src/plugins/accessible/widgets/main.cpp @@ -44,11 +44,13 @@ #include "simplewidgets.h" #include "rangecontrols.h" #include "complexwidgets.h" +#include "itemviews.h" #include #include #include #include +#include #include #include @@ -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(widget)) { + iface = new QAccessibleTree(widget); + } else { + iface = new QAccessibleTable2(widget); + } + } else if (classname == QLatin1String("QWidget") + && widget->objectName() == QLatin1String("qt_scrollarea_viewport") + && qobject_cast(widget->parentWidget())) { + if (qobject_cast(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(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); diff --git a/src/plugins/accessible/widgets/widgets.pro b/src/plugins/accessible/widgets/widgets.pro index 79110cb..9632f41 100644 --- a/src/plugins/accessible/widgets/widgets.pro +++ b/src/plugins/accessible/widgets/widgets.pro @@ -7,14 +7,18 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/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 + + diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index d764187..f8d6b6d 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -270,6 +270,9 @@ private slots: void scrollAreaTest(); void tableWidgetTest(); void tableViewTest(); + void table2ListTest(); + void table2TreeTest(); + void table2TableTest(); void calendarWidgetTest(); void dockWidgetTest(); void pushButtonTest(); @@ -3725,6 +3728,311 @@ void tst_QAccessibility::tableViewTest() QTestAccessibility::clearEvents(); } +void tst_QAccessibility::table2ListTest() +{ + QListWidget listView; + 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((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; + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::table2TreeTest() +{ + QTreeWidget treeView; + 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); + + 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 +// QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&treeView, 0, QAccessible::TableModelChanged))); + + 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(); +} + + +void tst_QAccessibility::table2TableTest() +{ + QTableWidget tableView(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); + + 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::PushButton); + 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(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; + QTestAccessibility::clearEvents(); +} + void tst_QAccessibility::calendarWidgetTest() { #ifndef QT_NO_CALENDARWIDGET -- cgit v0.12 From eff5ecc5d8f65fa25d6cfd6ed96a9d2a00d0c663 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 13 Jul 2011 16:53:01 +0200 Subject: Style cleanup - space after flow control keywords. Reviewed-by: TrustMe --- src/plugins/accessible/widgets/itemviews.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/plugins/accessible/widgets/itemviews.cpp index d7432e9..4618f87 100644 --- a/src/plugins/accessible/widgets/itemviews.cpp +++ b/src/plugins/accessible/widgets/itemviews.cpp @@ -284,7 +284,7 @@ QList QAccessibleTable2::selectedCells() const QList QAccessibleTable2::selectedColumns() const { QList columns; - Q_FOREACH(const QModelIndex &index, view->selectionModel()->selectedColumns()) { + Q_FOREACH (const QModelIndex &index, view->selectionModel()->selectedColumns()) { columns.append(index.column()); } return columns; @@ -293,7 +293,7 @@ QList QAccessibleTable2::selectedColumns() const QList QAccessibleTable2::selectedRows() const { QList rows; - Q_FOREACH(const QModelIndex &index, view->selectionModel()->selectedRows()) { + Q_FOREACH (const QModelIndex &index, view->selectionModel()->selectedRows()) { rows.append(index.row()); } return rows; @@ -773,7 +773,7 @@ QString QAccessibleTable2Cell::text(Text t, int child) const Q_ASSERT(child == 0); QAbstractItemModel *model = view->model(); QString value; - switch(t) { + switch (t) { case QAccessible::Value: case QAccessible::Name: value = model->data(m_index, Qt::AccessibleTextRole).toString(); -- cgit v0.12 From d29876008fad400bca8d6b37e5d5f61dd1bcb39d Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 14 Jul 2011 09:40:06 +0200 Subject: Fix autotest for accessible tables. The new table2 interface is ifdef'ed to only be used on X11. This adapts the auto test. 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: TrustMe --- tests/auto/qaccessibility/tst_qaccessibility.cpp | 147 +++++++++++++++-------- 1 file changed, 97 insertions(+), 50 deletions(-) diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index f8d6b6d..2db9f75 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -190,7 +190,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); } @@ -307,6 +308,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"; @@ -1755,18 +1760,22 @@ 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; + QVERIFY_EVENT(mw, 0, QAccessible::ObjectHide); + QTestAccessibility::clearEvents(); } class CounterButton : public QPushButton { @@ -2752,9 +2761,12 @@ 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); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); QVERIFY(iface); QCOMPARE(iface->childCount(), 1); delete iface; @@ -2768,11 +2780,11 @@ void tst_QAccessibility::listViewTest() listView.show(); QTest::qWait(1); // Need this for indexOfchild to work. #if defined(Q_WS_X11) - qt_x11_wait_for_window_manager(&listView); + qt_x11_wait_for_window_manager(listView); QTest::qWait(100); #endif - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); QCOMPARE((int)iface->role(0), (int)QAccessible::Client); QCOMPARE((int)iface->role(1), (int)QAccessible::List); QCOMPARE(iface->childCount(), 1); @@ -2817,6 +2829,7 @@ void tst_QAccessibility::listViewTest() } QTestAccessibility::clearEvents(); +#endif } @@ -3071,9 +3084,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); @@ -3116,6 +3131,7 @@ void tst_QAccessibility::lineEditTest() delete iface; delete toplevel; + QTestAccessibility::clearEvents(); } void tst_QAccessibility::workspaceTest() @@ -3526,6 +3542,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); @@ -3565,6 +3584,7 @@ void tst_QAccessibility::tableWidgetTest() delete topLevel; } QTestAccessibility::clearEvents(); +#endif } class QtTestTableModel: public QAbstractTableModel @@ -3647,6 +3667,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(); @@ -3726,23 +3749,28 @@ void tst_QAccessibility::tableViewTest() delete model; } QTestAccessibility::clearEvents(); +#endif } void tst_QAccessibility::table2ListTest() { - QListWidget listView; - listView.addItem("Oslo"); - listView.addItem("Berlin"); - listView.addItem("Brisbane"); - listView.resize(400,400); - listView.show(); +#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); + qt_x11_wait_for_window_manager(listView); QTest::qWait(100); #endif - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); + QCOMPARE(verifyHierarchy(iface), 0); QCOMPARE((int)iface->role(0), (int)QAccessible::List); QCOMPARE(iface->childCount(), 3); @@ -3771,14 +3799,14 @@ void tst_QAccessibility::table2ListTest() 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"); + 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 @@ -3799,23 +3827,27 @@ void tst_QAccessibility::table2ListTest() delete cell4; delete cell1; - delete iface; + delete listView; QTestAccessibility::clearEvents(); +#endif } void tst_QAccessibility::table2TreeTest() { - QTreeWidget treeView; - treeView.setColumnCount(2); +#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); + treeView->setHeaderItem(header); QTreeWidgetItem *root1 = new QTreeWidgetItem; root1->setText(0, "Spain"); - treeView.addTopLevelItem(root1); + treeView->addTopLevelItem(root1); QTreeWidgetItem *item1 = new QTreeWidgetItem; item1->setText(0, "Picasso"); @@ -3829,22 +3861,24 @@ void tst_QAccessibility::table2TreeTest() QTreeWidgetItem *root2 = new QTreeWidgetItem; root2->setText(0, "Austria"); - treeView.addTopLevelItem(root2); + 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(); + 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); + qt_x11_wait_for_window_manager(treeView); QTest::qWait(100); #endif - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&treeView); + 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) @@ -3897,14 +3931,13 @@ void tst_QAccessibility::table2TreeTest() delete cell2; delete cell1; - treeView.expandAll(); + treeView->expandAll(); QTest::qWait(1); // Need this for indexOfchild to work. #if defined(Q_WS_X11) - qt_x11_wait_for_window_manager(&treeView); + qt_x11_wait_for_window_manager(treeView); QTest::qWait(100); #endif -// QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&treeView, 0, QAccessible::TableModelChanged))); QCOMPARE(table2->columnCount(), 2); QCOMPARE(table2->rowCount(), 5); @@ -3925,36 +3958,42 @@ void tst_QAccessibility::table2TreeTest() delete iface; QTestAccessibility::clearEvents(); +#endif } void tst_QAccessibility::table2TableTest() { - QTableWidget tableView(3, 3); - tableView.setColumnCount(3); +#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); + tableView->setHorizontalHeaderLabels(hHeader); QStringList vHeader; vHeader << "v1" << "v2" << "v3"; - tableView.setVerticalHeaderLabels(vHeader); + 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->setItem(i/3, i%3, item); } - tableView.resize(600,600); - tableView.show(); + 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); + qt_x11_wait_for_window_manager(tableView); QTest::qWait(100); #endif - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&tableView); + 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) @@ -3964,7 +4003,7 @@ void tst_QAccessibility::table2TableTest() QCOMPARE(iface->navigate(QAccessible::Child, 1, &cornerButton), 0); QVERIFY(cornerButton); QCOMPARE(iface->indexOfChild(cornerButton), 1); - QCOMPARE(cornerButton->role(0), QAccessible::PushButton); + QCOMPARE(cornerButton->role(0), QAccessible::Pane); delete cornerButton; QAccessibleInterface *child1 = 0; @@ -4030,7 +4069,11 @@ void tst_QAccessibility::table2TableTest() QCOMPARE(table2->rowDescription(2), QString("v3")); delete iface; + + delete tableView; + QTestAccessibility::clearEvents(); +#endif } void tst_QAccessibility::calendarWidgetTest() @@ -4288,6 +4331,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); @@ -4345,6 +4391,7 @@ void tst_QAccessibility::treeWidgetTest() delete w; QTestAccessibility::clearEvents(); +#endif } void tst_QAccessibility::labelTest() -- cgit v0.12 From a1f2b68e97477440cf508e6d497eb5f5d9971971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Mill=C3=A1n=20Soto?= Date: Thu, 14 Jul 2011 14:25:57 +0200 Subject: Call QAccessible::updateAccessibility when setText is called on QLabel The method is called when the text of a label is changed and setAccessibleName has not been called on the label, as the text of the label acts as the accessible name of the label. Merge-request: 1301 Reviewed-by: Frederik Gladhorn --- src/gui/widgets/qlabel.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index 26dd0e1..dcf35aa 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -55,6 +55,10 @@ #include "private/qstylesheetstyle_p.h" #include +#ifndef QT_NO_ACCESSIBILITY +#include +#endif + QT_BEGIN_NAMESPACE /*! @@ -370,6 +374,11 @@ void QLabel::setText(const QString &text) #endif d->updateLabel(); + +#ifndef QT_NO_ACCESSIBILITY + if (accessibleName().isEmpty()) + QAccessible::updateAccessibility(this, 0, QAccessible::NameChanged); +#endif } QString QLabel::text() const -- cgit v0.12 From 81036d4be6122dfcb55a4852bcc1037c7d8f7309 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 14 Jul 2011 10:57:02 +0200 Subject: Add constants to QAccessible::Event enum. Reviewed-by: Gabi --- src/gui/accessible/qaccessible.h | 68 ++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index 16869bb..24a6744 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -84,40 +84,40 @@ public: MenuCommand = 0x0018, // Values from IAccessible2 - ActionChanged = 0x0101, - ActiveDescendantChanged, - AttributeChanged, - DocumentContentChanged, - DocumentLoadComplete, - DocumentLoadStopped, - DocumentReload, - HyperlinkEndIndexChanged, - HyperlinkNumberOfAnchorsChanged, - HyperlinkSelectedLinkChanged, - HypertextLinkActivated, - HypertextLinkSelected, - HyperlinkStartIndexChanged, - HypertextChanged, - HypertextNLinksChanged, - ObjectAttributeChanged, - PageChanged, - SectionChanged, - TableCaptionChanged, - TableColumnDescriptionChanged, - TableColumnHeaderChanged, - TableModelChanged, - TableRowDescriptionChanged, - TableRowHeaderChanged, - TableSummaryChanged, - TextAttributeChanged, - TextCaretMoved, - // TextChanged, deprecated, use TextUpdated - TextColumnChanged = TextCaretMoved + 2, - TextInserted, - TextRemoved, - TextUpdated, - TextSelectionChanged, - VisibleDataChanged, + ActionChanged = 0x0101, + ActiveDescendantChanged = 0x0102, + AttributeChanged = 0x0103, + DocumentContentChanged = 0x0104, + DocumentLoadComplete = 0x0105, + DocumentLoadStopped = 0x0106, + DocumentReload = 0x0107, + HyperlinkEndIndexChanged = 0x0108, + HyperlinkNumberOfAnchorsChanged = 0x0109, + HyperlinkSelectedLinkChanged = 0x010A, + HypertextLinkActivated = 0x010B, + HypertextLinkSelected = 0x010C, + HyperlinkStartIndexChanged = 0x010D, + HypertextChanged = 0x010E, + HypertextNLinksChanged = 0x010F, + ObjectAttributeChanged = 0x0110, + PageChanged = 0x0111, + SectionChanged = 0x0112, + TableCaptionChanged = 0x0113, + TableColumnDescriptionChanged = 0x0114, + TableColumnHeaderChanged = 0x0115, + TableModelChanged = 0x0116, + TableRowDescriptionChanged = 0x0117, + TableRowHeaderChanged = 0x0118, + TableSummaryChanged = 0x0119, + TextAttributeChanged = 0x011A, + TextCaretMoved = 0x011B, + // TextChanged = 0x011C, is deprecated in IA2, use TextUpdated + TextColumnChanged = 0x011D, + TextInserted = 0x011E, + TextRemoved = 0x011F, + TextUpdated = 0x0120, + TextSelectionChanged = 0x0121, + VisibleDataChanged = 0x0122, ObjectCreated = 0x8000, ObjectDestroyed = 0x8001, -- cgit v0.12 From 2a326fdc8f8bf2bd2c5764394616100906d9db2d Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 14 Jul 2011 16:27:44 -0700 Subject: Fix test for win and mac. Accidentally removed & in some places. Reviewed-by: TrustMe --- tests/auto/qaccessibility/tst_qaccessibility.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index 2db9f75..abe7fa7 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -2766,7 +2766,7 @@ void tst_QAccessibility::listViewTest() #else { QListView listView; - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); QVERIFY(iface); QCOMPARE(iface->childCount(), 1); delete iface; @@ -2780,11 +2780,11 @@ void tst_QAccessibility::listViewTest() listView.show(); QTest::qWait(1); // Need this for indexOfchild to work. #if defined(Q_WS_X11) - qt_x11_wait_for_window_manager(listView); + qt_x11_wait_for_window_manager(&listView); QTest::qWait(100); #endif - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); QCOMPARE((int)iface->role(0), (int)QAccessible::Client); QCOMPARE((int)iface->role(1), (int)QAccessible::List); QCOMPARE(iface->childCount(), 1); -- cgit v0.12 From 9b72e79e20d0d3560e0b064b8b0d75e35feb720e Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Sun, 17 Jul 2011 12:16:17 -0700 Subject: Fix accessibility test for QWS. For some reason we don't get the hide signal on QWS. Reviewed-by: Gabi --- tests/auto/qaccessibility/tst_qaccessibility.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index abe7fa7..79d7ee2 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -1774,6 +1774,9 @@ void tst_QAccessibility::mainWindowTest() QCOMPARE(interface->role(0), QAccessible::Window); delete interface; delete mw; +#ifndef Q_WS_QWS + QEXPECT_FAIL("", "The object hide event is missing on QWS.", Continue); +#endif QVERIFY_EVENT(mw, 0, QAccessible::ObjectHide); QTestAccessibility::clearEvents(); } -- cgit v0.12 From 075b0f744363842ed4179c644d933d461389544f Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 20 Jul 2011 01:09:27 -0700 Subject: Remove testing for Hide of mainwindow. This event is not used anywhere and the test seems to fail randomly. Since this line causes more trouble than it helps simply remove it. Reviewed-by: TrustMe --- tests/auto/qaccessibility/tst_qaccessibility.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index 79d7ee2..d452820 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -1774,10 +1774,6 @@ void tst_QAccessibility::mainWindowTest() QCOMPARE(interface->role(0), QAccessible::Window); delete interface; delete mw; -#ifndef Q_WS_QWS - QEXPECT_FAIL("", "The object hide event is missing on QWS.", Continue); -#endif - QVERIFY_EVENT(mw, 0, QAccessible::ObjectHide); QTestAccessibility::clearEvents(); } -- cgit v0.12