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 : QAccessibleWidgetV2(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);
592QRect QAccessibleTable::rect()
const
594 if (!view()->isVisible())
596 QPoint pos = view()->mapToGlobal(QPoint(0, 0));
597 return QRect(pos.x(), pos.y(), view()->width(), view()->height());
600QAccessibleInterface *QAccessibleTable::parent()
const
602 if (view() && view()->parent()) {
603 if (qstrcmp(
"QComboBoxPrivateContainer", view()->parent()->metaObject()->className()) == 0) {
604 return QAccessible::queryAccessibleInterface(view()->parent()->parent());
606 return QAccessible::queryAccessibleInterface(view()->parent());
608 return QAccessible::queryAccessibleInterface(qApp);
611QAccessibleInterface *QAccessibleTable::child(
int logicalIndex)
const
613 QAbstractItemView *theView = view();
617 const QAbstractItemModel *theModel = theView->model();
621 const QModelIndex rootIndex = theView->rootIndex();
622 auto id = childToId.constFind(logicalIndex);
623 if (id != childToId.constEnd())
624 return QAccessible::accessibleInterface(id.value());
626 int vHeader = verticalHeader() ? 1 : 0;
627 int hHeader = horizontalHeader() ? 1 : 0;
629 int columns = theModel->columnCount(rootIndex) + vHeader;
631 int row = logicalIndex / columns;
632 int column = logicalIndex % columns;
634 QAccessibleInterface *iface =
nullptr;
638 if (hHeader && row == 0) {
639 iface =
new QAccessibleTableCornerButton(theView);
641 iface =
new QAccessibleTableHeaderCell(theView, row - hHeader, Qt::Vertical);
646 if (!iface && hHeader) {
648 iface =
new QAccessibleTableHeaderCell(theView, column, Qt::Horizontal);
654 QModelIndex index = theModel->index(row, column, rootIndex);
655 if (Q_UNLIKELY(!index.isValid())) {
656 qWarning(
"QAccessibleTable::child: Invalid index at: %d %d", row, column);
659 iface =
new QAccessibleTableCell(theView, index, cellRole());
662 QAccessible::registerAccessibleInterface(iface);
663 childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
667void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t)
669 if (t == QAccessible::SelectionInterface)
670 return static_cast<QAccessibleSelectionInterface*>(
this);
671 if (t == QAccessible::TableInterface)
672 return static_cast<QAccessibleTableInterface*>(
this);
673 return QAccessibleWidgetV2::interface_cast(t);
676void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event)
679 if (childToId.isEmpty())
682 switch (event->modelChangeType()) {
683 case QAccessibleTableModelChangeEvent::ModelReset:
684 for (QAccessible::Id id : std::as_const(childToId))
685 QAccessible::deleteAccessibleInterface(id);
690 case QAccessibleTableModelChangeEvent::RowsInserted:
691 case QAccessibleTableModelChangeEvent::ColumnsInserted: {
692 int newRows = event->lastRow() - event->firstRow() + 1;
693 int newColumns = event->lastColumn() - event->firstColumn() + 1;
696 ChildCache::ConstIterator iter = childToId.constBegin();
698 while (iter != childToId.constEnd()) {
699 QAccessible::Id id = iter.value();
700 QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
702 if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted
703 && iface->role() == QAccessible::RowHeader) {
704 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
705 if (cell->index >= event->firstRow()) {
706 cell->index += newRows;
708 }
else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted
709 && iface->role() == QAccessible::ColumnHeader) {
710 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
711 if (cell->index >= event->firstColumn()) {
712 cell->index += newColumns;
715 if (indexOfChild(iface) >= 0) {
716 newCache.insert(indexOfChild(iface), id);
721 QAccessible::deleteAccessibleInterface(id);
725 childToId = newCache;
729 case QAccessibleTableModelChangeEvent::ColumnsRemoved:
730 case QAccessibleTableModelChangeEvent::RowsRemoved: {
731 int deletedColumns = event->lastColumn() - event->firstColumn() + 1;
732 int deletedRows = event->lastRow() - event->firstRow() + 1;
734 ChildCache::ConstIterator iter = childToId.constBegin();
735 while (iter != childToId.constEnd()) {
736 QAccessible::Id id = iter.value();
737 QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
739 if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
740 Q_ASSERT(iface->tableCellInterface());
741 QAccessibleTableCell *cell =
static_cast<QAccessibleTableCell*>(iface->tableCellInterface());
743 if (cell->m_index.isValid())
744 newCache.insert(indexOfChild(cell), id);
746 QAccessible::deleteAccessibleInterface(id);
747 }
else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved
748 && iface->role() == QAccessible::RowHeader) {
749 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
750 if (cell->index < event->firstRow()) {
751 newCache.insert(indexOfChild(cell), id);
752 }
else if (cell->index > event->lastRow()) {
753 cell->index -= deletedRows;
754 newCache.insert(indexOfChild(cell), id);
756 QAccessible::deleteAccessibleInterface(id);
758 }
else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved
759 && iface->role() == QAccessible::ColumnHeader) {
760 QAccessibleTableHeaderCell *cell =
static_cast<QAccessibleTableHeaderCell*>(iface);
761 if (cell->index < event->firstColumn()) {
762 newCache.insert(indexOfChild(cell), id);
763 }
else if (cell->index > event->lastColumn()) {
764 cell->index -= deletedColumns;
765 newCache.insert(indexOfChild(cell), id);
767 QAccessible::deleteAccessibleInterface(id);
772 childToId = newCache;
776 case QAccessibleTableModelChangeEvent::DataChanged:
782#if QT_CONFIG(treeview)
786QModelIndex QAccessibleTree::indexFromLogical(
int row,
int column)
const
788 if (!isValid() || !view()->model())
789 return QModelIndex();
791 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
792 if (Q_UNLIKELY(row < 0 || column < 0 || treeView->d_func()->viewItems.size() <= row)) {
793 qWarning() <<
"QAccessibleTree::indexFromLogical: invalid index: " << row << column <<
" for " << treeView;
794 return QModelIndex();
796 QModelIndex modelIndex = treeView->d_func()->viewItems.at(row).index;
798 if (modelIndex.isValid() && column > 0) {
799 modelIndex = view()->model()->index(modelIndex.row(), column, modelIndex.parent());
804QAccessibleInterface *QAccessibleTree::childAt(
int x,
int y)
const
806 const QAbstractItemView *theView = view();
809 const QAbstractItemModel *theModel = theView->model();
813 const QPoint viewportOffset = theView->viewport()->mapTo(theView, QPoint(0, 0));
814 const QPoint indexPosition = theView->mapFromGlobal(QPoint(x, y) - viewportOffset);
816 const QModelIndex index = theView->indexAt(indexPosition);
817 if (!index.isValid())
820 const QTreeView *treeView = qobject_cast<
const QTreeView *>(theView);
821 int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0);
822 int column = index.column();
824 int i = row * theModel->columnCount(theView->rootIndex()) + column;
828QAccessibleInterface *QAccessibleTree::focusChild()
const
830 const QAbstractItemView *theView = view();
833 const QAbstractItemModel *theModel = theView->model();
834 const QModelIndex index = theView->currentIndex();
835 if (!index.isValid())
838 const QTreeView *treeView = qobject_cast<
const QTreeView *>(theView);
839 const int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0);
840 const int column = index.column();
842 int i = row * theModel->columnCount(theView->rootIndex()) + column;
846int QAccessibleTree::childCount()
const
848 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
851 const QAbstractItemModel *theModel = treeView->model();
855 int hHeader = horizontalHeader() ? 1 : 0;
856 return (treeView->d_func()->viewItems.size() + hHeader)
857 * theModel->columnCount(treeView->rootIndex());
860QAccessibleInterface *QAccessibleTree::child(
int logicalIndex)
const
862 QAbstractItemView *theView = view();
865 const QAbstractItemModel *theModel = theView->model();
866 const QModelIndex rootIndex = theView->rootIndex();
867 if (logicalIndex < 0 || !theModel || !theModel->columnCount(rootIndex))
870 auto id = childToId.constFind(logicalIndex);
871 if (id != childToId.constEnd())
872 return QAccessible::accessibleInterface(id.value());
874 QAccessibleInterface *iface =
nullptr;
875 int index = logicalIndex;
877 if (horizontalHeader()) {
878 if (index < theModel->columnCount(rootIndex))
879 iface =
new QAccessibleTableHeaderCell(theView, index, Qt::Horizontal);
881 index -= theModel->columnCount(rootIndex);
885 const int row = index / theModel->columnCount(rootIndex);
886 const int column = index % theModel->columnCount(rootIndex);
887 const QModelIndex modelIndex = indexFromLogical(row, column);
888 if (!modelIndex.isValid())
890 iface =
new QAccessibleTableCell(theView, modelIndex, cellRole());
892 QAccessible::registerAccessibleInterface(iface);
893 childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
897int QAccessibleTree::rowCount()
const
899 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
902 return treeView->d_func()->viewItems.size();
905int QAccessibleTree::indexOfChild(
const QAccessibleInterface *iface)
const
907 const QAbstractItemView *theView = view();
910 const QAbstractItemModel *theModel = theView->model();
913 QAccessibleInterface *parent = iface->parent();
914 if (parent->object() != theView)
917 if (iface->role() == QAccessible::TreeItem) {
918 const QAccessibleTableCell* cell =
static_cast<
const QAccessibleTableCell*>(iface);
919 const QTreeView *treeView = qobject_cast<
const QTreeView *>(theView);
921 int row = treeView->d_func()->viewIndex(cell->m_index) + (horizontalHeader() ? 1 : 0);
922 int column = cell->m_index.column();
924 int index = row * theModel->columnCount(theView->rootIndex()) + column;
926 }
else if (iface->role() == QAccessible::ColumnHeader){
927 const QAccessibleTableHeaderCell* cell =
static_cast<
const QAccessibleTableHeaderCell*>(iface);
930 qWarning() <<
"WARNING QAccessibleTable::indexOfChild invalid child"
931 << iface->role() << iface->text(QAccessible::Name);
937QAccessibleInterface *QAccessibleTree::cellAt(
int row,
int column)
const
939 QModelIndex index = indexFromLogical(row, column);
940 if (Q_UNLIKELY(!index.isValid())) {
941 qWarning(
"Requested invalid tree cell: %d %d", row, column);
944 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view());
946 int logicalIndex = treeView->d_func()->accessibleTable2Index(index);
948 return child(logicalIndex);
951QString QAccessibleTree::rowDescription(
int)
const
956bool QAccessibleTree::isRowSelected(
int row)
const
958 if (!view()->selectionModel())
960 QModelIndex index = indexFromLogical(row);
961 return view()->selectionModel()->isRowSelected(index.row(), index.parent());
964bool QAccessibleTree::selectRow(
int row)
966 if (!view()->selectionModel())
968 QModelIndex index = indexFromLogical(row);
970 if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns)
973 switch (view()->selectionMode()) {
974 case QAbstractItemView::NoSelection:
976 case QAbstractItemView::SingleSelection:
977 if ((view()->selectionBehavior() != QAbstractItemView::SelectRows) && (columnCount() > 1))
979 view()->clearSelection();
981 case QAbstractItemView::ContiguousSelection:
982 if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
983 && !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex()))
984 view()->clearSelection();
990 view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
996#if QT_CONFIG(listview)
1000QAccessibleInterface *QAccessibleList::child(
int logicalIndex)
const
1002 QAbstractItemView *theView = view();
1005 const QAbstractItemModel *theModel = theView->model();
1009 if (columnCount() == 0) {
1013 const auto id = childToId.constFind(logicalIndex);
1014 if (id != childToId.constEnd())
1015 return QAccessible::accessibleInterface(id.value());
1017 const QListView *listView = qobject_cast<
const QListView*>(theView);
1019 int row = logicalIndex;
1020 int column = listView->modelColumn();
1022 const QModelIndex rootIndex = theView->rootIndex();
1023 const QModelIndex index = theModel->index(row, column, rootIndex);
1024 if (Q_UNLIKELY(!index.isValid())) {
1025 qWarning(
"QAccessibleList::child: Invalid index at: %d %d", row, column);
1028 const auto iface =
new QAccessibleTableCell(theView, index, cellRole());
1030 QAccessible::registerAccessibleInterface(iface);
1031 childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
1035QAccessibleInterface *QAccessibleList::cellAt(
int row,
int column)
const
1043int QAccessibleList::selectedCellCount()
const
1045 QAbstractItemView *theView = view();
1046 if (!theView->selectionModel())
1048 const QListView *listView = qobject_cast<
const QListView*>(theView);
1049 const int modelColumn = listView->modelColumn();
1050 const QModelIndexList selectedIndexes = theView->selectionModel()->selectedIndexes();
1051 return std::count_if(selectedIndexes.cbegin(), selectedIndexes.cend(),
1052 [modelColumn](
const auto &index) {
1053 return index.column() == modelColumn;
1057QList<QAccessibleInterface *> QAccessibleList::selectedCells()
const
1059 QAbstractItemView *theView = view();
1060 QList<QAccessibleInterface*> cells;
1061 if (!view()->selectionModel() || columnCount() == 0)
1063 const QListView *listView = qobject_cast<
const QListView*>(theView);
1064 const int modelColumn = listView->modelColumn();
1065 const QModelIndexList selectedIndexes = theView->selectionModel()->selectedIndexes();
1066 cells.reserve(qMin(selectedIndexes.size(), rowCount()));
1067 for (
const QModelIndex &index : selectedIndexes)
1068 if (index.column() == modelColumn) {
1069 cells.append(child(index.row()));
1078QAccessibleTableCell::QAccessibleTableCell(QAbstractItemView *view_,
const QModelIndex &index_, QAccessible::Role role_)
1079 : view(view_), m_index(index_), m_role(role_)
1081 if (Q_UNLIKELY(!index_.isValid()))
1082 qWarning() <<
"QAccessibleTableCell::QAccessibleTableCell with invalid index: " << index_;
1085void *QAccessibleTableCell::interface_cast(QAccessible::InterfaceType t)
1087 if (t == QAccessible::TableCellInterface)
1088 return static_cast<QAccessibleTableCellInterface*>(
this);
1089 if (t == QAccessible::ActionInterface)
1090 return static_cast<QAccessibleActionInterface*>(
this);
1094int QAccessibleTableCell::columnExtent()
const {
return 1; }
1095int QAccessibleTableCell::rowExtent()
const {
return 1; }
1097QList<QAccessibleInterface*> QAccessibleTableCell::rowHeaderCells()
const
1099 QList<QAccessibleInterface*> headerCell;
1100 if (verticalHeader()) {
1102 headerCell.append(
new QAccessibleTableHeaderCell(view, m_index.row(), Qt::Vertical));
1107QList<QAccessibleInterface*> QAccessibleTableCell::columnHeaderCells()
const
1109 QList<QAccessibleInterface*> headerCell;
1110 if (horizontalHeader()) {
1112 headerCell.append(
new QAccessibleTableHeaderCell(view, m_index.column(), Qt::Horizontal));
1117QHeaderView *QAccessibleTableCell::horizontalHeader()
const
1119 QHeaderView *header =
nullptr;
1122#if QT_CONFIG(tableview)
1123 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view)) {
1124 header = tv->horizontalHeader();
1126#if QT_CONFIG(treeview)
1127 }
else if (
const QTreeView *tv = qobject_cast<
const QTreeView*>(view)) {
1128 header = tv->header();
1135QHeaderView *QAccessibleTableCell::verticalHeader()
const
1137 QHeaderView *header =
nullptr;
1138#if QT_CONFIG(tableview)
1139 if (
const QTableView *tv = qobject_cast<
const QTableView*>(view))
1140 header = tv->verticalHeader();
1145int QAccessibleTableCell::columnIndex()
const
1149#if QT_CONFIG(listview)
1150 if (role() == QAccessible::ListItem) {
1154 return m_index.column();
1157int QAccessibleTableCell::rowIndex()
const
1161#if QT_CONFIG(treeview)
1162 if (role() == QAccessible::TreeItem) {
1163 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view);
1165 int row = treeView->d_func()->viewIndex(m_index);
1169 return m_index.row();
1172bool QAccessibleTableCell::isSelected()
const
1176 return view->selectionModel()->isSelected(m_index);
1179QStringList QAccessibleTableCell::actionNames()
const
1182 names << toggleAction();
1186void QAccessibleTableCell::doAction(
const QString& actionName)
1188 if (actionName == toggleAction()) {
1189#if defined(Q_OS_ANDROID)
1190 QAccessibleInterface *parentInterface = parent();
1191 while (parentInterface){
1192 if (parentInterface->role() == QAccessible::ComboBox) {
1194 parentInterface->actionInterface()->doAction(pressAction());
1197 parentInterface = parentInterface->parent();
1209QStringList QAccessibleTableCell::keyBindingsForAction(
const QString &)
const
1211 return QStringList();
1215void QAccessibleTableCell::selectCell()
1219 QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
1220 if (selectionMode == QAbstractItemView::NoSelection)
1223 QAccessibleTableInterface *cellTable = table()->tableInterface();
1225 switch (view->selectionBehavior()) {
1226 case QAbstractItemView::SelectItems:
1228 case QAbstractItemView::SelectColumns:
1230 cellTable->selectColumn(m_index.column());
1232 case QAbstractItemView::SelectRows:
1234 cellTable->selectRow(m_index.row());
1238 if (selectionMode == QAbstractItemView::SingleSelection) {
1239 view->clearSelection();
1242 view->selectionModel()->select(m_index, QItemSelectionModel::Select);
1245void QAccessibleTableCell::unselectCell()
1249 QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
1250 if (selectionMode == QAbstractItemView::NoSelection)
1253 QAccessibleTableInterface *cellTable = table()->tableInterface();
1255 switch (view->selectionBehavior()) {
1256 case QAbstractItemView::SelectItems:
1258 case QAbstractItemView::SelectColumns:
1260 cellTable->unselectColumn(m_index.column());
1262 case QAbstractItemView::SelectRows:
1264 cellTable->unselectRow(m_index.row());
1270 if ((selectionMode != QAbstractItemView::MultiSelection)
1271 && (selectionMode != QAbstractItemView::ExtendedSelection)
1272 && (view->selectionModel()->selectedIndexes().size() <= 1))
1275 view->selectionModel()->select(m_index, QItemSelectionModel::Deselect);
1278QAccessibleInterface *QAccessibleTableCell::table()
const
1280 return QAccessible::queryAccessibleInterface(view);
1283QAccessible::Role QAccessibleTableCell::role()
const
1288QAccessible::State QAccessibleTableCell::state()
const
1290 QAccessible::State st;
1294 QRect globalRect = view->rect();
1295 globalRect.translate(view->mapToGlobal(QPoint(0,0)));
1296 if (!globalRect.intersects(rect()))
1297 st.invisible =
true;
1299 if (view->selectionModel()->isSelected(m_index))
1301 if (view->selectionModel()->currentIndex() == m_index)
1304 const QVariant checkState = m_index.data(Qt::CheckStateRole);
1305 if (checkState.toInt() == Qt::Checked)
1308 Qt::ItemFlags flags = m_index.flags();
1309 if ((flags & Qt::ItemIsUserCheckable) && checkState.isValid())
1310 st.checkable =
true;
1311 if (flags & Qt::ItemIsSelectable) {
1312 st.selectable =
true;
1313 st.focusable =
true;
1314 if (view->selectionMode() == QAbstractItemView::MultiSelection)
1315 st.multiSelectable =
true;
1316 if (view->selectionMode() == QAbstractItemView::ExtendedSelection)
1317 st.extSelectable =
true;
1319#if QT_CONFIG(treeview)
1320 if (m_role == QAccessible::TreeItem) {
1321 const QTreeView *treeView = qobject_cast<
const QTreeView*>(view);
1322 if (treeView->model()->hasChildren(m_index))
1323 st.expandable =
true;
1324 if (treeView->isExpanded(m_index))
1332QRect QAccessibleTableCell::rect()
const
1337 r = view->visualRect(m_index);
1340 r.translate(view->viewport()->mapTo(view, QPoint(0,0)));
1341 r.translate(view->mapToGlobal(QPoint(0, 0)));
1346QString QAccessibleTableCell::text(QAccessible::Text t)
const
1351 QAbstractItemModel *model = view->model();
1353 case QAccessible::Name:
1354 value = model->data(m_index, Qt::AccessibleTextRole).toString();
1355 if (value.isEmpty())
1356 value = model->data(m_index, Qt::DisplayRole).toString();
1358 case QAccessible::Description:
1359 value = model->data(m_index, Qt::AccessibleDescriptionRole).toString();
1367void QAccessibleTableCell::setText(QAccessible::Text ,
const QString &text)
1369 if (!isValid() || !(m_index.flags() & Qt::ItemIsEditable))
1371 view->model()->setData(m_index, text);
1374bool QAccessibleTableCell::isValid()
const
1376 return view && !qt_widget_private(view)->data.in_destructor
1377 && view->model() && m_index.isValid();
1380QAccessibleInterface *QAccessibleTableCell::parent()
const
1382 return QAccessible::queryAccessibleInterface(view);
1385QAccessibleInterface *QAccessibleTableCell::child(
int)
const
1390QAccessibleTableHeaderCell::QAccessibleTableHeaderCell(QAbstractItemView *view_,
int index_, Qt::Orientation orientation_)
1391 : view(view_), index(index_), orientation(orientation_)
1393 Q_ASSERT(index_ >= 0);
1396QAccessible::Role QAccessibleTableHeaderCell::role()
const
1398 if (orientation == Qt::Horizontal)
1399 return QAccessible::ColumnHeader;
1400 return QAccessible::RowHeader;
1403QAccessible::State QAccessibleTableHeaderCell::state()
const
1405 QAccessible::State s;
1406 if (QHeaderView *h = headerView()) {
1407 s.invisible = !h->testAttribute(Qt::WA_WState_Visible);
1408 s.disabled = !h->isEnabled();
1413QRect QAccessibleTableHeaderCell::rect()
const
1415 QHeaderView *header =
nullptr;
1417#if QT_CONFIG(tableview)
1418 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view)) {
1419 if (orientation == Qt::Horizontal) {
1420 header = tv->horizontalHeader();
1422 header = tv->verticalHeader();
1425#if QT_CONFIG(treeview)
1426 }
else if (
const QTreeView *tv = qobject_cast<
const QTreeView*>(view)) {
1427 header = tv->header();
1432 QPoint zero = header->mapToGlobal(QPoint(0, 0));
1433 int sectionSize = header->sectionSize(index);
1434 int sectionPos = header->sectionPosition(index);
1435 return orientation == Qt::Horizontal
1436 ? QRect(zero.x() + sectionPos, zero.y(), sectionSize, header->height())
1437 : QRect(zero.x(), zero.y() + sectionPos, header->width(), sectionSize);
1440QString QAccessibleTableHeaderCell::text(QAccessible::Text t)
const
1442 QAbstractItemModel *model = view->model();
1445 case QAccessible::Name:
1446 value = model->headerData(index, orientation, Qt::AccessibleTextRole).toString();
1447 if (value.isEmpty())
1448 value = model->headerData(index, orientation, Qt::DisplayRole).toString();
1450 case QAccessible::Description:
1451 value = model->headerData(index, orientation, Qt::AccessibleDescriptionRole).toString();
1459void QAccessibleTableHeaderCell::setText(QAccessible::Text,
const QString &)
1464bool QAccessibleTableHeaderCell::isValid()
const
1466 const QAbstractItemModel *theModel = view && !qt_widget_private(view)->data.in_destructor
1467 ? view->model() :
nullptr;
1470 const QModelIndex rootIndex = view->rootIndex();
1471 return (index >= 0) && ((orientation == Qt::Horizontal)
1472 ? (index < theModel->columnCount(rootIndex))
1473 : (index < theModel->rowCount(rootIndex)));
1476QAccessibleInterface *QAccessibleTableHeaderCell::parent()
const
1478 return QAccessible::queryAccessibleInterface(view);
1481QAccessibleInterface *QAccessibleTableHeaderCell::child(
int)
const
1486QHeaderView *QAccessibleTableHeaderCell::headerView()
const
1488 QHeaderView *header =
nullptr;
1490#if QT_CONFIG(tableview)
1491 }
else if (
const QTableView *tv = qobject_cast<
const QTableView*>(view)) {
1492 if (orientation == Qt::Horizontal) {
1493 header = tv->horizontalHeader();
1495 header = tv->verticalHeader();
1498#if QT_CONFIG(treeview)
1499 }
else if (
const QTreeView *tv = qobject_cast<
const QTreeView*>(view)) {
1500 header = tv->header();