7#include <qheaderview.h>
8#if QT_CONFIG(tableview)
11#if QT_CONFIG(listview)
14#if QT_CONFIG(treeview)
16#include <private/qtreeview_p.h>
18#include <private/qwidget_p.h>
20#if QT_CONFIG(accessibility)
25
26
27
28
29
30
31
32
33
36QAbstractItemView *QAccessibleTable::view()
const
38 return qobject_cast<QAbstractItemView*>(object());
41int QAccessibleTable::logicalIndex(
const QModelIndex &index)
const
43 const QAbstractItemModel *theModel = index.model();
44 if (!theModel || !index.isValid())
47#if QT_CONFIG(listview)
48 if (role() == QAccessible::List) {
49 if (index.column() != qobject_cast<
const QListView*>(view())->modelColumn())
56 const int vHeader = verticalHeader() ? 1 : 0;
57 const int hHeader = horizontalHeader() ? 1 : 0;
58 return (index.row() + hHeader) * (columnCount() + vHeader)
59 + (index.column() + vHeader);
63QAccessibleTable::QAccessibleTable(QWidget *w, QAccessible::Role role)
64 : QAccessibleWidgetV2(w, role)
69QAccessibleTable::~QAccessibleTable()
71 for (QAccessible::Id id : std::as_const(childToId))
72 QAccessible::deleteAccessibleInterface(id);
75QHeaderView *QAccessibleTable::horizontalHeader()
const
77 QHeaderView *header =
nullptr;
79#if QT_CONFIG(tableview)
80 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view())) {
81 header = tv->horizontalHeader();
83#if QT_CONFIG(treeview)
84 }
else if (
const QTreeView *tv = qobject_cast<
const QTreeView*>(view())) {
85 header = tv->header();
91QHeaderView *QAccessibleTable::verticalHeader()
const
93 QHeaderView *header =
nullptr;
95#if QT_CONFIG(tableview)
96 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view())) {
97 header = tv->verticalHeader();
118QAccessibleInterface *QAccessibleTable::cellAt(
int row,
int column)
const
120 const QAbstractItemView *theView = view();
121 const QAbstractItemModel *theModel = theView->model();
124 Q_ASSERT(role() != QAccessible::List);
125 Q_ASSERT(role() != QAccessible::Tree);
127 const int vHeader = verticalHeader() ? 1 : 0;
128 const int hHeader = horizontalHeader() ? 1 : 0;
130 const int doHHeader = ((row == -1) && hHeader);
131 const int doVHeader = ((column == -1) && vHeader);
133 if (doVHeader && doHHeader)
137 return child((row + hHeader) * (columnCount() + vHeader) + (column + vHeader));
140 return child((row + hHeader) * (columnCount() + vHeader) + (column + vHeader));
142 QModelIndex index = theModel->index(row, column, theView->rootIndex());
143 if (Q_UNLIKELY(!index.isValid())) {
144 qWarning() <<
"QAccessibleTable::cellAt: invalid index: " << index <<
" for " << theView;
147 return child(logicalIndex(index));
150QAccessibleInterface *QAccessibleTable::caption()
const
155QString QAccessibleTable::columnDescription(
int column)
const
157 const QAbstractItemView *theView = view();
158 const QAbstractItemModel *theModel = theView->model();
161 return theModel->headerData(column, Qt::Horizontal).toString();
164int QAccessibleTable::columnCount()
const
166 const QAbstractItemView *theView = view();
167 const QAbstractItemModel *theModel = theView->model();
170 const int modelColumnCount = theModel->columnCount(theView->rootIndex());
171 return role() == QAccessible::List ? qMin(1, modelColumnCount) : modelColumnCount;
174int QAccessibleTable::rowCount()
const
176 const QAbstractItemView *theView = view();
177 const QAbstractItemModel *theModel = theView->model();
180 return theModel->rowCount(theView->rootIndex());
183int QAccessibleTable::selectedCellCount()
const
185 if (!view()->selectionModel())
187 return view()->selectionModel()->selectedIndexes().size();
190int QAccessibleTable::selectedColumnCount()
const
192 if (!view()->selectionModel())
194 return view()->selectionModel()->selectedColumns().size();
197int QAccessibleTable::selectedRowCount()
const
199 if (!view()->selectionModel())
201 return view()->selectionModel()->selectedRows().size();
204QString QAccessibleTable::rowDescription(
int row)
const
206 const QAbstractItemView *theView = view();
207 const QAbstractItemModel *theModel = theView->model();
210 return theModel->headerData(row, Qt::Vertical).toString();
213QList<QAccessibleInterface *> QAccessibleTable::selectedCells()
const
215 QList<QAccessibleInterface*> cells;
216 if (!view()->selectionModel())
218 const QModelIndexList selectedIndexes = view()->selectionModel()->selectedIndexes();
219 cells.reserve(selectedIndexes.size());
220 for (
const QModelIndex &index : selectedIndexes)
221 cells.append(child(logicalIndex(index)));
225QList<
int> QAccessibleTable::selectedColumns()
const
227 if (!view()->selectionModel())
230 const QModelIndexList selectedColumns = view()->selectionModel()->selectedColumns();
231 columns.reserve(selectedColumns.size());
232 for (
const QModelIndex &index : selectedColumns)
233 columns.append(index.column());
238QList<
int> QAccessibleTable::selectedRows()
const
240 if (!view()->selectionModel())
243 const QModelIndexList selectedRows = view()->selectionModel()->selectedRows();
244 rows.reserve(selectedRows.size());
245 for (
const QModelIndex &index : selectedRows)
246 rows.append(index.row());
251QAccessibleInterface *QAccessibleTable::summary()
const
256bool QAccessibleTable::isColumnSelected(
int column)
const
258 if (!view()->selectionModel())
260 return view()->selectionModel()->isColumnSelected(column, QModelIndex());
263bool QAccessibleTable::isRowSelected(
int row)
const
265 if (!view()->selectionModel())
267 return view()->selectionModel()->isRowSelected(row, QModelIndex());
270bool QAccessibleTable::selectRow(
int row)
272 QAbstractItemView *theView = view();
273 const QAbstractItemModel *theModel = theView->model();
274 if (!theModel || !view()->selectionModel())
277 const QModelIndex rootIndex = theView->rootIndex();
278 const QModelIndex index = theModel->index(row, 0, rootIndex);
280 if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns)
283 switch (view()->selectionMode()) {
284 case QAbstractItemView::NoSelection:
286 case QAbstractItemView::SingleSelection:
287 if (view()->selectionBehavior() != QAbstractItemView::SelectRows && columnCount() > 1 )
289 view()->clearSelection();
291 case QAbstractItemView::ContiguousSelection:
292 if ((!row || !theView->selectionModel()->isRowSelected(row - 1, rootIndex))
293 && !theView->selectionModel()->isRowSelected(row + 1, rootIndex)) {
294 theView->clearSelection();
301 view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
305bool QAccessibleTable::selectColumn(
int column)
307 QAbstractItemView *theView = view();
308 const QAbstractItemModel *theModel = theView->model();
309 auto *selectionModel = theView->selectionModel();
310 if (!theModel || !selectionModel)
313 const QModelIndex rootIndex = theView->rootIndex();
314 const QModelIndex index = theModel->index(0, column, rootIndex);
316 if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectRows)
319 switch (theView->selectionMode()) {
320 case QAbstractItemView::NoSelection:
322 case QAbstractItemView::SingleSelection:
323 if (theView->selectionBehavior() != QAbstractItemView::SelectColumns && rowCount() > 1)
326 case QAbstractItemView::ContiguousSelection:
327 if ((!column || !selectionModel->isColumnSelected(column - 1, rootIndex))
328 && !selectionModel->isColumnSelected(column + 1, rootIndex)) {
329 theView->clearSelection();
336 selectionModel->select(index, QItemSelectionModel::Select | QItemSelectionModel::Columns);
340bool QAccessibleTable::unselectRow(
int row)
342 const QAbstractItemView *theView = view();
343 const QAbstractItemModel *theModel = theView->model();
344 auto *selectionModel = theView->selectionModel();
345 if (!theModel || !selectionModel)
348 const QModelIndex rootIndex = theView->rootIndex();
349 const QModelIndex index = view()->model()->index(row, 0, rootIndex);
350 if (!index.isValid())
353 QItemSelection selection(index, index);
355 switch (theView->selectionMode()) {
356 case QAbstractItemView::SingleSelection:
359 if (selectedRowCount() == 1)
362 case QAbstractItemView::ContiguousSelection:
363 if (selectedRowCount() == 1)
366 if ((!row || selectionModel->isRowSelected(row - 1, rootIndex))
367 && selectionModel->isRowSelected(row + 1, rootIndex)) {
370 selection = QItemSelection(index, theModel->index(rowCount() - 1, 0, rootIndex));
377 selectionModel->select(selection, QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
381bool QAccessibleTable::unselectColumn(
int column)
383 const QAbstractItemView *theView = view();
384 const QAbstractItemModel *theModel = theView->model();
385 auto *selectionModel = theView->selectionModel();
386 if (!theModel || !selectionModel)
389 const QModelIndex rootIndex = theView->rootIndex();
390 const QModelIndex index = view()->model()->index(0, column, rootIndex);
391 if (!index.isValid())
394 QItemSelection selection(index, index);
396 switch (view()->selectionMode()) {
397 case QAbstractItemView::SingleSelection:
400 if (selectedColumnCount() == 1)
403 case QAbstractItemView::ContiguousSelection:
404 if (selectedColumnCount() == 1)
407 if ((!column || selectionModel->isColumnSelected(column - 1, rootIndex))
408 && selectionModel->isColumnSelected(column + 1, rootIndex)) {
411 selection = QItemSelection(index, theModel->index(0, columnCount() - 1, rootIndex));
418 selectionModel->select(selection, QItemSelectionModel::Deselect | QItemSelectionModel::Columns);
422int QAccessibleTable::selectedItemCount()
const
424 return selectedCellCount();
427QList<QAccessibleInterface*> QAccessibleTable::selectedItems()
const
429 return selectedCells();
432bool QAccessibleTable::isSelected(QAccessibleInterface *childCell)
const
434 if (!childCell || childCell->parent() !=
this) {
435 qWarning() <<
"QAccessibleTable::isSelected: Accessible interface must be a direct child of the table interface.";
439 const QAccessibleTableCellInterface *cell = childCell->tableCellInterface();
441 return cell->isSelected();
446bool QAccessibleTable::select(QAccessibleInterface *childCell)
448 if (!childCell || childCell->parent() !=
this) {
449 qWarning() <<
"QAccessibleTable::select: Accessible interface must be a direct child of the table interface.";
453 if (!childCell->tableCellInterface()) {
454 qWarning() <<
"QAccessibleTable::select: Accessible interface doesn't implement table cell interface.";
458 if (childCell->role() == QAccessible::Cell || childCell->role() == QAccessible::ListItem || childCell->role() == QAccessible::TreeItem) {
459 QAccessibleTableCell* cell =
static_cast<QAccessibleTableCell*>(childCell);
467bool QAccessibleTable::unselect(QAccessibleInterface *childCell)
469 if (!childCell || childCell->parent() !=
this) {
470 qWarning() <<
"QAccessibleTable::select: Accessible interface must be a direct child of the table interface.";
474 if (!childCell->tableCellInterface()) {
475 qWarning() <<
"QAccessibleTable::unselect: Accessible interface doesn't implement table cell interface.";
479 if (childCell->role() == QAccessible::Cell || childCell->role() == QAccessible::ListItem || childCell->role() == QAccessible::TreeItem) {
480 QAccessibleTableCell* cell =
static_cast<QAccessibleTableCell*>(childCell);
481 cell->unselectCell();
488bool QAccessibleTable::selectAll()
494bool QAccessibleTable::clear()
496 view()->selectionModel()->clearSelection();
501QAccessibleInterface *QAccessibleTable::childAt(
int x,
int y)
const
503 QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0));
504 QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset);
507 const QModelIndex index = view()->indexAt(indexPosition);
509 return child(logicalIndex(index));
513QAccessibleInterface *QAccessibleTable::focusChild()
const
515 QModelIndex index = view()->currentIndex();
516 if (!index.isValid())
519 return child(logicalIndex(index));
522int QAccessibleTable::childCount()
const
524 const QAbstractItemView *theView = view();
527 const QAbstractItemModel *theModel = theView->model();
530 const QModelIndex rootIndex = theView->rootIndex();
531 int vHeader = verticalHeader() ? 1 : 0;
532 int hHeader = horizontalHeader() ? 1 : 0;
533 return (theModel->rowCount(rootIndex) + hHeader) * (columnCount() + vHeader);
536int QAccessibleTable::indexOfChild(
const QAccessibleInterface *iface)
const
538 const QAbstractItemView *theView = view();
541 const QAbstractItemModel *theModel = theView->model();
544 QAccessibleInterface *parent = iface->parent();
545 if (parent->object() != theView)
548 const QModelIndex rootIndex = theView->rootIndex();
549 Q_ASSERT(iface->role() != QAccessible::TreeItem);
550 if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
551 const QAccessibleTableCell* cell =
static_cast<
const QAccessibleTableCell*>(iface);
552 return logicalIndex(cell->m_index);
553 }
else if (iface->role() == QAccessible::ColumnHeader){
554 const QAccessibleTableHeaderCell* cell =
static_cast<
const QAccessibleTableHeaderCell*>(iface);
555 return cell->index + (verticalHeader() ? 1 : 0);
556 }
else if (iface->role() == QAccessible::RowHeader){
557 const QAccessibleTableHeaderCell* cell =
static_cast<
const QAccessibleTableHeaderCell*>(iface);
558 return (cell->index + 1) * (theModel->columnCount(rootIndex) + 1);
559 }
else if (iface->role() == QAccessible::Pane) {
562 qWarning() <<
"WARNING QAccessibleTable::indexOfChild Fix my children..."
563 << iface->role() << iface->text(QAccessible::Name);
569QAccessibleInterface *QAccessibleTable::parent()
const
571 if (view() && view()->parent()) {
572 if (qstrcmp(
"QComboBoxPrivateContainer", view()->parent()->metaObject()->className()) == 0) {
573 return QAccessible::queryAccessibleInterface(view()->parent()->parent());
575 return QAccessible::queryAccessibleInterface(view()->parent());
577 return QAccessible::queryAccessibleInterface(qApp);
580QAccessibleInterface *QAccessibleTable::child(
int logicalIndex)
const
582 QAbstractItemView *theView = view();
586 const QAbstractItemModel *theModel = theView->model();
590 const QModelIndex rootIndex = theView->rootIndex();
591 auto id = childToId.constFind(logicalIndex);
592 if (id != childToId.constEnd())
593 return QAccessible::accessibleInterface(id.value());
595 int vHeader = verticalHeader() ? 1 : 0;
596 int hHeader = horizontalHeader() ? 1 : 0;
598 int columns = theModel->columnCount(rootIndex) + vHeader;
600 int row = logicalIndex / columns;
601 int column = logicalIndex % columns;
603 QAccessibleInterface *iface =
nullptr;
607 if (hHeader && row == 0) {
608 iface =
new QAccessibleTableCornerButton(theView);
610 iface =
new QAccessibleTableHeaderCell(theView, row - hHeader, Qt::Vertical);
615 if (!iface && hHeader) {
617 iface =
new QAccessibleTableHeaderCell(theView, column, Qt::Horizontal);
623 QModelIndex index = theModel->index(row, column, rootIndex);
624 if (Q_UNLIKELY(!index.isValid())) {
625 qWarning(
"QAccessibleTable::child: Invalid index at: %d %d", row, column);
628 iface =
new QAccessibleTableCell(theView, index, cellRole());
631 QAccessible::registerAccessibleInterface(iface);
632 childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
636void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t)
638 if (t == QAccessible::SelectionInterface)
639 return static_cast<QAccessibleSelectionInterface*>(
this);
640 if (t == QAccessible::TableInterface)
641 return static_cast<QAccessibleTableInterface*>(
this);
642 return QAccessibleWidgetV2::interface_cast(t);
645void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event)
648 if (childToId.isEmpty())
651 switch (event->modelChangeType()) {
652 case QAccessibleTableModelChangeEvent::ModelReset:
653 for (QAccessible::Id id : std::as_const(childToId))
654 QAccessible::deleteAccessibleInterface(id);
659 case QAccessibleTableModelChangeEvent::RowsInserted:
660 case QAccessibleTableModelChangeEvent::ColumnsInserted: {
661 int newRows = event->lastRow() - event->firstRow() + 1;
662 int newColumns = event->lastColumn() - event->firstColumn() + 1;
665 ChildCache::ConstIterator iter = childToId.constBegin();
667 while (iter != childToId.constEnd()) {
668 QAccessible::Id id = iter.value();
669 QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
671 if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted
672 && iface->role() == QAccessible::RowHeader) {
673 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
674 if (cell->index >= event->firstRow()) {
675 cell->index += newRows;
677 }
else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted
678 && iface->role() == QAccessible::ColumnHeader) {
679 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
680 if (cell->index >= event->firstColumn()) {
681 cell->index += newColumns;
684 if (indexOfChild(iface) >= 0) {
685 newCache.insert(indexOfChild(iface), id);
690 QAccessible::deleteAccessibleInterface(id);
694 childToId = newCache;
698 case QAccessibleTableModelChangeEvent::ColumnsRemoved:
699 case QAccessibleTableModelChangeEvent::RowsRemoved: {
700 int deletedColumns = event->lastColumn() - event->firstColumn() + 1;
701 int deletedRows = event->lastRow() - event->firstRow() + 1;
703 ChildCache::ConstIterator iter = childToId.constBegin();
704 while (iter != childToId.constEnd()) {
705 QAccessible::Id id = iter.value();
706 QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
708 if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
709 Q_ASSERT(iface->tableCellInterface());
710 QAccessibleTableCell *cell =
static_cast<QAccessibleTableCell*>(iface->tableCellInterface());
712 if (cell->m_index.isValid())
713 newCache.insert(indexOfChild(cell), id);
715 QAccessible::deleteAccessibleInterface(id);
716 }
else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved
717 && iface->role() == QAccessible::RowHeader) {
718 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
719 if (cell->index < event->firstRow()) {
720 newCache.insert(indexOfChild(cell), id);
721 }
else if (cell->index > event->lastRow()) {
722 cell->index -= deletedRows;
723 newCache.insert(indexOfChild(cell), id);
725 QAccessible::deleteAccessibleInterface(id);
727 }
else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved
728 && iface->role() == QAccessible::ColumnHeader) {
729 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
730 if (cell->index < event->firstColumn()) {
731 newCache.insert(indexOfChild(cell), id);
732 }
else if (cell->index > event->lastColumn()) {
733 cell->index -= deletedColumns;
734 newCache.insert(indexOfChild(cell), id);
736 QAccessible::deleteAccessibleInterface(id);
741 childToId = newCache;
745 case QAccessibleTableModelChangeEvent::DataChanged:
751#if QT_CONFIG(treeview)
755QModelIndex QAccessibleTree::indexFromLogical(
int row,
int column)
const
757 if (!isValid() || !view()->model())
758 return QModelIndex();
760 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
761 if (Q_UNLIKELY(row < 0 || column < 0 || treeView->d_func()->viewItems.size() <= row)) {
762 qWarning() <<
"QAccessibleTree::indexFromLogical: invalid index: " << row << column <<
" for " << treeView;
763 return QModelIndex();
765 QModelIndex modelIndex = treeView->d_func()->viewItems.at(row).index;
767 if (modelIndex.isValid() && column > 0) {
768 modelIndex = view()->model()->index(modelIndex.row(), column, modelIndex.parent());
773QAccessibleInterface *QAccessibleTree::childAt(
int x,
int y)
const
775 const QAbstractItemView *theView = view();
778 const QAbstractItemModel *theModel = theView->model();
782 const QPoint viewportOffset = theView->viewport()->mapTo(theView, QPoint(0, 0));
783 const QPoint indexPosition = theView->mapFromGlobal(QPoint(x, y) - viewportOffset);
785 const QModelIndex index = theView->indexAt(indexPosition);
786 if (!index.isValid())
789 const QTreeView *treeView = qobject_cast<
const QTreeView *>(theView);
790 int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0);
791 int column = index.column();
793 int i = row * theModel->columnCount(theView->rootIndex()) + column;
797QAccessibleInterface *QAccessibleTree::focusChild()
const
799 const QAbstractItemView *theView = view();
802 const QAbstractItemModel *theModel = theView->model();
803 const QModelIndex index = theView->currentIndex();
804 if (!index.isValid())
807 const QTreeView *treeView = qobject_cast<
const QTreeView *>(theView);
808 const int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0);
809 const int column = index.column();
811 int i = row * theModel->columnCount(theView->rootIndex()) + column;
815int QAccessibleTree::childCount()
const
817 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
820 const QAbstractItemModel *theModel = treeView->model();
824 int hHeader = horizontalHeader() ? 1 : 0;
825 return (treeView->d_func()->viewItems.size() + hHeader)
826 * theModel->columnCount(treeView->rootIndex());
829QAccessibleInterface *QAccessibleTree::child(
int logicalIndex)
const
831 QAbstractItemView *theView = view();
834 const QAbstractItemModel *theModel = theView->model();
835 const QModelIndex rootIndex = theView->rootIndex();
836 if (logicalIndex < 0 || !theModel || !theModel->columnCount(rootIndex))
839 auto id = childToId.constFind(logicalIndex);
840 if (id != childToId.constEnd())
841 return QAccessible::accessibleInterface(id.value());
843 QAccessibleInterface *iface =
nullptr;
844 int index = logicalIndex;
846 if (horizontalHeader()) {
847 if (index < theModel->columnCount(rootIndex))
848 iface =
new QAccessibleTableHeaderCell(theView, index, Qt::Horizontal);
850 index -= theModel->columnCount(rootIndex);
854 const int row = index / theModel->columnCount(rootIndex);
855 const int column = index % theModel->columnCount(rootIndex);
856 const QModelIndex modelIndex = indexFromLogical(row, column);
857 if (!modelIndex.isValid())
859 iface =
new QAccessibleTableCell(theView, modelIndex, cellRole());
861 QAccessible::registerAccessibleInterface(iface);
862 childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
866int QAccessibleTree::rowCount()
const
868 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
871 return treeView->d_func()->viewItems.size();
874int QAccessibleTree::indexOfChild(
const QAccessibleInterface *iface)
const
876 const QAbstractItemView *theView = view();
879 const QAbstractItemModel *theModel = theView->model();
882 QAccessibleInterface *parent = iface->parent();
883 if (parent->object() != theView)
886 if (iface->role() == QAccessible::TreeItem) {
887 const QAccessibleTableCell* cell =
static_cast<
const QAccessibleTableCell*>(iface);
888 const QTreeView *treeView = qobject_cast<
const QTreeView *>(theView);
890 int row = treeView->d_func()->viewIndex(cell->m_index) + (horizontalHeader() ? 1 : 0);
891 int column = cell->m_index.column();
893 int index = row * theModel->columnCount(theView->rootIndex()) + column;
895 }
else if (iface->role() == QAccessible::ColumnHeader){
896 const QAccessibleTableHeaderCell* cell =
static_cast<
const QAccessibleTableHeaderCell*>(iface);
899 qWarning() <<
"WARNING QAccessibleTable::indexOfChild invalid child"
900 << iface->role() << iface->text(QAccessible::Name);
906QAccessibleInterface *QAccessibleTree::cellAt(
int row,
int column)
const
908 QModelIndex index = indexFromLogical(row, column);
909 if (Q_UNLIKELY(!index.isValid())) {
910 qWarning(
"Requested invalid tree cell: %d %d", row, column);
913 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
915 int logicalIndex = treeView->d_func()->accessibleTable2Index(index);
917 return child(logicalIndex);
920QString QAccessibleTree::rowDescription(
int)
const
925bool QAccessibleTree::isRowSelected(
int row)
const
927 if (!view()->selectionModel())
929 QModelIndex index = indexFromLogical(row);
930 return view()->selectionModel()->isRowSelected(index.row(), index.parent());
933bool QAccessibleTree::selectRow(
int row)
935 if (!view()->selectionModel())
937 QModelIndex index = indexFromLogical(row);
939 if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns)
942 switch (view()->selectionMode()) {
943 case QAbstractItemView::NoSelection:
945 case QAbstractItemView::SingleSelection:
946 if ((view()->selectionBehavior() != QAbstractItemView::SelectRows) && (columnCount() > 1))
948 view()->clearSelection();
950 case QAbstractItemView::ContiguousSelection:
951 if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
952 && !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex()))
953 view()->clearSelection();
959 view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
965#if QT_CONFIG(listview)
969QAccessibleInterface *QAccessibleList::child(
int logicalIndex)
const
971 QAbstractItemView *theView = view();
974 const QAbstractItemModel *theModel = theView->model();
978 if (columnCount() == 0) {
982 const auto id = childToId.constFind(logicalIndex);
983 if (id != childToId.constEnd())
984 return QAccessible::accessibleInterface(id.value());
986 const QListView *listView = qobject_cast<
const QListView*>(theView);
988 int row = logicalIndex;
989 int column = listView->modelColumn();
991 const QModelIndex rootIndex = theView->rootIndex();
992 const QModelIndex index = theModel->index(row, column, rootIndex);
993 if (Q_UNLIKELY(!index.isValid())) {
994 qWarning(
"QAccessibleList::child: Invalid index at: %d %d", row, column);
997 const auto iface =
new QAccessibleTableCell(theView, index, cellRole());
999 QAccessible::registerAccessibleInterface(iface);
1000 childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
1004QAccessibleInterface *QAccessibleList::cellAt(
int row,
int column)
const
1012int QAccessibleList::selectedCellCount()
const
1014 QAbstractItemView *theView = view();
1015 if (!theView->selectionModel())
1017 const QListView *listView = qobject_cast<
const QListView*>(theView);
1018 const int modelColumn = listView->modelColumn();
1019 const QModelIndexList selectedIndexes = theView->selectionModel()->selectedIndexes();
1020 return std::count_if(selectedIndexes.cbegin(), selectedIndexes.cend(),
1021 [modelColumn](
const auto &index) {
1022 return index.column() == modelColumn;
1026QList<QAccessibleInterface *> QAccessibleList::selectedCells()
const
1028 QAbstractItemView *theView = view();
1029 QList<QAccessibleInterface*> cells;
1030 if (!view()->selectionModel() || columnCount() == 0)
1032 const QListView *listView = qobject_cast<
const QListView*>(theView);
1033 const int modelColumn = listView->modelColumn();
1034 const QModelIndexList selectedIndexes = theView->selectionModel()->selectedIndexes();
1035 cells.reserve(qMin(selectedIndexes.size(), rowCount()));
1036 for (
const QModelIndex &index : selectedIndexes)
1037 if (index.column() == modelColumn) {
1038 cells.append(child(index.row()));
1047QAccessibleTableCell::QAccessibleTableCell(QAbstractItemView *view_,
const QModelIndex &index_, QAccessible::Role role_)
1048 : view(view_), m_index(index_), m_role(role_)
1050 if (Q_UNLIKELY(!index_.isValid()))
1051 qWarning() <<
"QAccessibleTableCell::QAccessibleTableCell with invalid index: " << index_;
1054void *QAccessibleTableCell::interface_cast(QAccessible::InterfaceType t)
1056 if (t == QAccessible::TableCellInterface)
1057 return static_cast<QAccessibleTableCellInterface*>(
this);
1058 if (t == QAccessible::ActionInterface)
1059 return static_cast<QAccessibleActionInterface*>(
this);
1063int QAccessibleTableCell::columnExtent()
const {
return 1; }
1064int QAccessibleTableCell::rowExtent()
const {
return 1; }
1066QList<QAccessibleInterface*> QAccessibleTableCell::rowHeaderCells()
const
1068 QList<QAccessibleInterface*> headerCell;
1069 if (verticalHeader()) {
1071 headerCell.append(
new QAccessibleTableHeaderCell(view, m_index.row(), Qt::Vertical));
1076QList<QAccessibleInterface*> QAccessibleTableCell::columnHeaderCells()
const
1078 QList<QAccessibleInterface*> headerCell;
1079 if (horizontalHeader()) {
1081 headerCell.append(
new QAccessibleTableHeaderCell(view, m_index.column(), Qt::Horizontal));
1086QHeaderView *QAccessibleTableCell::horizontalHeader()
const
1088 QHeaderView *header =
nullptr;
1091#if QT_CONFIG(tableview)
1092 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view)) {
1093 header = tv->horizontalHeader();
1095#if QT_CONFIG(treeview)
1096 }
else if (
const QTreeView *tv = qobject_cast<
const QTreeView*>(view)) {
1097 header = tv->header();
1104QHeaderView *QAccessibleTableCell::verticalHeader()
const
1106 QHeaderView *header =
nullptr;
1107#if QT_CONFIG(tableview)
1108 if (
const QTableView *tv = qobject_cast<
const QTableView*>(view))
1109 header = tv->verticalHeader();
1114int QAccessibleTableCell::columnIndex()
const
1118#if QT_CONFIG(listview)
1119 if (role() == QAccessible::ListItem) {
1123 return m_index.column();
1126int QAccessibleTableCell::rowIndex()
const
1130#if QT_CONFIG(treeview)
1131 if (role() == QAccessible::TreeItem) {
1132 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view);
1134 int row = treeView->d_func()->viewIndex(m_index);
1138 return m_index.row();
1141bool QAccessibleTableCell::isSelected()
const
1145 return view->selectionModel()->isSelected(m_index);
1148QStringList QAccessibleTableCell::actionNames()
const
1151 names << toggleAction();
1155void QAccessibleTableCell::doAction(
const QString& actionName)
1157 if (actionName == toggleAction()) {
1158#if defined(Q_OS_ANDROID)
1159 QAccessibleInterface *parentInterface = parent();
1160 while (parentInterface){
1161 if (parentInterface->role() == QAccessible::ComboBox) {
1163 parentInterface->actionInterface()->doAction(pressAction());
1166 parentInterface = parentInterface->parent();
1178QStringList QAccessibleTableCell::keyBindingsForAction(
const QString &)
const
1180 return QStringList();
1184void QAccessibleTableCell::selectCell()
1188 QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
1189 if (selectionMode == QAbstractItemView::NoSelection)
1192 QAccessibleTableInterface *cellTable = table()->tableInterface();
1194 switch (view->selectionBehavior()) {
1195 case QAbstractItemView::SelectItems:
1197 case QAbstractItemView::SelectColumns:
1199 cellTable->selectColumn(m_index.column());
1201 case QAbstractItemView::SelectRows:
1203 cellTable->selectRow(m_index.row());
1207 if (selectionMode == QAbstractItemView::SingleSelection) {
1208 view->clearSelection();
1211 view->selectionModel()->select(m_index, QItemSelectionModel::Select);
1214void QAccessibleTableCell::unselectCell()
1218 QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
1219 if (selectionMode == QAbstractItemView::NoSelection)
1222 QAccessibleTableInterface *cellTable = table()->tableInterface();
1224 switch (view->selectionBehavior()) {
1225 case QAbstractItemView::SelectItems:
1227 case QAbstractItemView::SelectColumns:
1229 cellTable->unselectColumn(m_index.column());
1231 case QAbstractItemView::SelectRows:
1233 cellTable->unselectRow(m_index.row());
1239 if ((selectionMode != QAbstractItemView::MultiSelection)
1240 && (selectionMode != QAbstractItemView::ExtendedSelection)
1241 && (view->selectionModel()->selectedIndexes().size() <= 1))
1244 view->selectionModel()->select(m_index, QItemSelectionModel::Deselect);
1247QAccessibleInterface *QAccessibleTableCell::table()
const
1249 return QAccessible::queryAccessibleInterface(view);
1252QAccessible::Role QAccessibleTableCell::role()
const
1257QAccessible::State QAccessibleTableCell::state()
const
1259 QAccessible::State st;
1263 QRect globalRect = view->rect();
1264 globalRect.translate(view->mapToGlobal(QPoint(0,0)));
1265 if (!globalRect.intersects(rect()))
1266 st.invisible =
true;
1268 if (view->selectionModel()->isSelected(m_index))
1270 if (view->selectionModel()->currentIndex() == m_index)
1273 const QVariant checkState = m_index.data(Qt::CheckStateRole);
1274 if (checkState.toInt() == Qt::Checked)
1277 Qt::ItemFlags flags = m_index.flags();
1278 if ((flags & Qt::ItemIsUserCheckable) && checkState.isValid())
1279 st.checkable =
true;
1280 if (flags & Qt::ItemIsSelectable) {
1281 st.selectable =
true;
1282 st.focusable =
true;
1283 if (view->selectionMode() == QAbstractItemView::MultiSelection)
1284 st.multiSelectable =
true;
1285 if (view->selectionMode() == QAbstractItemView::ExtendedSelection)
1286 st.extSelectable =
true;
1288#if QT_CONFIG(treeview)
1289 if (m_role == QAccessible::TreeItem) {
1290 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view);
1291 if (treeView->model()->hasChildren(m_index))
1292 st.expandable =
true;
1293 if (treeView->isExpanded(m_index))
1301QRect QAccessibleTableCell::rect()
const
1306 r = view->visualRect(m_index);
1309 r.translate(view->viewport()->mapTo(view, QPoint(0,0)));
1310 r.translate(view->mapToGlobal(QPoint(0, 0)));
1315QString QAccessibleTableCell::text(QAccessible::Text t)
const
1320 QAbstractItemModel *model = view->model();
1322 case QAccessible::Name:
1323 value = model->data(m_index, Qt::AccessibleTextRole).toString();
1324 if (value.isEmpty())
1325 value = model->data(m_index, Qt::DisplayRole).toString();
1327 case QAccessible::Description:
1328 value = model->data(m_index, Qt::AccessibleDescriptionRole).toString();
1336void QAccessibleTableCell::setText(QAccessible::Text ,
const QString &text)
1338 if (!isValid() || !(m_index.flags() & Qt::ItemIsEditable))
1340 view->model()->setData(m_index, text);
1343bool QAccessibleTableCell::isValid()
const
1345 return view && !qt_widget_private(view)->data.in_destructor
1346 && view->model() && m_index.isValid();
1349QAccessibleInterface *QAccessibleTableCell::parent()
const
1351 return QAccessible::queryAccessibleInterface(view);
1354QAccessibleInterface *QAccessibleTableCell::child(
int)
const
1359QAccessibleTableHeaderCell::QAccessibleTableHeaderCell(QAbstractItemView *view_,
int index_, Qt::Orientation orientation_)
1360 : view(view_), index(index_), orientation(orientation_)
1362 Q_ASSERT(index_ >= 0);
1365QAccessible::Role QAccessibleTableHeaderCell::role()
const
1367 if (orientation == Qt::Horizontal)
1368 return QAccessible::ColumnHeader;
1369 return QAccessible::RowHeader;
1372QAccessible::State QAccessibleTableHeaderCell::state()
const
1374 QAccessible::State s;
1375 if (QHeaderView *h = headerView()) {
1376 s.invisible = !h->testAttribute(Qt::WA_WState_Visible);
1377 s.disabled = !h->isEnabled();
1382QRect QAccessibleTableHeaderCell::rect()
const
1384 QHeaderView *header =
nullptr;
1386#if QT_CONFIG(tableview)
1387 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view)) {
1388 if (orientation == Qt::Horizontal) {
1389 header = tv->horizontalHeader();
1391 header = tv->verticalHeader();
1394#if QT_CONFIG(treeview)
1395 }
else if (
const QTreeView *tv = qobject_cast<
const QTreeView*>(view)) {
1396 header = tv->header();
1401 QPoint zero = header->mapToGlobal(QPoint(0, 0));
1402 int sectionSize = header->sectionSize(index);
1403 int sectionPos = header->sectionPosition(index);
1404 return orientation == Qt::Horizontal
1405 ? QRect(zero.x() + sectionPos, zero.y(), sectionSize, header->height())
1406 : QRect(zero.x(), zero.y() + sectionPos, header->width(), sectionSize);
1409QString QAccessibleTableHeaderCell::text(QAccessible::Text t)
const
1411 QAbstractItemModel *model = view->model();
1414 case QAccessible::Name:
1415 value = model->headerData(index, orientation, Qt::AccessibleTextRole).toString();
1416 if (value.isEmpty())
1417 value = model->headerData(index, orientation, Qt::DisplayRole).toString();
1419 case QAccessible::Description:
1420 value = model->headerData(index, orientation, Qt::AccessibleDescriptionRole).toString();
1428void QAccessibleTableHeaderCell::setText(QAccessible::Text,
const QString &)
1433bool QAccessibleTableHeaderCell::isValid()
const
1435 const QAbstractItemModel *theModel = view && !qt_widget_private(view)->data.in_destructor
1436 ? view->model() :
nullptr;
1439 const QModelIndex rootIndex = view->rootIndex();
1440 return (index >= 0) && ((orientation == Qt::Horizontal)
1441 ? (index < theModel->columnCount(rootIndex))
1442 : (index < theModel->rowCount(rootIndex)));
1445QAccessibleInterface *QAccessibleTableHeaderCell::parent()
const
1447 return QAccessible::queryAccessibleInterface(view);
1450QAccessibleInterface *QAccessibleTableHeaderCell::child(
int)
const
1455QHeaderView *QAccessibleTableHeaderCell::headerView()
const
1457 QHeaderView *header =
nullptr;
1459#if QT_CONFIG(tableview)
1460 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view)) {
1461 if (orientation == Qt::Horizontal) {
1462 header = tv->horizontalHeader();
1464 header = tv->verticalHeader();
1467#if QT_CONFIG(treeview)
1468 }
else if (
const QTreeView *tv = qobject_cast<
const QTreeView*>(view)) {
1469 header = tv->header();