6#include <qheaderview.h>
7#if QT_CONFIG(tableview)
10#if QT_CONFIG(listview)
13#if QT_CONFIG(treeview)
15#include <private/qtreeview_p.h>
17#include <private/qwidget_p.h>
19#if QT_CONFIG(accessibility)
24
25
26
27
28
29
30
31
32
35QAbstractItemView *QAccessibleTable::view()
const
37 return qobject_cast<QAbstractItemView*>(object());
40int QAccessibleTable::logicalIndex(
const QModelIndex &index)
const
42 const QAbstractItemModel *theModel = index.model();
43 if (!theModel || !index.isValid())
46#if QT_CONFIG(listview)
47 if (m_role == QAccessible::List) {
48 if (index.column() != qobject_cast<
const QListView*>(view())->modelColumn())
55 const int vHeader = verticalHeader() ? 1 : 0;
56 const int hHeader = horizontalHeader() ? 1 : 0;
57 return (index.row() + hHeader) * (columnCount() + vHeader)
58 + (index.column() + vHeader);
62QAccessibleTable::QAccessibleTable(QWidget *w)
63 : QAccessibleObject(w)
67#if QT_CONFIG(tableview)
68 if (qobject_cast<
const QTableView*>(view())) {
69 m_role = QAccessible::Table;
72#if QT_CONFIG(treeview)
73 if (qobject_cast<
const QTreeView*>(view())) {
74 m_role = QAccessible::Tree;
77#if QT_CONFIG(listview)
78 if (qobject_cast<
const QListView*>(view())) {
79 m_role = QAccessible::List;
84 m_role = QAccessible::Table;
88bool QAccessibleTable::isValid()
const
90 return view() && !qt_widget_private(view())->data.in_destructor;
93QAccessibleTable::~QAccessibleTable()
95 for (QAccessible::Id id : std::as_const(childToId))
96 QAccessible::deleteAccessibleInterface(id);
99QHeaderView *QAccessibleTable::horizontalHeader()
const
101 QHeaderView *header =
nullptr;
103#if QT_CONFIG(tableview)
104 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view())) {
105 header = tv->horizontalHeader();
107#if QT_CONFIG(treeview)
108 }
else if (
const QTreeView *tv = qobject_cast<
const QTreeView*>(view())) {
109 header = tv->header();
115QHeaderView *QAccessibleTable::verticalHeader()
const
117 QHeaderView *header =
nullptr;
119#if QT_CONFIG(tableview)
120 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view())) {
121 header = tv->verticalHeader();
127QAccessibleInterface *QAccessibleTable::cellAt(
int row,
int column)
const
129 const QAbstractItemView *theView = view();
130 const QAbstractItemModel *theModel = theView->model();
133 Q_ASSERT(role() != QAccessible::List);
134 Q_ASSERT(role() != QAccessible::Tree);
135 QModelIndex index = theModel->index(row, column, theView->rootIndex());
136 if (Q_UNLIKELY(!index.isValid())) {
137 qWarning() <<
"QAccessibleTable::cellAt: invalid index: " << index <<
" for " << theView;
140 return child(logicalIndex(index));
143QAccessibleInterface *QAccessibleTable::caption()
const
148QString QAccessibleTable::columnDescription(
int column)
const
150 const QAbstractItemView *theView = view();
151 const QAbstractItemModel *theModel = theView->model();
154 return theModel->headerData(column, Qt::Horizontal).toString();
157int QAccessibleTable::columnCount()
const
159 const QAbstractItemView *theView = view();
160 const QAbstractItemModel *theModel = theView->model();
163 const int modelColumnCount = theModel->columnCount(theView->rootIndex());
164 return m_role == QAccessible::List ? qMin(1, modelColumnCount) : modelColumnCount;
167int QAccessibleTable::rowCount()
const
169 const QAbstractItemView *theView = view();
170 const QAbstractItemModel *theModel = theView->model();
173 return theModel->rowCount(theView->rootIndex());
176int QAccessibleTable::selectedCellCount()
const
178 if (!view()->selectionModel())
180 return view()->selectionModel()->selectedIndexes().size();
183int QAccessibleTable::selectedColumnCount()
const
185 if (!view()->selectionModel())
187 return view()->selectionModel()->selectedColumns().size();
190int QAccessibleTable::selectedRowCount()
const
192 if (!view()->selectionModel())
194 return view()->selectionModel()->selectedRows().size();
197QString QAccessibleTable::rowDescription(
int row)
const
199 const QAbstractItemView *theView = view();
200 const QAbstractItemModel *theModel = theView->model();
203 return theModel->headerData(row, Qt::Vertical).toString();
206QList<QAccessibleInterface *> QAccessibleTable::selectedCells()
const
208 QList<QAccessibleInterface*> cells;
209 if (!view()->selectionModel())
211 const QModelIndexList selectedIndexes = view()->selectionModel()->selectedIndexes();
212 cells.reserve(selectedIndexes.size());
213 for (
const QModelIndex &index : selectedIndexes)
214 cells.append(child(logicalIndex(index)));
218QList<
int> QAccessibleTable::selectedColumns()
const
220 if (!view()->selectionModel())
223 const QModelIndexList selectedColumns = view()->selectionModel()->selectedColumns();
224 columns.reserve(selectedColumns.size());
225 for (
const QModelIndex &index : selectedColumns)
226 columns.append(index.column());
231QList<
int> QAccessibleTable::selectedRows()
const
233 if (!view()->selectionModel())
236 const QModelIndexList selectedRows = view()->selectionModel()->selectedRows();
237 rows.reserve(selectedRows.size());
238 for (
const QModelIndex &index : selectedRows)
239 rows.append(index.row());
244QAccessibleInterface *QAccessibleTable::summary()
const
249bool QAccessibleTable::isColumnSelected(
int column)
const
251 if (!view()->selectionModel())
253 return view()->selectionModel()->isColumnSelected(column, QModelIndex());
256bool QAccessibleTable::isRowSelected(
int row)
const
258 if (!view()->selectionModel())
260 return view()->selectionModel()->isRowSelected(row, QModelIndex());
263bool QAccessibleTable::selectRow(
int row)
265 QAbstractItemView *theView = view();
266 const QAbstractItemModel *theModel = theView->model();
267 if (!theModel || !view()->selectionModel())
270 const QModelIndex rootIndex = theView->rootIndex();
271 const QModelIndex index = theModel->index(row, 0, rootIndex);
273 if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns)
276 switch (view()->selectionMode()) {
277 case QAbstractItemView::NoSelection:
279 case QAbstractItemView::SingleSelection:
280 if (view()->selectionBehavior() != QAbstractItemView::SelectRows && columnCount() > 1 )
282 view()->clearSelection();
284 case QAbstractItemView::ContiguousSelection:
285 if ((!row || !theView->selectionModel()->isRowSelected(row - 1, rootIndex))
286 && !theView->selectionModel()->isRowSelected(row + 1, rootIndex)) {
287 theView->clearSelection();
294 view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
298bool QAccessibleTable::selectColumn(
int column)
300 QAbstractItemView *theView = view();
301 const QAbstractItemModel *theModel = theView->model();
302 auto *selectionModel = theView->selectionModel();
303 if (!theModel || !selectionModel)
306 const QModelIndex rootIndex = theView->rootIndex();
307 const QModelIndex index = theModel->index(0, column, rootIndex);
309 if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectRows)
312 switch (theView->selectionMode()) {
313 case QAbstractItemView::NoSelection:
315 case QAbstractItemView::SingleSelection:
316 if (theView->selectionBehavior() != QAbstractItemView::SelectColumns && rowCount() > 1)
319 case QAbstractItemView::ContiguousSelection:
320 if ((!column || !selectionModel->isColumnSelected(column - 1, rootIndex))
321 && !selectionModel->isColumnSelected(column + 1, rootIndex)) {
322 theView->clearSelection();
329 selectionModel->select(index, QItemSelectionModel::Select | QItemSelectionModel::Columns);
333bool QAccessibleTable::unselectRow(
int row)
335 const QAbstractItemView *theView = view();
336 const QAbstractItemModel *theModel = theView->model();
337 auto *selectionModel = theView->selectionModel();
338 if (!theModel || !selectionModel)
341 const QModelIndex rootIndex = theView->rootIndex();
342 const QModelIndex index = view()->model()->index(row, 0, rootIndex);
343 if (!index.isValid())
346 QItemSelection selection(index, index);
348 switch (theView->selectionMode()) {
349 case QAbstractItemView::SingleSelection:
352 if (selectedRowCount() == 1)
355 case QAbstractItemView::ContiguousSelection:
356 if (selectedRowCount() == 1)
359 if ((!row || selectionModel->isRowSelected(row - 1, rootIndex))
360 && selectionModel->isRowSelected(row + 1, rootIndex)) {
363 selection = QItemSelection(index, theModel->index(rowCount() - 1, 0, rootIndex));
370 selectionModel->select(selection, QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
374bool QAccessibleTable::unselectColumn(
int column)
376 const QAbstractItemView *theView = view();
377 const QAbstractItemModel *theModel = theView->model();
378 auto *selectionModel = theView->selectionModel();
379 if (!theModel || !selectionModel)
382 const QModelIndex rootIndex = theView->rootIndex();
383 const QModelIndex index = view()->model()->index(0, column, rootIndex);
384 if (!index.isValid())
387 QItemSelection selection(index, index);
389 switch (view()->selectionMode()) {
390 case QAbstractItemView::SingleSelection:
393 if (selectedColumnCount() == 1)
396 case QAbstractItemView::ContiguousSelection:
397 if (selectedColumnCount() == 1)
400 if ((!column || selectionModel->isColumnSelected(column - 1, rootIndex))
401 && selectionModel->isColumnSelected(column + 1, rootIndex)) {
404 selection = QItemSelection(index, theModel->index(0, columnCount() - 1, rootIndex));
411 selectionModel->select(selection, QItemSelectionModel::Deselect | QItemSelectionModel::Columns);
415int QAccessibleTable::selectedItemCount()
const
417 return selectedCellCount();
420QList<QAccessibleInterface*> QAccessibleTable::selectedItems()
const
422 return selectedCells();
425bool QAccessibleTable::isSelected(QAccessibleInterface *childCell)
const
427 if (!childCell || childCell->parent() !=
this) {
428 qWarning() <<
"QAccessibleTable::isSelected: Accessible interface must be a direct child of the table interface.";
432 const QAccessibleTableCellInterface *cell = childCell->tableCellInterface();
434 return cell->isSelected();
439bool QAccessibleTable::select(QAccessibleInterface *childCell)
441 if (!childCell || childCell->parent() !=
this) {
442 qWarning() <<
"QAccessibleTable::select: Accessible interface must be a direct child of the table interface.";
446 if (!childCell->tableCellInterface()) {
447 qWarning() <<
"QAccessibleTable::select: Accessible interface doesn't implement table cell interface.";
451 if (childCell->role() == QAccessible::Cell || childCell->role() == QAccessible::ListItem || childCell->role() == QAccessible::TreeItem) {
452 QAccessibleTableCell* cell =
static_cast<QAccessibleTableCell*>(childCell);
460bool QAccessibleTable::unselect(QAccessibleInterface *childCell)
462 if (!childCell || childCell->parent() !=
this) {
463 qWarning() <<
"QAccessibleTable::select: Accessible interface must be a direct child of the table interface.";
467 if (!childCell->tableCellInterface()) {
468 qWarning() <<
"QAccessibleTable::unselect: Accessible interface doesn't implement table cell interface.";
472 if (childCell->role() == QAccessible::Cell || childCell->role() == QAccessible::ListItem || childCell->role() == QAccessible::TreeItem) {
473 QAccessibleTableCell* cell =
static_cast<QAccessibleTableCell*>(childCell);
474 cell->unselectCell();
481bool QAccessibleTable::selectAll()
487bool QAccessibleTable::clear()
489 view()->selectionModel()->clearSelection();
494QAccessible::Role QAccessibleTable::role()
const
499QAccessible::State QAccessibleTable::state()
const
501 QAccessible::State state;
502 const auto *w = view();
504 if (w->testAttribute(Qt::WA_WState_Visible) ==
false)
505 state.invisible =
true;
506 if (w->focusPolicy() != Qt::NoFocus)
507 state.focusable =
true;
509 state.focused =
true;
511 state.disabled =
true;
513 if (w->windowFlags() & Qt::WindowSystemMenuHint)
514 state.movable =
true;
515 if (w->minimumSize() != w->maximumSize())
516 state.sizeable =
true;
517 if (w->isActiveWindow())
524QAccessibleInterface *QAccessibleTable::childAt(
int x,
int y)
const
526 QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0));
527 QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset);
530 const QModelIndex index = view()->indexAt(indexPosition);
532 return child(logicalIndex(index));
536QAccessibleInterface *QAccessibleTable::focusChild()
const
538 QModelIndex index = view()->currentIndex();
539 if (!index.isValid())
542 return child(logicalIndex(index));
545int QAccessibleTable::childCount()
const
547 const QAbstractItemView *theView = view();
550 const QAbstractItemModel *theModel = theView->model();
553 const QModelIndex rootIndex = theView->rootIndex();
554 int vHeader = verticalHeader() ? 1 : 0;
555 int hHeader = horizontalHeader() ? 1 : 0;
556 return (theModel->rowCount(rootIndex) + hHeader) * (columnCount() + vHeader);
559int QAccessibleTable::indexOfChild(
const QAccessibleInterface *iface)
const
561 const QAbstractItemView *theView = view();
564 const QAbstractItemModel *theModel = theView->model();
567 QAccessibleInterface *parent = iface->parent();
568 if (parent->object() != theView)
571 const QModelIndex rootIndex = theView->rootIndex();
572 Q_ASSERT(iface->role() != QAccessible::TreeItem);
573 if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
574 const QAccessibleTableCell* cell =
static_cast<
const QAccessibleTableCell*>(iface);
575 return logicalIndex(cell->m_index);
576 }
else if (iface->role() == QAccessible::ColumnHeader){
577 const QAccessibleTableHeaderCell* cell =
static_cast<
const QAccessibleTableHeaderCell*>(iface);
578 return cell->index + (verticalHeader() ? 1 : 0);
579 }
else if (iface->role() == QAccessible::RowHeader){
580 const QAccessibleTableHeaderCell* cell =
static_cast<
const QAccessibleTableHeaderCell*>(iface);
581 return (cell->index + 1) * (theModel->columnCount(rootIndex) + 1);
582 }
else if (iface->role() == QAccessible::Pane) {
585 qWarning() <<
"WARNING QAccessibleTable::indexOfChild Fix my children..."
586 << iface->role() << iface->text(QAccessible::Name);
592QString QAccessibleTable::text(QAccessible::Text t)
const
594 if (t == QAccessible::Description)
595 return view()->accessibleDescription();
596 return view()->accessibleName();
599QRect QAccessibleTable::rect()
const
601 if (!view()->isVisible())
603 QPoint pos = view()->mapToGlobal(QPoint(0, 0));
604 return QRect(pos.x(), pos.y(), view()->width(), view()->height());
607QAccessibleInterface *QAccessibleTable::parent()
const
609 if (view() && view()->parent()) {
610 if (qstrcmp(
"QComboBoxPrivateContainer", view()->parent()->metaObject()->className()) == 0) {
611 return QAccessible::queryAccessibleInterface(view()->parent()->parent());
613 return QAccessible::queryAccessibleInterface(view()->parent());
615 return QAccessible::queryAccessibleInterface(qApp);
618QAccessibleInterface *QAccessibleTable::child(
int logicalIndex)
const
620 QAbstractItemView *theView = view();
624 const QAbstractItemModel *theModel = theView->model();
628 const QModelIndex rootIndex = theView->rootIndex();
629 auto id = childToId.constFind(logicalIndex);
630 if (id != childToId.constEnd())
631 return QAccessible::accessibleInterface(id.value());
633 int vHeader = verticalHeader() ? 1 : 0;
634 int hHeader = horizontalHeader() ? 1 : 0;
636 int columns = theModel->columnCount(rootIndex) + vHeader;
638 int row = logicalIndex / columns;
639 int column = logicalIndex % columns;
641 QAccessibleInterface *iface =
nullptr;
645 if (hHeader && row == 0) {
646 iface =
new QAccessibleTableCornerButton(theView);
648 iface =
new QAccessibleTableHeaderCell(theView, row - hHeader, Qt::Vertical);
653 if (!iface && hHeader) {
655 iface =
new QAccessibleTableHeaderCell(theView, column, Qt::Horizontal);
661 QModelIndex index = theModel->index(row, column, rootIndex);
662 if (Q_UNLIKELY(!index.isValid())) {
663 qWarning(
"QAccessibleTable::child: Invalid index at: %d %d", row, column);
666 iface =
new QAccessibleTableCell(theView, index, cellRole());
669 QAccessible::registerAccessibleInterface(iface);
670 childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
674void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t)
676 if (t == QAccessible::SelectionInterface)
677 return static_cast<QAccessibleSelectionInterface*>(
this);
678 if (t == QAccessible::TableInterface)
679 return static_cast<QAccessibleTableInterface*>(
this);
683void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event)
686 if (childToId.isEmpty())
689 switch (event->modelChangeType()) {
690 case QAccessibleTableModelChangeEvent::ModelReset:
691 for (QAccessible::Id id : std::as_const(childToId))
692 QAccessible::deleteAccessibleInterface(id);
697 case QAccessibleTableModelChangeEvent::RowsInserted:
698 case QAccessibleTableModelChangeEvent::ColumnsInserted: {
699 int newRows = event->lastRow() - event->firstRow() + 1;
700 int newColumns = event->lastColumn() - event->firstColumn() + 1;
703 ChildCache::ConstIterator iter = childToId.constBegin();
705 while (iter != childToId.constEnd()) {
706 QAccessible::Id id = iter.value();
707 QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
709 if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted
710 && iface->role() == QAccessible::RowHeader) {
711 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
712 if (cell->index >= event->firstRow()) {
713 cell->index += newRows;
715 }
else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted
716 && iface->role() == QAccessible::ColumnHeader) {
717 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
718 if (cell->index >= event->firstColumn()) {
719 cell->index += newColumns;
722 if (indexOfChild(iface) >= 0) {
723 newCache.insert(indexOfChild(iface), id);
728 QAccessible::deleteAccessibleInterface(id);
732 childToId = newCache;
736 case QAccessibleTableModelChangeEvent::ColumnsRemoved:
737 case QAccessibleTableModelChangeEvent::RowsRemoved: {
738 int deletedColumns = event->lastColumn() - event->firstColumn() + 1;
739 int deletedRows = event->lastRow() - event->firstRow() + 1;
741 ChildCache::ConstIterator iter = childToId.constBegin();
742 while (iter != childToId.constEnd()) {
743 QAccessible::Id id = iter.value();
744 QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
746 if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
747 Q_ASSERT(iface->tableCellInterface());
748 QAccessibleTableCell *cell =
static_cast<QAccessibleTableCell*>(iface->tableCellInterface());
750 if (cell->m_index.isValid())
751 newCache.insert(indexOfChild(cell), id);
753 QAccessible::deleteAccessibleInterface(id);
754 }
else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved
755 && iface->role() == QAccessible::RowHeader) {
756 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
757 if (cell->index < event->firstRow()) {
758 newCache.insert(indexOfChild(cell), id);
759 }
else if (cell->index > event->lastRow()) {
760 cell->index -= deletedRows;
761 newCache.insert(indexOfChild(cell), id);
763 QAccessible::deleteAccessibleInterface(id);
765 }
else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved
766 && iface->role() == QAccessible::ColumnHeader) {
767 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
768 if (cell->index < event->firstColumn()) {
769 newCache.insert(indexOfChild(cell), id);
770 }
else if (cell->index > event->lastColumn()) {
771 cell->index -= deletedColumns;
772 newCache.insert(indexOfChild(cell), id);
774 QAccessible::deleteAccessibleInterface(id);
779 childToId = newCache;
783 case QAccessibleTableModelChangeEvent::DataChanged:
789#if QT_CONFIG(treeview)
793QModelIndex QAccessibleTree::indexFromLogical(
int row,
int column)
const
795 if (!isValid() || !view()->model())
796 return QModelIndex();
798 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
799 if (Q_UNLIKELY(row < 0 || column < 0 || treeView->d_func()->viewItems.size() <= row)) {
800 qWarning() <<
"QAccessibleTree::indexFromLogical: invalid index: " << row << column <<
" for " << treeView;
801 return QModelIndex();
803 QModelIndex modelIndex = treeView->d_func()->viewItems.at(row).index;
805 if (modelIndex.isValid() && column > 0) {
806 modelIndex = view()->model()->index(modelIndex.row(), column, modelIndex.parent());
811QAccessibleInterface *QAccessibleTree::childAt(
int x,
int y)
const
813 const QAbstractItemView *theView = view();
816 const QAbstractItemModel *theModel = theView->model();
820 const QPoint viewportOffset = theView->viewport()->mapTo(theView, QPoint(0, 0));
821 const QPoint indexPosition = theView->mapFromGlobal(QPoint(x, y) - viewportOffset);
823 const QModelIndex index = theView->indexAt(indexPosition);
824 if (!index.isValid())
827 const QTreeView *treeView = qobject_cast<
const QTreeView *>(theView);
828 int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0);
829 int column = index.column();
831 int i = row * theModel->columnCount(theView->rootIndex()) + column;
835QAccessibleInterface *QAccessibleTree::focusChild()
const
837 const QAbstractItemView *theView = view();
840 const QAbstractItemModel *theModel = theView->model();
841 const QModelIndex index = theView->currentIndex();
842 if (!index.isValid())
845 const QTreeView *treeView = qobject_cast<
const QTreeView *>(theView);
846 const int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0);
847 const int column = index.column();
849 int i = row * theModel->columnCount(theView->rootIndex()) + column;
853int QAccessibleTree::childCount()
const
855 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
858 const QAbstractItemModel *theModel = treeView->model();
862 int hHeader = horizontalHeader() ? 1 : 0;
863 return (treeView->d_func()->viewItems.size() + hHeader)
864 * theModel->columnCount(treeView->rootIndex());
867QAccessibleInterface *QAccessibleTree::child(
int logicalIndex)
const
869 QAbstractItemView *theView = view();
872 const QAbstractItemModel *theModel = theView->model();
873 const QModelIndex rootIndex = theView->rootIndex();
874 if (logicalIndex < 0 || !theModel || !theModel->columnCount(rootIndex))
877 auto id = childToId.constFind(logicalIndex);
878 if (id != childToId.constEnd())
879 return QAccessible::accessibleInterface(id.value());
881 QAccessibleInterface *iface =
nullptr;
882 int index = logicalIndex;
884 if (horizontalHeader()) {
885 if (index < theModel->columnCount(rootIndex))
886 iface =
new QAccessibleTableHeaderCell(theView, index, Qt::Horizontal);
888 index -= theModel->columnCount(rootIndex);
892 const int row = index / theModel->columnCount(rootIndex);
893 const int column = index % theModel->columnCount(rootIndex);
894 const QModelIndex modelIndex = indexFromLogical(row, column);
895 if (!modelIndex.isValid())
897 iface =
new QAccessibleTableCell(theView, modelIndex, cellRole());
899 QAccessible::registerAccessibleInterface(iface);
900 childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
904int QAccessibleTree::rowCount()
const
906 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
909 return treeView->d_func()->viewItems.size();
912int QAccessibleTree::indexOfChild(
const QAccessibleInterface *iface)
const
914 const QAbstractItemView *theView = view();
917 const QAbstractItemModel *theModel = theView->model();
920 QAccessibleInterface *parent = iface->parent();
921 if (parent->object() != theView)
924 if (iface->role() == QAccessible::TreeItem) {
925 const QAccessibleTableCell* cell =
static_cast<
const QAccessibleTableCell*>(iface);
926 const QTreeView *treeView = qobject_cast<
const QTreeView *>(theView);
928 int row = treeView->d_func()->viewIndex(cell->m_index) + (horizontalHeader() ? 1 : 0);
929 int column = cell->m_index.column();
931 int index = row * theModel->columnCount(theView->rootIndex()) + column;
933 }
else if (iface->role() == QAccessible::ColumnHeader){
934 const QAccessibleTableHeaderCell* cell =
static_cast<
const QAccessibleTableHeaderCell*>(iface);
937 qWarning() <<
"WARNING QAccessibleTable::indexOfChild invalid child"
938 << iface->role() << iface->text(QAccessible::Name);
944QAccessibleInterface *QAccessibleTree::cellAt(
int row,
int column)
const
946 QModelIndex index = indexFromLogical(row, column);
947 if (Q_UNLIKELY(!index.isValid())) {
948 qWarning(
"Requested invalid tree cell: %d %d", row, column);
951 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
953 int logicalIndex = treeView->d_func()->accessibleTable2Index(index);
955 return child(logicalIndex);
958QString QAccessibleTree::rowDescription(
int)
const
963bool QAccessibleTree::isRowSelected(
int row)
const
965 if (!view()->selectionModel())
967 QModelIndex index = indexFromLogical(row);
968 return view()->selectionModel()->isRowSelected(index.row(), index.parent());
971bool QAccessibleTree::selectRow(
int row)
973 if (!view()->selectionModel())
975 QModelIndex index = indexFromLogical(row);
977 if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns)
980 switch (view()->selectionMode()) {
981 case QAbstractItemView::NoSelection:
983 case QAbstractItemView::SingleSelection:
984 if ((view()->selectionBehavior() != QAbstractItemView::SelectRows) && (columnCount() > 1))
986 view()->clearSelection();
988 case QAbstractItemView::ContiguousSelection:
989 if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
990 && !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex()))
991 view()->clearSelection();
997 view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
1003#if QT_CONFIG(listview)
1007QAccessibleInterface *QAccessibleList::child(
int logicalIndex)
const
1009 QAbstractItemView *theView = view();
1012 const QAbstractItemModel *theModel = theView->model();
1016 if (columnCount() == 0) {
1020 const auto id = childToId.constFind(logicalIndex);
1021 if (id != childToId.constEnd())
1022 return QAccessible::accessibleInterface(id.value());
1024 const QListView *listView = qobject_cast<
const QListView*>(theView);
1026 int row = logicalIndex;
1027 int column = listView->modelColumn();
1029 const QModelIndex rootIndex = theView->rootIndex();
1030 const QModelIndex index = theModel->index(row, column, rootIndex);
1031 if (Q_UNLIKELY(!index.isValid())) {
1032 qWarning(
"QAccessibleList::child: Invalid index at: %d %d", row, column);
1035 const auto iface =
new QAccessibleTableCell(theView, index, cellRole());
1037 QAccessible::registerAccessibleInterface(iface);
1038 childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
1042QAccessibleInterface *QAccessibleList::cellAt(
int row,
int column)
const
1050int QAccessibleList::selectedCellCount()
const
1052 QAbstractItemView *theView = view();
1053 if (!theView->selectionModel())
1055 const QListView *listView = qobject_cast<
const QListView*>(theView);
1056 const int modelColumn = listView->modelColumn();
1057 const QModelIndexList selectedIndexes = theView->selectionModel()->selectedIndexes();
1058 return std::count_if(selectedIndexes.cbegin(), selectedIndexes.cend(),
1059 [modelColumn](
const auto &index) {
1060 return index.column() == modelColumn;
1064QList<QAccessibleInterface *> QAccessibleList::selectedCells()
const
1066 QAbstractItemView *theView = view();
1067 QList<QAccessibleInterface*> cells;
1068 if (!view()->selectionModel() || columnCount() == 0)
1070 const QListView *listView = qobject_cast<
const QListView*>(theView);
1071 const int modelColumn = listView->modelColumn();
1072 const QModelIndexList selectedIndexes = theView->selectionModel()->selectedIndexes();
1073 cells.reserve(qMin(selectedIndexes.size(), rowCount()));
1074 for (
const QModelIndex &index : selectedIndexes)
1075 if (index.column() == modelColumn) {
1076 cells.append(child(index.row()));
1085QAccessibleTableCell::QAccessibleTableCell(QAbstractItemView *view_,
const QModelIndex &index_, QAccessible::Role role_)
1086 : view(view_), m_index(index_), m_role(role_)
1088 if (Q_UNLIKELY(!index_.isValid()))
1089 qWarning() <<
"QAccessibleTableCell::QAccessibleTableCell with invalid index: " << index_;
1092void *QAccessibleTableCell::interface_cast(QAccessible::InterfaceType t)
1094 if (t == QAccessible::TableCellInterface)
1095 return static_cast<QAccessibleTableCellInterface*>(
this);
1096 if (t == QAccessible::ActionInterface)
1097 return static_cast<QAccessibleActionInterface*>(
this);
1101int QAccessibleTableCell::columnExtent()
const {
return 1; }
1102int QAccessibleTableCell::rowExtent()
const {
return 1; }
1104QList<QAccessibleInterface*> QAccessibleTableCell::rowHeaderCells()
const
1106 QList<QAccessibleInterface*> headerCell;
1107 if (verticalHeader()) {
1109 headerCell.append(
new QAccessibleTableHeaderCell(view, m_index.row(), Qt::Vertical));
1114QList<QAccessibleInterface*> QAccessibleTableCell::columnHeaderCells()
const
1116 QList<QAccessibleInterface*> headerCell;
1117 if (horizontalHeader()) {
1119 headerCell.append(
new QAccessibleTableHeaderCell(view, m_index.column(), Qt::Horizontal));
1124QHeaderView *QAccessibleTableCell::horizontalHeader()
const
1126 QHeaderView *header =
nullptr;
1129#if QT_CONFIG(tableview)
1130 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view)) {
1131 header = tv->horizontalHeader();
1133#if QT_CONFIG(treeview)
1134 }
else if (
const QTreeView *tv = qobject_cast<
const QTreeView*>(view)) {
1135 header = tv->header();
1142QHeaderView *QAccessibleTableCell::verticalHeader()
const
1144 QHeaderView *header =
nullptr;
1145#if QT_CONFIG(tableview)
1146 if (
const QTableView *tv = qobject_cast<
const QTableView*>(view))
1147 header = tv->verticalHeader();
1152int QAccessibleTableCell::columnIndex()
const
1156#if QT_CONFIG(listview)
1157 if (role() == QAccessible::ListItem) {
1161 return m_index.column();
1164int QAccessibleTableCell::rowIndex()
const
1168#if QT_CONFIG(treeview)
1169 if (role() == QAccessible::TreeItem) {
1170 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view);
1172 int row = treeView->d_func()->viewIndex(m_index);
1176 return m_index.row();
1179bool QAccessibleTableCell::isSelected()
const
1183 return view->selectionModel()->isSelected(m_index);
1186QStringList QAccessibleTableCell::actionNames()
const
1189 names << toggleAction();
1193void QAccessibleTableCell::doAction(
const QString& actionName)
1195 if (actionName == toggleAction()) {
1196#if defined(Q_OS_ANDROID)
1197 QAccessibleInterface *parentInterface = parent();
1198 while (parentInterface){
1199 if (parentInterface->role() == QAccessible::ComboBox) {
1201 parentInterface->actionInterface()->doAction(pressAction());
1204 parentInterface = parentInterface->parent();
1216QStringList QAccessibleTableCell::keyBindingsForAction(
const QString &)
const
1218 return QStringList();
1222void QAccessibleTableCell::selectCell()
1226 QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
1227 if (selectionMode == QAbstractItemView::NoSelection)
1230 QAccessibleTableInterface *cellTable = table()->tableInterface();
1232 switch (view->selectionBehavior()) {
1233 case QAbstractItemView::SelectItems:
1235 case QAbstractItemView::SelectColumns:
1237 cellTable->selectColumn(m_index.column());
1239 case QAbstractItemView::SelectRows:
1241 cellTable->selectRow(m_index.row());
1245 if (selectionMode == QAbstractItemView::SingleSelection) {
1246 view->clearSelection();
1249 view->selectionModel()->select(m_index, QItemSelectionModel::Select);
1252void QAccessibleTableCell::unselectCell()
1256 QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
1257 if (selectionMode == QAbstractItemView::NoSelection)
1260 QAccessibleTableInterface *cellTable = table()->tableInterface();
1262 switch (view->selectionBehavior()) {
1263 case QAbstractItemView::SelectItems:
1265 case QAbstractItemView::SelectColumns:
1267 cellTable->unselectColumn(m_index.column());
1269 case QAbstractItemView::SelectRows:
1271 cellTable->unselectRow(m_index.row());
1277 if ((selectionMode != QAbstractItemView::MultiSelection)
1278 && (selectionMode != QAbstractItemView::ExtendedSelection)
1279 && (view->selectionModel()->selectedIndexes().size() <= 1))
1282 view->selectionModel()->select(m_index, QItemSelectionModel::Deselect);
1285QAccessibleInterface *QAccessibleTableCell::table()
const
1287 return QAccessible::queryAccessibleInterface(view);
1290QAccessible::Role QAccessibleTableCell::role()
const
1295QAccessible::State QAccessibleTableCell::state()
const
1297 QAccessible::State st;
1301 QRect globalRect = view->rect();
1302 globalRect.translate(view->mapToGlobal(QPoint(0,0)));
1303 if (!globalRect.intersects(rect()))
1304 st.invisible =
true;
1306 if (view->selectionModel()->isSelected(m_index))
1308 if (view->selectionModel()->currentIndex() == m_index)
1311 const QVariant checkState = m_index.data(Qt::CheckStateRole);
1312 if (checkState.toInt() == Qt::Checked)
1315 Qt::ItemFlags flags = m_index.flags();
1316 if ((flags & Qt::ItemIsUserCheckable) && checkState.isValid())
1317 st.checkable =
true;
1318 if (flags & Qt::ItemIsSelectable) {
1319 st.selectable =
true;
1320 st.focusable =
true;
1321 if (view->selectionMode() == QAbstractItemView::MultiSelection)
1322 st.multiSelectable =
true;
1323 if (view->selectionMode() == QAbstractItemView::ExtendedSelection)
1324 st.extSelectable =
true;
1326#if QT_CONFIG(treeview)
1327 if (m_role == QAccessible::TreeItem) {
1328 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view);
1329 if (treeView->model()->hasChildren(m_index))
1330 st.expandable =
true;
1331 if (treeView->isExpanded(m_index))
1339QRect QAccessibleTableCell::rect()
const
1344 r = view->visualRect(m_index);
1347 r.translate(view->viewport()->mapTo(view, QPoint(0,0)));
1348 r.translate(view->mapToGlobal(QPoint(0, 0)));
1353QString QAccessibleTableCell::text(QAccessible::Text t)
const
1358 QAbstractItemModel *model = view->model();
1360 case QAccessible::Name:
1361 value = model->data(m_index, Qt::AccessibleTextRole).toString();
1362 if (value.isEmpty())
1363 value = model->data(m_index, Qt::DisplayRole).toString();
1365 case QAccessible::Description:
1366 value = model->data(m_index, Qt::AccessibleDescriptionRole).toString();
1374void QAccessibleTableCell::setText(QAccessible::Text ,
const QString &text)
1376 if (!isValid() || !(m_index.flags() & Qt::ItemIsEditable))
1378 view->model()->setData(m_index, text);
1381bool QAccessibleTableCell::isValid()
const
1383 return view && !qt_widget_private(view)->data.in_destructor
1384 && view->model() && m_index.isValid();
1387QAccessibleInterface *QAccessibleTableCell::parent()
const
1389 return QAccessible::queryAccessibleInterface(view);
1392QAccessibleInterface *QAccessibleTableCell::child(
int)
const
1397QAccessibleTableHeaderCell::QAccessibleTableHeaderCell(QAbstractItemView *view_,
int index_, Qt::Orientation orientation_)
1398 : view(view_), index(index_), orientation(orientation_)
1400 Q_ASSERT(index_ >= 0);
1403QAccessible::Role QAccessibleTableHeaderCell::role()
const
1405 if (orientation == Qt::Horizontal)
1406 return QAccessible::ColumnHeader;
1407 return QAccessible::RowHeader;
1410QAccessible::State QAccessibleTableHeaderCell::state()
const
1412 QAccessible::State s;
1413 if (QHeaderView *h = headerView()) {
1414 s.invisible = !h->testAttribute(Qt::WA_WState_Visible);
1415 s.disabled = !h->isEnabled();
1420QRect QAccessibleTableHeaderCell::rect()
const
1422 QHeaderView *header =
nullptr;
1424#if QT_CONFIG(tableview)
1425 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view)) {
1426 if (orientation == Qt::Horizontal) {
1427 header = tv->horizontalHeader();
1429 header = tv->verticalHeader();
1432#if QT_CONFIG(treeview)
1433 }
else if (
const QTreeView *tv = qobject_cast<
const QTreeView*>(view)) {
1434 header = tv->header();
1439 QPoint zero = header->mapToGlobal(QPoint(0, 0));
1440 int sectionSize = header->sectionSize(index);
1441 int sectionPos = header->sectionPosition(index);
1442 return orientation == Qt::Horizontal
1443 ? QRect(zero.x() + sectionPos, zero.y(), sectionSize, header->height())
1444 : QRect(zero.x(), zero.y() + sectionPos, header->width(), sectionSize);
1447QString QAccessibleTableHeaderCell::text(QAccessible::Text t)
const
1449 QAbstractItemModel *model = view->model();
1452 case QAccessible::Name:
1453 value = model->headerData(index, orientation, Qt::AccessibleTextRole).toString();
1454 if (value.isEmpty())
1455 value = model->headerData(index, orientation, Qt::DisplayRole).toString();
1457 case QAccessible::Description:
1458 value = model->headerData(index, orientation, Qt::AccessibleDescriptionRole).toString();
1466void QAccessibleTableHeaderCell::setText(QAccessible::Text,
const QString &)
1471bool QAccessibleTableHeaderCell::isValid()
const
1473 const QAbstractItemModel *theModel = view && !qt_widget_private(view)->data.in_destructor
1474 ? view->model() :
nullptr;
1477 const QModelIndex rootIndex = view->rootIndex();
1478 return (index >= 0) && ((orientation == Qt::Horizontal)
1479 ? (index < theModel->columnCount(rootIndex))
1480 : (index < theModel->rowCount(rootIndex)));
1483QAccessibleInterface *QAccessibleTableHeaderCell::parent()
const
1485 return QAccessible::queryAccessibleInterface(view);
1488QAccessibleInterface *QAccessibleTableHeaderCell::child(
int)
const
1493QHeaderView *QAccessibleTableHeaderCell::headerView()
const
1495 QHeaderView *header =
nullptr;
1497#if QT_CONFIG(tableview)
1498 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view)) {
1499 if (orientation == Qt::Horizontal) {
1500 header = tv->horizontalHeader();
1502 header = tv->verticalHeader();
1505#if QT_CONFIG(treeview)
1506 }
else if (
const QTreeView *tv = qobject_cast<
const QTreeView*>(view)) {
1507 header = tv->header();