1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the plugins of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "itemviews_p.h" |
41 | |
42 | #include <qheaderview.h> |
43 | #if QT_CONFIG(tableview) |
44 | #include <qtableview.h> |
45 | #endif |
46 | #if QT_CONFIG(listview) |
47 | #include <qlistview.h> |
48 | #endif |
49 | #if QT_CONFIG(treeview) |
50 | #include <qtreeview.h> |
51 | #include <private/qtreeview_p.h> |
52 | #endif |
53 | #include <private/qwidget_p.h> |
54 | |
55 | #ifndef QT_NO_ACCESSIBILITY |
56 | |
57 | QT_BEGIN_NAMESPACE |
58 | |
59 | /* |
60 | Implementation of the IAccessible2 table2 interface. Much simpler than |
61 | the other table interfaces since there is only the main table and cells: |
62 | |
63 | TABLE/LIST/TREE |
64 | |- HEADER CELL |
65 | |- CELL |
66 | |- CELL |
67 | ... |
68 | */ |
69 | |
70 | |
71 | QAbstractItemView *QAccessibleTable::view() const |
72 | { |
73 | return qobject_cast<QAbstractItemView*>(object: object()); |
74 | } |
75 | |
76 | int QAccessibleTable::logicalIndex(const QModelIndex &index) const |
77 | { |
78 | if (!view()->model() || !index.isValid()) |
79 | return -1; |
80 | int = verticalHeader() ? 1 : 0; |
81 | int = horizontalHeader() ? 1 : 0; |
82 | return (index.row() + hHeader)*(index.model()->columnCount() + vHeader) + (index.column() + vHeader); |
83 | } |
84 | |
85 | QAccessibleTable::QAccessibleTable(QWidget *w) |
86 | : QAccessibleObject(w) |
87 | { |
88 | Q_ASSERT(view()); |
89 | |
90 | #if QT_CONFIG(tableview) |
91 | if (qobject_cast<const QTableView*>(object: view())) { |
92 | m_role = QAccessible::Table; |
93 | } else |
94 | #endif |
95 | #if QT_CONFIG(treeview) |
96 | if (qobject_cast<const QTreeView*>(object: view())) { |
97 | m_role = QAccessible::Tree; |
98 | } else |
99 | #endif |
100 | #if QT_CONFIG(listview) |
101 | if (qobject_cast<const QListView*>(object: view())) { |
102 | m_role = QAccessible::List; |
103 | } else |
104 | #endif |
105 | { |
106 | // is this our best guess? |
107 | m_role = QAccessible::Table; |
108 | } |
109 | } |
110 | |
111 | bool QAccessibleTable::isValid() const |
112 | { |
113 | return view() && !qt_widget_private(widget: view())->data.in_destructor; |
114 | } |
115 | |
116 | QAccessibleTable::~QAccessibleTable() |
117 | { |
118 | for (QAccessible::Id id : qAsConst(t&: childToId)) |
119 | QAccessible::deleteAccessibleInterface(uniqueId: id); |
120 | } |
121 | |
122 | QHeaderView *QAccessibleTable::() const |
123 | { |
124 | QHeaderView * = nullptr; |
125 | if (false) { |
126 | #if QT_CONFIG(tableview) |
127 | } else if (const QTableView *tv = qobject_cast<const QTableView*>(object: view())) { |
128 | header = tv->horizontalHeader(); |
129 | #endif |
130 | #if QT_CONFIG(treeview) |
131 | } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(object: view())) { |
132 | header = tv->header(); |
133 | #endif |
134 | } |
135 | return header; |
136 | } |
137 | |
138 | QHeaderView *QAccessibleTable::() const |
139 | { |
140 | QHeaderView * = nullptr; |
141 | if (false) { |
142 | #if QT_CONFIG(tableview) |
143 | } else if (const QTableView *tv = qobject_cast<const QTableView*>(object: view())) { |
144 | header = tv->verticalHeader(); |
145 | #endif |
146 | } |
147 | return header; |
148 | } |
149 | |
150 | QAccessibleInterface *QAccessibleTable::cellAt(int row, int column) const |
151 | { |
152 | if (!view()->model()) |
153 | return nullptr; |
154 | Q_ASSERT(role() != QAccessible::Tree); |
155 | QModelIndex index = view()->model()->index(row, column, parent: view()->rootIndex()); |
156 | if (Q_UNLIKELY(!index.isValid())) { |
157 | qWarning() << "QAccessibleTable::cellAt: invalid index: " << index << " for " << view(); |
158 | return nullptr; |
159 | } |
160 | return child(index: logicalIndex(index)); |
161 | } |
162 | |
163 | QAccessibleInterface *QAccessibleTable::caption() const |
164 | { |
165 | return nullptr; |
166 | } |
167 | |
168 | QString QAccessibleTable::columnDescription(int column) const |
169 | { |
170 | if (!view()->model()) |
171 | return QString(); |
172 | return view()->model()->headerData(section: column, orientation: Qt::Horizontal).toString(); |
173 | } |
174 | |
175 | int QAccessibleTable::columnCount() const |
176 | { |
177 | if (!view()->model()) |
178 | return 0; |
179 | return view()->model()->columnCount(); |
180 | } |
181 | |
182 | int QAccessibleTable::rowCount() const |
183 | { |
184 | if (!view()->model()) |
185 | return 0; |
186 | return view()->model()->rowCount(); |
187 | } |
188 | |
189 | int QAccessibleTable::selectedCellCount() const |
190 | { |
191 | if (!view()->selectionModel()) |
192 | return 0; |
193 | return view()->selectionModel()->selectedIndexes().count(); |
194 | } |
195 | |
196 | int QAccessibleTable::selectedColumnCount() const |
197 | { |
198 | if (!view()->selectionModel()) |
199 | return 0; |
200 | return view()->selectionModel()->selectedColumns().count(); |
201 | } |
202 | |
203 | int QAccessibleTable::selectedRowCount() const |
204 | { |
205 | if (!view()->selectionModel()) |
206 | return 0; |
207 | return view()->selectionModel()->selectedRows().count(); |
208 | } |
209 | |
210 | QString QAccessibleTable::rowDescription(int row) const |
211 | { |
212 | if (!view()->model()) |
213 | return QString(); |
214 | return view()->model()->headerData(section: row, orientation: Qt::Vertical).toString(); |
215 | } |
216 | |
217 | QList<QAccessibleInterface *> QAccessibleTable::selectedCells() const |
218 | { |
219 | QList<QAccessibleInterface*> cells; |
220 | if (!view()->selectionModel()) |
221 | return cells; |
222 | const QModelIndexList selectedIndexes = view()->selectionModel()->selectedIndexes(); |
223 | cells.reserve(alloc: selectedIndexes.size()); |
224 | for (const QModelIndex &index : selectedIndexes) |
225 | cells.append(t: child(index: logicalIndex(index))); |
226 | return cells; |
227 | } |
228 | |
229 | QList<int> QAccessibleTable::selectedColumns() const |
230 | { |
231 | if (!view()->selectionModel()) |
232 | return QList<int>(); |
233 | QList<int> columns; |
234 | const QModelIndexList selectedColumns = view()->selectionModel()->selectedColumns(); |
235 | columns.reserve(alloc: selectedColumns.size()); |
236 | for (const QModelIndex &index : selectedColumns) |
237 | columns.append(t: index.column()); |
238 | |
239 | return columns; |
240 | } |
241 | |
242 | QList<int> QAccessibleTable::selectedRows() const |
243 | { |
244 | if (!view()->selectionModel()) |
245 | return QList<int>(); |
246 | QList<int> rows; |
247 | const QModelIndexList selectedRows = view()->selectionModel()->selectedRows(); |
248 | rows.reserve(alloc: selectedRows.size()); |
249 | for (const QModelIndex &index : selectedRows) |
250 | rows.append(t: index.row()); |
251 | |
252 | return rows; |
253 | } |
254 | |
255 | QAccessibleInterface *QAccessibleTable::summary() const |
256 | { |
257 | return nullptr; |
258 | } |
259 | |
260 | bool QAccessibleTable::isColumnSelected(int column) const |
261 | { |
262 | if (!view()->selectionModel()) |
263 | return false; |
264 | return view()->selectionModel()->isColumnSelected(column, parent: QModelIndex()); |
265 | } |
266 | |
267 | bool QAccessibleTable::isRowSelected(int row) const |
268 | { |
269 | if (!view()->selectionModel()) |
270 | return false; |
271 | return view()->selectionModel()->isRowSelected(row, parent: QModelIndex()); |
272 | } |
273 | |
274 | bool QAccessibleTable::selectRow(int row) |
275 | { |
276 | if (!view()->model() || !view()->selectionModel()) |
277 | return false; |
278 | QModelIndex index = view()->model()->index(row, column: 0, parent: view()->rootIndex()); |
279 | |
280 | if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns) |
281 | return false; |
282 | |
283 | switch (view()->selectionMode()) { |
284 | case QAbstractItemView::NoSelection: |
285 | return false; |
286 | case QAbstractItemView::SingleSelection: |
287 | if (view()->selectionBehavior() != QAbstractItemView::SelectRows && columnCount() > 1 ) |
288 | return false; |
289 | view()->clearSelection(); |
290 | break; |
291 | case QAbstractItemView::ContiguousSelection: |
292 | if ((!row || !view()->selectionModel()->isRowSelected(row: row - 1, parent: view()->rootIndex())) |
293 | && !view()->selectionModel()->isRowSelected(row: row + 1, parent: view()->rootIndex())) |
294 | view()->clearSelection(); |
295 | break; |
296 | default: |
297 | break; |
298 | } |
299 | |
300 | view()->selectionModel()->select(index, command: QItemSelectionModel::Select | QItemSelectionModel::Rows); |
301 | return true; |
302 | } |
303 | |
304 | bool QAccessibleTable::selectColumn(int column) |
305 | { |
306 | if (!view()->model() || !view()->selectionModel()) |
307 | return false; |
308 | QModelIndex index = view()->model()->index(row: 0, column, parent: view()->rootIndex()); |
309 | |
310 | if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectRows) |
311 | return false; |
312 | |
313 | switch (view()->selectionMode()) { |
314 | case QAbstractItemView::NoSelection: |
315 | return false; |
316 | case QAbstractItemView::SingleSelection: |
317 | if (view()->selectionBehavior() != QAbstractItemView::SelectColumns && rowCount() > 1) |
318 | return false; |
319 | Q_FALLTHROUGH(); |
320 | case QAbstractItemView::ContiguousSelection: |
321 | if ((!column || !view()->selectionModel()->isColumnSelected(column: column - 1, parent: view()->rootIndex())) |
322 | && !view()->selectionModel()->isColumnSelected(column: column + 1, parent: view()->rootIndex())) |
323 | view()->clearSelection(); |
324 | break; |
325 | default: |
326 | break; |
327 | } |
328 | |
329 | view()->selectionModel()->select(index, command: QItemSelectionModel::Select | QItemSelectionModel::Columns); |
330 | return true; |
331 | } |
332 | |
333 | bool QAccessibleTable::unselectRow(int row) |
334 | { |
335 | if (!view()->model() || !view()->selectionModel()) |
336 | return false; |
337 | |
338 | QModelIndex index = view()->model()->index(row, column: 0, parent: view()->rootIndex()); |
339 | if (!index.isValid()) |
340 | return false; |
341 | |
342 | QItemSelection selection(index, index); |
343 | |
344 | switch (view()->selectionMode()) { |
345 | case QAbstractItemView::SingleSelection: |
346 | //In SingleSelection and ContiguousSelection once an item |
347 | //is selected, there's no way for the user to unselect all items |
348 | if (selectedRowCount() == 1) |
349 | return false; |
350 | break; |
351 | case QAbstractItemView::ContiguousSelection: |
352 | if (selectedRowCount() == 1) |
353 | return false; |
354 | |
355 | if ((!row || view()->selectionModel()->isRowSelected(row: row - 1, parent: view()->rootIndex())) |
356 | && view()->selectionModel()->isRowSelected(row: row + 1, parent: view()->rootIndex())) { |
357 | //If there are rows selected both up the current row and down the current rown, |
358 | //the ones which are down the current row will be deselected |
359 | selection = QItemSelection(index, view()->model()->index(row: rowCount() - 1, column: 0, parent: view()->rootIndex())); |
360 | } |
361 | default: |
362 | break; |
363 | } |
364 | |
365 | view()->selectionModel()->select(selection, command: QItemSelectionModel::Deselect | QItemSelectionModel::Rows); |
366 | return true; |
367 | } |
368 | |
369 | bool QAccessibleTable::unselectColumn(int column) |
370 | { |
371 | if (!view()->model() || !view()->selectionModel()) |
372 | return false; |
373 | |
374 | QModelIndex index = view()->model()->index(row: 0, column, parent: view()->rootIndex()); |
375 | if (!index.isValid()) |
376 | return false; |
377 | |
378 | QItemSelection selection(index, index); |
379 | |
380 | switch (view()->selectionMode()) { |
381 | case QAbstractItemView::SingleSelection: |
382 | //In SingleSelection and ContiguousSelection once an item |
383 | //is selected, there's no way for the user to unselect all items |
384 | if (selectedColumnCount() == 1) |
385 | return false; |
386 | break; |
387 | case QAbstractItemView::ContiguousSelection: |
388 | if (selectedColumnCount() == 1) |
389 | return false; |
390 | |
391 | if ((!column || view()->selectionModel()->isColumnSelected(column: column - 1, parent: view()->rootIndex())) |
392 | && view()->selectionModel()->isColumnSelected(column: column + 1, parent: view()->rootIndex())) { |
393 | //If there are columns selected both at the left of the current row and at the right |
394 | //of the current rown, the ones which are at the right will be deselected |
395 | selection = QItemSelection(index, view()->model()->index(row: 0, column: columnCount() - 1, parent: view()->rootIndex())); |
396 | } |
397 | default: |
398 | break; |
399 | } |
400 | |
401 | view()->selectionModel()->select(selection, command: QItemSelectionModel::Deselect | QItemSelectionModel::Columns); |
402 | return true; |
403 | } |
404 | |
405 | QAccessible::Role QAccessibleTable::role() const |
406 | { |
407 | return m_role; |
408 | } |
409 | |
410 | QAccessible::State QAccessibleTable::state() const |
411 | { |
412 | return QAccessible::State(); |
413 | } |
414 | |
415 | QAccessibleInterface *QAccessibleTable::childAt(int x, int y) const |
416 | { |
417 | QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0)); |
418 | QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset); |
419 | // FIXME: if indexPosition < 0 in one coordinate, return header |
420 | |
421 | QModelIndex index = view()->indexAt(point: indexPosition); |
422 | if (index.isValid()) { |
423 | return child(index: logicalIndex(index)); |
424 | } |
425 | return nullptr; |
426 | } |
427 | |
428 | int QAccessibleTable::childCount() const |
429 | { |
430 | if (!view()->model()) |
431 | return 0; |
432 | int = verticalHeader() ? 1 : 0; |
433 | int = horizontalHeader() ? 1 : 0; |
434 | return (view()->model()->rowCount()+hHeader) * (view()->model()->columnCount()+vHeader); |
435 | } |
436 | |
437 | int QAccessibleTable::indexOfChild(const QAccessibleInterface *iface) const |
438 | { |
439 | if (!view()->model()) |
440 | return -1; |
441 | QAccessibleInterface *parent = iface->parent(); |
442 | if (parent->object() != view()) |
443 | return -1; |
444 | |
445 | Q_ASSERT(iface->role() != QAccessible::TreeItem); // should be handled by tree class |
446 | if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) { |
447 | const QAccessibleTableCell* cell = static_cast<const QAccessibleTableCell*>(iface); |
448 | return logicalIndex(index: cell->m_index); |
449 | } else if (iface->role() == QAccessible::ColumnHeader){ |
450 | const QAccessibleTableHeaderCell* cell = static_cast<const QAccessibleTableHeaderCell*>(iface); |
451 | return cell->index + (verticalHeader() ? 1 : 0); |
452 | } else if (iface->role() == QAccessible::RowHeader){ |
453 | const QAccessibleTableHeaderCell* cell = static_cast<const QAccessibleTableHeaderCell*>(iface); |
454 | return (cell->index + 1) * (view()->model()->columnCount() + 1); |
455 | } else if (iface->role() == QAccessible::Pane) { |
456 | return 0; // corner button |
457 | } else { |
458 | qWarning() << "WARNING QAccessibleTable::indexOfChild Fix my children..." |
459 | << iface->role() << iface->text(t: QAccessible::Name); |
460 | } |
461 | // FIXME: we are in denial of our children. this should stop. |
462 | return -1; |
463 | } |
464 | |
465 | QString QAccessibleTable::text(QAccessible::Text t) const |
466 | { |
467 | if (t == QAccessible::Description) |
468 | return view()->accessibleDescription(); |
469 | return view()->accessibleName(); |
470 | } |
471 | |
472 | QRect QAccessibleTable::rect() const |
473 | { |
474 | if (!view()->isVisible()) |
475 | return QRect(); |
476 | QPoint pos = view()->mapToGlobal(QPoint(0, 0)); |
477 | return QRect(pos.x(), pos.y(), view()->width(), view()->height()); |
478 | } |
479 | |
480 | QAccessibleInterface *QAccessibleTable::parent() const |
481 | { |
482 | if (view() && view()->parent()) { |
483 | if (qstrcmp(str1: "QComboBoxPrivateContainer" , str2: view()->parent()->metaObject()->className()) == 0) { |
484 | return QAccessible::queryAccessibleInterface(view()->parent()->parent()); |
485 | } |
486 | return QAccessible::queryAccessibleInterface(view()->parent()); |
487 | } |
488 | return nullptr; |
489 | } |
490 | |
491 | QAccessibleInterface *QAccessibleTable::child(int logicalIndex) const |
492 | { |
493 | if (!view()->model()) |
494 | return nullptr; |
495 | |
496 | auto id = childToId.constFind(akey: logicalIndex); |
497 | if (id != childToId.constEnd()) |
498 | return QAccessible::accessibleInterface(uniqueId: id.value()); |
499 | |
500 | int = verticalHeader() ? 1 : 0; |
501 | int = horizontalHeader() ? 1 : 0; |
502 | |
503 | int columns = view()->model()->columnCount() + vHeader; |
504 | |
505 | int row = logicalIndex / columns; |
506 | int column = logicalIndex % columns; |
507 | |
508 | QAccessibleInterface *iface = nullptr; |
509 | |
510 | if (vHeader) { |
511 | if (column == 0) { |
512 | if (hHeader && row == 0) { |
513 | iface = new QAccessibleTableCornerButton(view()); |
514 | } else { |
515 | iface = new QAccessibleTableHeaderCell(view(), row - hHeader, Qt::Vertical); |
516 | } |
517 | } |
518 | --column; |
519 | } |
520 | if (!iface && hHeader) { |
521 | if (row == 0) { |
522 | iface = new QAccessibleTableHeaderCell(view(), column, Qt::Horizontal); |
523 | } |
524 | --row; |
525 | } |
526 | |
527 | if (!iface) { |
528 | QModelIndex index = view()->model()->index(row, column, parent: view()->rootIndex()); |
529 | if (Q_UNLIKELY(!index.isValid())) { |
530 | qWarning(msg: "QAccessibleTable::child: Invalid index at: %d %d" , row, column); |
531 | return nullptr; |
532 | } |
533 | iface = new QAccessibleTableCell(view(), index, cellRole()); |
534 | } |
535 | |
536 | QAccessible::registerAccessibleInterface(iface); |
537 | childToId.insert(akey: logicalIndex, avalue: QAccessible::uniqueId(iface)); |
538 | return iface; |
539 | } |
540 | |
541 | void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t) |
542 | { |
543 | if (t == QAccessible::TableInterface) |
544 | return static_cast<QAccessibleTableInterface*>(this); |
545 | return nullptr; |
546 | } |
547 | |
548 | void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event) |
549 | { |
550 | // if there is no cache yet, we don't update anything |
551 | if (childToId.isEmpty()) |
552 | return; |
553 | |
554 | switch (event->modelChangeType()) { |
555 | case QAccessibleTableModelChangeEvent::ModelReset: |
556 | for (QAccessible::Id id : qAsConst(t&: childToId)) |
557 | QAccessible::deleteAccessibleInterface(uniqueId: id); |
558 | childToId.clear(); |
559 | break; |
560 | |
561 | // rows are inserted: move every row after that |
562 | case QAccessibleTableModelChangeEvent::RowsInserted: |
563 | case QAccessibleTableModelChangeEvent::ColumnsInserted: { |
564 | int newRows = event->lastRow() - event->firstRow() + 1; |
565 | int newColumns = event->lastColumn() - event->firstColumn() + 1; |
566 | |
567 | ChildCache newCache; |
568 | ChildCache::ConstIterator iter = childToId.constBegin(); |
569 | |
570 | while (iter != childToId.constEnd()) { |
571 | QAccessible::Id id = iter.value(); |
572 | QAccessibleInterface *iface = QAccessible::accessibleInterface(uniqueId: id); |
573 | Q_ASSERT(iface); |
574 | if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted |
575 | && iface->role() == QAccessible::RowHeader) { |
576 | QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface); |
577 | if (cell->index >= event->firstRow()) { |
578 | cell->index += newRows; |
579 | } |
580 | } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted |
581 | && iface->role() == QAccessible::ColumnHeader) { |
582 | QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface); |
583 | if (cell->index >= event->firstColumn()) { |
584 | cell->index += newColumns; |
585 | } |
586 | } |
587 | if (indexOfChild(iface) >= 0) { |
588 | newCache.insert(akey: indexOfChild(iface), avalue: id); |
589 | } else { |
590 | // ### This should really not happen, |
591 | // but it might if the view has a root index set. |
592 | // This needs to be fixed. |
593 | QAccessible::deleteAccessibleInterface(uniqueId: id); |
594 | } |
595 | ++iter; |
596 | } |
597 | childToId = newCache; |
598 | break; |
599 | } |
600 | |
601 | case QAccessibleTableModelChangeEvent::ColumnsRemoved: |
602 | case QAccessibleTableModelChangeEvent::RowsRemoved: { |
603 | int deletedColumns = event->lastColumn() - event->firstColumn() + 1; |
604 | int deletedRows = event->lastRow() - event->firstRow() + 1; |
605 | ChildCache newCache; |
606 | ChildCache::ConstIterator iter = childToId.constBegin(); |
607 | while (iter != childToId.constEnd()) { |
608 | QAccessible::Id id = iter.value(); |
609 | QAccessibleInterface *iface = QAccessible::accessibleInterface(uniqueId: id); |
610 | Q_ASSERT(iface); |
611 | if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) { |
612 | Q_ASSERT(iface->tableCellInterface()); |
613 | QAccessibleTableCell *cell = static_cast<QAccessibleTableCell*>(iface->tableCellInterface()); |
614 | // Since it is a QPersistentModelIndex, we only need to check if it is valid |
615 | if (cell->m_index.isValid()) |
616 | newCache.insert(akey: indexOfChild(iface: cell), avalue: id); |
617 | else |
618 | QAccessible::deleteAccessibleInterface(uniqueId: id); |
619 | } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved |
620 | && iface->role() == QAccessible::RowHeader) { |
621 | QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface); |
622 | if (cell->index < event->firstRow()) { |
623 | newCache.insert(akey: indexOfChild(iface: cell), avalue: id); |
624 | } else if (cell->index > event->lastRow()) { |
625 | cell->index -= deletedRows; |
626 | newCache.insert(akey: indexOfChild(iface: cell), avalue: id); |
627 | } else { |
628 | QAccessible::deleteAccessibleInterface(uniqueId: id); |
629 | } |
630 | } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved |
631 | && iface->role() == QAccessible::ColumnHeader) { |
632 | QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface); |
633 | if (cell->index < event->firstColumn()) { |
634 | newCache.insert(akey: indexOfChild(iface: cell), avalue: id); |
635 | } else if (cell->index > event->lastColumn()) { |
636 | cell->index -= deletedColumns; |
637 | newCache.insert(akey: indexOfChild(iface: cell), avalue: id); |
638 | } else { |
639 | QAccessible::deleteAccessibleInterface(uniqueId: id); |
640 | } |
641 | } |
642 | ++iter; |
643 | } |
644 | childToId = newCache; |
645 | break; |
646 | } |
647 | |
648 | case QAccessibleTableModelChangeEvent::DataChanged: |
649 | // nothing to do in this case |
650 | break; |
651 | } |
652 | } |
653 | |
654 | #if QT_CONFIG(treeview) |
655 | |
656 | // TREE VIEW |
657 | |
658 | QModelIndex QAccessibleTree::indexFromLogical(int row, int column) const |
659 | { |
660 | if (!isValid() || !view()->model()) |
661 | return QModelIndex(); |
662 | |
663 | const QTreeView *treeView = qobject_cast<const QTreeView*>(object: view()); |
664 | if (Q_UNLIKELY(row < 0 || column < 0 || treeView->d_func()->viewItems.count() <= row)) { |
665 | qWarning() << "QAccessibleTree::indexFromLogical: invalid index: " << row << column << " for " << treeView; |
666 | return QModelIndex(); |
667 | } |
668 | QModelIndex modelIndex = treeView->d_func()->viewItems.at(i: row).index; |
669 | |
670 | if (modelIndex.isValid() && column > 0) { |
671 | modelIndex = view()->model()->index(row: modelIndex.row(), column, parent: modelIndex.parent()); |
672 | } |
673 | return modelIndex; |
674 | } |
675 | |
676 | QAccessibleInterface *QAccessibleTree::childAt(int x, int y) const |
677 | { |
678 | if (!view()->model()) |
679 | return nullptr; |
680 | QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0)); |
681 | QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset); |
682 | |
683 | QModelIndex index = view()->indexAt(point: indexPosition); |
684 | if (!index.isValid()) |
685 | return nullptr; |
686 | |
687 | const QTreeView *treeView = qobject_cast<const QTreeView*>(object: view()); |
688 | int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0); |
689 | int column = index.column(); |
690 | |
691 | int i = row * view()->model()->columnCount() + column; |
692 | return child(index: i); |
693 | } |
694 | |
695 | int QAccessibleTree::childCount() const |
696 | { |
697 | const QTreeView *treeView = qobject_cast<const QTreeView*>(object: view()); |
698 | Q_ASSERT(treeView); |
699 | if (!view()->model()) |
700 | return 0; |
701 | |
702 | int = horizontalHeader() ? 1 : 0; |
703 | return (treeView->d_func()->viewItems.count() + hHeader)* view()->model()->columnCount(); |
704 | } |
705 | |
706 | QAccessibleInterface *QAccessibleTree::child(int logicalIndex) const |
707 | { |
708 | if (logicalIndex < 0 || !view()->model() || !view()->model()->columnCount()) |
709 | return nullptr; |
710 | |
711 | QAccessibleInterface *iface = nullptr; |
712 | int index = logicalIndex; |
713 | |
714 | if (horizontalHeader()) { |
715 | if (index < view()->model()->columnCount()) { |
716 | iface = new QAccessibleTableHeaderCell(view(), index, Qt::Horizontal); |
717 | } else { |
718 | index -= view()->model()->columnCount(); |
719 | } |
720 | } |
721 | |
722 | if (!iface) { |
723 | int row = index / view()->model()->columnCount(); |
724 | int column = index % view()->model()->columnCount(); |
725 | QModelIndex modelIndex = indexFromLogical(row, column); |
726 | if (!modelIndex.isValid()) |
727 | return nullptr; |
728 | iface = new QAccessibleTableCell(view(), modelIndex, cellRole()); |
729 | } |
730 | QAccessible::registerAccessibleInterface(iface); |
731 | // ### FIXME: get interfaces from the cache instead of re-creating them |
732 | return iface; |
733 | } |
734 | |
735 | int QAccessibleTree::rowCount() const |
736 | { |
737 | const QTreeView *treeView = qobject_cast<const QTreeView*>(object: view()); |
738 | Q_ASSERT(treeView); |
739 | return treeView->d_func()->viewItems.count(); |
740 | } |
741 | |
742 | int QAccessibleTree::indexOfChild(const QAccessibleInterface *iface) const |
743 | { |
744 | if (!view()->model()) |
745 | return -1; |
746 | QAccessibleInterface *parent = iface->parent(); |
747 | if (parent->object() != view()) |
748 | return -1; |
749 | |
750 | if (iface->role() == QAccessible::TreeItem) { |
751 | const QAccessibleTableCell* cell = static_cast<const QAccessibleTableCell*>(iface); |
752 | const QTreeView *treeView = qobject_cast<const QTreeView*>(object: view()); |
753 | Q_ASSERT(treeView); |
754 | int row = treeView->d_func()->viewIndex(index: cell->m_index) + (horizontalHeader() ? 1 : 0); |
755 | int column = cell->m_index.column(); |
756 | |
757 | int index = row * view()->model()->columnCount() + column; |
758 | return index; |
759 | } else if (iface->role() == QAccessible::ColumnHeader){ |
760 | const QAccessibleTableHeaderCell* cell = static_cast<const QAccessibleTableHeaderCell*>(iface); |
761 | return cell->index; |
762 | } else { |
763 | qWarning() << "WARNING QAccessibleTable::indexOfChild invalid child" |
764 | << iface->role() << iface->text(t: QAccessible::Name); |
765 | } |
766 | // FIXME: add scrollbars and don't just ignore them |
767 | return -1; |
768 | } |
769 | |
770 | QAccessibleInterface *QAccessibleTree::cellAt(int row, int column) const |
771 | { |
772 | QModelIndex index = indexFromLogical(row, column); |
773 | if (Q_UNLIKELY(!index.isValid())) { |
774 | qWarning(msg: "Requested invalid tree cell: %d %d" , row, column); |
775 | return nullptr; |
776 | } |
777 | const QTreeView *treeView = qobject_cast<const QTreeView*>(object: view()); |
778 | Q_ASSERT(treeView); |
779 | int logicalIndex = treeView->d_func()->accessibleTable2Index(index); |
780 | |
781 | return child(logicalIndex); // FIXME ### new QAccessibleTableCell(view(), index, cellRole()); |
782 | } |
783 | |
784 | QString QAccessibleTree::rowDescription(int) const |
785 | { |
786 | return QString(); // no headers for rows in trees |
787 | } |
788 | |
789 | bool QAccessibleTree::isRowSelected(int row) const |
790 | { |
791 | if (!view()->selectionModel()) |
792 | return false; |
793 | QModelIndex index = indexFromLogical(row); |
794 | return view()->selectionModel()->isRowSelected(row: index.row(), parent: index.parent()); |
795 | } |
796 | |
797 | bool QAccessibleTree::selectRow(int row) |
798 | { |
799 | if (!view()->selectionModel()) |
800 | return false; |
801 | QModelIndex index = indexFromLogical(row); |
802 | |
803 | if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns) |
804 | return false; |
805 | |
806 | switch (view()->selectionMode()) { |
807 | case QAbstractItemView::NoSelection: |
808 | return false; |
809 | case QAbstractItemView::SingleSelection: |
810 | if ((view()->selectionBehavior() != QAbstractItemView::SelectRows) && (columnCount() > 1)) |
811 | return false; |
812 | view()->clearSelection(); |
813 | break; |
814 | case QAbstractItemView::ContiguousSelection: |
815 | if ((!row || !view()->selectionModel()->isRowSelected(row: row - 1, parent: view()->rootIndex())) |
816 | && !view()->selectionModel()->isRowSelected(row: row + 1, parent: view()->rootIndex())) |
817 | view()->clearSelection(); |
818 | break; |
819 | default: |
820 | break; |
821 | } |
822 | |
823 | view()->selectionModel()->select(index, command: QItemSelectionModel::Select | QItemSelectionModel::Rows); |
824 | return true; |
825 | } |
826 | |
827 | #endif // QT_CONFIG(treeview) |
828 | |
829 | // TABLE CELL |
830 | |
831 | QAccessibleTableCell::QAccessibleTableCell(QAbstractItemView *view_, const QModelIndex &index_, QAccessible::Role role_) |
832 | : /* QAccessibleSimpleEditableTextInterface(this), */ view(view_), m_index(index_), m_role(role_) |
833 | { |
834 | if (Q_UNLIKELY(!index_.isValid())) |
835 | qWarning() << "QAccessibleTableCell::QAccessibleTableCell with invalid index: " << index_; |
836 | } |
837 | |
838 | void *QAccessibleTableCell::interface_cast(QAccessible::InterfaceType t) |
839 | { |
840 | if (t == QAccessible::TableCellInterface) |
841 | return static_cast<QAccessibleTableCellInterface*>(this); |
842 | if (t == QAccessible::ActionInterface) |
843 | return static_cast<QAccessibleActionInterface*>(this); |
844 | return nullptr; |
845 | } |
846 | |
847 | int QAccessibleTableCell::columnExtent() const { return 1; } |
848 | int QAccessibleTableCell::rowExtent() const { return 1; } |
849 | |
850 | QList<QAccessibleInterface*> QAccessibleTableCell::() const |
851 | { |
852 | QList<QAccessibleInterface*> ; |
853 | if (verticalHeader()) { |
854 | // FIXME |
855 | headerCell.append(t: new QAccessibleTableHeaderCell(view, m_index.row(), Qt::Vertical)); |
856 | } |
857 | return headerCell; |
858 | } |
859 | |
860 | QList<QAccessibleInterface*> QAccessibleTableCell::columnHeaderCells() const |
861 | { |
862 | QList<QAccessibleInterface*> ; |
863 | if (horizontalHeader()) { |
864 | // FIXME |
865 | headerCell.append(t: new QAccessibleTableHeaderCell(view, m_index.column(), Qt::Horizontal)); |
866 | } |
867 | return headerCell; |
868 | } |
869 | |
870 | QHeaderView *QAccessibleTableCell::() const |
871 | { |
872 | QHeaderView * = nullptr; |
873 | |
874 | if (false) { |
875 | #if QT_CONFIG(tableview) |
876 | } else if (const QTableView *tv = qobject_cast<const QTableView*>(object: view)) { |
877 | header = tv->horizontalHeader(); |
878 | #endif |
879 | #if QT_CONFIG(treeview) |
880 | } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(object: view)) { |
881 | header = tv->header(); |
882 | #endif |
883 | } |
884 | |
885 | return header; |
886 | } |
887 | |
888 | QHeaderView *QAccessibleTableCell::() const |
889 | { |
890 | QHeaderView * = nullptr; |
891 | #if QT_CONFIG(tableview) |
892 | if (const QTableView *tv = qobject_cast<const QTableView*>(object: view)) |
893 | header = tv->verticalHeader(); |
894 | #endif |
895 | return header; |
896 | } |
897 | |
898 | int QAccessibleTableCell::columnIndex() const |
899 | { |
900 | if (!isValid()) |
901 | return -1; |
902 | return m_index.column(); |
903 | } |
904 | |
905 | int QAccessibleTableCell::rowIndex() const |
906 | { |
907 | if (!isValid()) |
908 | return -1; |
909 | #if QT_CONFIG(treeview) |
910 | if (role() == QAccessible::TreeItem) { |
911 | const QTreeView *treeView = qobject_cast<const QTreeView*>(object: view); |
912 | Q_ASSERT(treeView); |
913 | int row = treeView->d_func()->viewIndex(index: m_index); |
914 | return row; |
915 | } |
916 | #endif |
917 | return m_index.row(); |
918 | } |
919 | |
920 | bool QAccessibleTableCell::isSelected() const |
921 | { |
922 | if (!isValid()) |
923 | return false; |
924 | return view->selectionModel()->isSelected(index: m_index); |
925 | } |
926 | |
927 | QStringList QAccessibleTableCell::actionNames() const |
928 | { |
929 | QStringList names; |
930 | names << toggleAction(); |
931 | return names; |
932 | } |
933 | |
934 | void QAccessibleTableCell::doAction(const QString& actionName) |
935 | { |
936 | if (actionName == toggleAction()) { |
937 | #if defined(Q_OS_ANDROID) |
938 | QAccessibleInterface *parentInterface = parent(); |
939 | while (parentInterface){ |
940 | if (parentInterface->role() == QAccessible::ComboBox) { |
941 | selectCell(); |
942 | parentInterface->actionInterface()->doAction(pressAction()); |
943 | return; |
944 | } else { |
945 | parentInterface = parentInterface->parent(); |
946 | } |
947 | } |
948 | #endif |
949 | if (isSelected()) { |
950 | unselectCell(); |
951 | } else { |
952 | selectCell(); |
953 | } |
954 | } |
955 | } |
956 | |
957 | QStringList QAccessibleTableCell::keyBindingsForAction(const QString &) const |
958 | { |
959 | return QStringList(); |
960 | } |
961 | |
962 | |
963 | void QAccessibleTableCell::selectCell() |
964 | { |
965 | if (!isValid()) |
966 | return; |
967 | QAbstractItemView::SelectionMode selectionMode = view->selectionMode(); |
968 | if (selectionMode == QAbstractItemView::NoSelection) |
969 | return; |
970 | Q_ASSERT(table()); |
971 | QAccessibleTableInterface *cellTable = table()->tableInterface(); |
972 | |
973 | switch (view->selectionBehavior()) { |
974 | case QAbstractItemView::SelectItems: |
975 | break; |
976 | case QAbstractItemView::SelectColumns: |
977 | if (cellTable) |
978 | cellTable->selectColumn(column: m_index.column()); |
979 | return; |
980 | case QAbstractItemView::SelectRows: |
981 | if (cellTable) |
982 | cellTable->selectRow(row: m_index.row()); |
983 | return; |
984 | } |
985 | |
986 | if (selectionMode == QAbstractItemView::SingleSelection) { |
987 | view->clearSelection(); |
988 | } |
989 | |
990 | view->selectionModel()->select(index: m_index, command: QItemSelectionModel::Select); |
991 | } |
992 | |
993 | void QAccessibleTableCell::unselectCell() |
994 | { |
995 | if (!isValid()) |
996 | return; |
997 | QAbstractItemView::SelectionMode selectionMode = view->selectionMode(); |
998 | if (selectionMode == QAbstractItemView::NoSelection) |
999 | return; |
1000 | |
1001 | QAccessibleTableInterface *cellTable = table()->tableInterface(); |
1002 | |
1003 | switch (view->selectionBehavior()) { |
1004 | case QAbstractItemView::SelectItems: |
1005 | break; |
1006 | case QAbstractItemView::SelectColumns: |
1007 | if (cellTable) |
1008 | cellTable->unselectColumn(column: m_index.column()); |
1009 | return; |
1010 | case QAbstractItemView::SelectRows: |
1011 | if (cellTable) |
1012 | cellTable->unselectRow(row: m_index.row()); |
1013 | return; |
1014 | } |
1015 | |
1016 | //If the mode is not MultiSelection or ExtendedSelection and only |
1017 | //one cell is selected it cannot be unselected by the user |
1018 | if ((selectionMode != QAbstractItemView::MultiSelection) |
1019 | && (selectionMode != QAbstractItemView::ExtendedSelection) |
1020 | && (view->selectionModel()->selectedIndexes().count() <= 1)) |
1021 | return; |
1022 | |
1023 | view->selectionModel()->select(index: m_index, command: QItemSelectionModel::Deselect); |
1024 | } |
1025 | |
1026 | QAccessibleInterface *QAccessibleTableCell::table() const |
1027 | { |
1028 | return QAccessible::queryAccessibleInterface(view); |
1029 | } |
1030 | |
1031 | QAccessible::Role QAccessibleTableCell::role() const |
1032 | { |
1033 | return m_role; |
1034 | } |
1035 | |
1036 | QAccessible::State QAccessibleTableCell::state() const |
1037 | { |
1038 | QAccessible::State st; |
1039 | if (!isValid()) |
1040 | return st; |
1041 | |
1042 | QRect globalRect = view->rect(); |
1043 | globalRect.translate(p: view->mapToGlobal(QPoint(0,0))); |
1044 | if (!globalRect.intersects(r: rect())) |
1045 | st.invisible = true; |
1046 | |
1047 | if (view->selectionModel()->isSelected(index: m_index)) |
1048 | st.selected = true; |
1049 | if (view->selectionModel()->currentIndex() == m_index) |
1050 | st.focused = true; |
1051 | |
1052 | QVariant checkState = m_index.model()->data(index: m_index, role: Qt::CheckStateRole); |
1053 | if (checkState.toInt() == Qt::Checked) |
1054 | st.checked = true; |
1055 | |
1056 | Qt::ItemFlags flags = m_index.flags(); |
1057 | if ((flags & Qt::ItemIsUserCheckable) && checkState.isValid()) |
1058 | st.checkable = true; |
1059 | if (flags & Qt::ItemIsSelectable) { |
1060 | st.selectable = true; |
1061 | st.focusable = true; |
1062 | if (view->selectionMode() == QAbstractItemView::MultiSelection) |
1063 | st.multiSelectable = true; |
1064 | if (view->selectionMode() == QAbstractItemView::ExtendedSelection) |
1065 | st.extSelectable = true; |
1066 | } |
1067 | #if QT_CONFIG(treeview) |
1068 | if (m_role == QAccessible::TreeItem) { |
1069 | const QTreeView *treeView = qobject_cast<const QTreeView*>(object: view); |
1070 | if (treeView->model()->hasChildren(parent: m_index)) |
1071 | st.expandable = true; |
1072 | if (treeView->isExpanded(index: m_index)) |
1073 | st.expanded = true; |
1074 | } |
1075 | #endif |
1076 | return st; |
1077 | } |
1078 | |
1079 | |
1080 | QRect QAccessibleTableCell::rect() const |
1081 | { |
1082 | QRect r; |
1083 | if (!isValid()) |
1084 | return r; |
1085 | r = view->visualRect(index: m_index); |
1086 | |
1087 | if (!r.isNull()) { |
1088 | r.translate(p: view->viewport()->mapTo(view, QPoint(0,0))); |
1089 | r.translate(p: view->mapToGlobal(QPoint(0, 0))); |
1090 | } |
1091 | return r; |
1092 | } |
1093 | |
1094 | QString QAccessibleTableCell::text(QAccessible::Text t) const |
1095 | { |
1096 | QString value; |
1097 | if (!isValid()) |
1098 | return value; |
1099 | QAbstractItemModel *model = view->model(); |
1100 | switch (t) { |
1101 | case QAccessible::Name: |
1102 | value = model->data(index: m_index, role: Qt::AccessibleTextRole).toString(); |
1103 | if (value.isEmpty()) |
1104 | value = model->data(index: m_index, role: Qt::DisplayRole).toString(); |
1105 | break; |
1106 | case QAccessible::Description: |
1107 | value = model->data(index: m_index, role: Qt::AccessibleDescriptionRole).toString(); |
1108 | break; |
1109 | default: |
1110 | break; |
1111 | } |
1112 | return value; |
1113 | } |
1114 | |
1115 | void QAccessibleTableCell::setText(QAccessible::Text /*t*/, const QString &text) |
1116 | { |
1117 | if (!isValid() || !(m_index.flags() & Qt::ItemIsEditable)) |
1118 | return; |
1119 | view->model()->setData(index: m_index, value: text); |
1120 | } |
1121 | |
1122 | bool QAccessibleTableCell::isValid() const |
1123 | { |
1124 | return view && !qt_widget_private(widget: view)->data.in_destructor |
1125 | && view->model() && m_index.isValid(); |
1126 | } |
1127 | |
1128 | QAccessibleInterface *QAccessibleTableCell::parent() const |
1129 | { |
1130 | return QAccessible::queryAccessibleInterface(view); |
1131 | } |
1132 | |
1133 | QAccessibleInterface *QAccessibleTableCell::child(int) const |
1134 | { |
1135 | return nullptr; |
1136 | } |
1137 | |
1138 | QAccessibleTableHeaderCell::(QAbstractItemView *view_, int index_, Qt::Orientation orientation_) |
1139 | : view(view_), index(index_), orientation(orientation_) |
1140 | { |
1141 | Q_ASSERT(index_ >= 0); |
1142 | } |
1143 | |
1144 | QAccessible::Role QAccessibleTableHeaderCell::() const |
1145 | { |
1146 | if (orientation == Qt::Horizontal) |
1147 | return QAccessible::ColumnHeader; |
1148 | return QAccessible::RowHeader; |
1149 | } |
1150 | |
1151 | QAccessible::State QAccessibleTableHeaderCell::() const |
1152 | { |
1153 | QAccessible::State s; |
1154 | if (QHeaderView *h = headerView()) { |
1155 | s.invisible = !h->testAttribute(attribute: Qt::WA_WState_Visible); |
1156 | s.disabled = !h->isEnabled(); |
1157 | } |
1158 | return s; |
1159 | } |
1160 | |
1161 | QRect QAccessibleTableHeaderCell::() const |
1162 | { |
1163 | QHeaderView * = nullptr; |
1164 | if (false) { |
1165 | #if QT_CONFIG(tableview) |
1166 | } else if (const QTableView *tv = qobject_cast<const QTableView*>(object: view)) { |
1167 | if (orientation == Qt::Horizontal) { |
1168 | header = tv->horizontalHeader(); |
1169 | } else { |
1170 | header = tv->verticalHeader(); |
1171 | } |
1172 | #endif |
1173 | #if QT_CONFIG(treeview) |
1174 | } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(object: view)) { |
1175 | header = tv->header(); |
1176 | #endif |
1177 | } |
1178 | if (!header) |
1179 | return QRect(); |
1180 | QPoint zero = header->mapToGlobal(QPoint(0, 0)); |
1181 | int sectionSize = header->sectionSize(logicalIndex: index); |
1182 | int sectionPos = header->sectionPosition(logicalIndex: index); |
1183 | return orientation == Qt::Horizontal |
1184 | ? QRect(zero.x() + sectionPos, zero.y(), sectionSize, header->height()) |
1185 | : QRect(zero.x(), zero.y() + sectionPos, header->width(), sectionSize); |
1186 | } |
1187 | |
1188 | QString QAccessibleTableHeaderCell::(QAccessible::Text t) const |
1189 | { |
1190 | QAbstractItemModel *model = view->model(); |
1191 | QString value; |
1192 | switch (t) { |
1193 | case QAccessible::Name: |
1194 | value = model->headerData(section: index, orientation, role: Qt::AccessibleTextRole).toString(); |
1195 | if (value.isEmpty()) |
1196 | value = model->headerData(section: index, orientation, role: Qt::DisplayRole).toString(); |
1197 | break; |
1198 | case QAccessible::Description: |
1199 | value = model->headerData(section: index, orientation, role: Qt::AccessibleDescriptionRole).toString(); |
1200 | break; |
1201 | default: |
1202 | break; |
1203 | } |
1204 | return value; |
1205 | } |
1206 | |
1207 | void QAccessibleTableHeaderCell::(QAccessible::Text, const QString &) |
1208 | { |
1209 | return; |
1210 | } |
1211 | |
1212 | bool QAccessibleTableHeaderCell::() const |
1213 | { |
1214 | return view && !qt_widget_private(widget: view)->data.in_destructor |
1215 | && view->model() && (index >= 0) |
1216 | && ((orientation == Qt::Horizontal) ? (index < view->model()->columnCount()) : (index < view->model()->rowCount())); |
1217 | } |
1218 | |
1219 | QAccessibleInterface *QAccessibleTableHeaderCell::() const |
1220 | { |
1221 | return QAccessible::queryAccessibleInterface(view); |
1222 | } |
1223 | |
1224 | QAccessibleInterface *QAccessibleTableHeaderCell::(int) const |
1225 | { |
1226 | return nullptr; |
1227 | } |
1228 | |
1229 | QHeaderView *QAccessibleTableHeaderCell::() const |
1230 | { |
1231 | QHeaderView * = nullptr; |
1232 | if (false) { |
1233 | #if QT_CONFIG(tableview) |
1234 | } else if (const QTableView *tv = qobject_cast<const QTableView*>(object: view)) { |
1235 | if (orientation == Qt::Horizontal) { |
1236 | header = tv->horizontalHeader(); |
1237 | } else { |
1238 | header = tv->verticalHeader(); |
1239 | } |
1240 | #endif |
1241 | #if QT_CONFIG(treeview) |
1242 | } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(object: view)) { |
1243 | header = tv->header(); |
1244 | #endif |
1245 | } |
1246 | return header; |
1247 | } |
1248 | |
1249 | QT_END_NAMESPACE |
1250 | |
1251 | #endif // QT_NO_ACCESSIBILITY |
1252 | |