mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-26 20:03:13 +00:00
1092 lines
32 KiB
C++
1092 lines
32 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
** Copyright (C) 2016-2021 Ivailo Monev
|
|
**
|
|
** This file is part of the plugins of the Katie Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** This file may be used under the terms of the GNU Lesser
|
|
** General Public License version 2.1 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** As a special exception, The Qt Company gives you certain additional
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 3.0 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU General Public License version 3.0 requirements will be
|
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "itemviews.h"
|
|
|
|
#include "qheaderview.h"
|
|
#include "qtableview.h"
|
|
#include "qlistview.h"
|
|
#include "qtreeview.h"
|
|
#include "qtreewidget_p.h"
|
|
#include "qaccessible2.h"
|
|
#include <QDebug>
|
|
|
|
#ifndef QT_NO_ACCESSIBILITY
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
|
|
|
|
#ifndef QT_NO_ITEMVIEWS
|
|
/*
|
|
Implementation of the IAccessible2 table2 interface. Much simpler than
|
|
the other table interfaces since there is only the main table and cells:
|
|
|
|
TABLE/LIST/TREE
|
|
|- HEADER CELL
|
|
|- CELL
|
|
|- CELL
|
|
...
|
|
*/
|
|
|
|
QAbstractItemView *QAccessibleTable2::view() const
|
|
{
|
|
return qobject_cast<QAbstractItemView*>(object());
|
|
}
|
|
|
|
int QAccessibleTable2::logicalIndex(const QModelIndex &index) const
|
|
{
|
|
if (!view()->model() || !index.isValid())
|
|
return -1;
|
|
int vHeader = verticalHeader() ? 1 : 0;
|
|
int hHeader = horizontalHeader() ? 1 : 0;
|
|
// row * number columns + column + 1 for one based counting
|
|
return (index.row() + hHeader)*(index.model()->columnCount() + vHeader) + (index.column() + vHeader) + 1;
|
|
}
|
|
|
|
QAccessibleInterface *QAccessibleTable2::childFromLogical(int logicalIndex) const
|
|
{
|
|
if (!view()->model())
|
|
return 0;
|
|
|
|
logicalIndex--; // one based counting ftw
|
|
int vHeader = verticalHeader() ? 1 : 0;
|
|
int hHeader = horizontalHeader() ? 1 : 0;
|
|
|
|
int columns = view()->model()->columnCount() + vHeader;
|
|
|
|
int row = logicalIndex / columns;
|
|
int column = logicalIndex % columns;
|
|
|
|
if (vHeader) {
|
|
if (column == 0) {
|
|
if (row == 0) {
|
|
return new QAccessibleTable2CornerButton(view());
|
|
}
|
|
return new QAccessibleTable2HeaderCell(view(), row-1, Qt::Vertical);
|
|
}
|
|
--column;
|
|
}
|
|
if (hHeader) {
|
|
if (row == 0) {
|
|
return new QAccessibleTable2HeaderCell(view(), column, Qt::Horizontal);
|
|
}
|
|
--row;
|
|
}
|
|
|
|
QModelIndex index = view()->model()->index(row, column, view()->rootIndex());
|
|
if (!index.isValid()) {
|
|
qWarning() << "QAccessibleTable2::childFromLogical: Invalid index at: " << row << column;
|
|
return 0;
|
|
}
|
|
return new QAccessibleTable2Cell(view(), index, cellRole());
|
|
}
|
|
|
|
QAccessibleTable2::QAccessibleTable2(QWidget *w)
|
|
: QAccessibleObject(w)
|
|
{
|
|
Q_ASSERT(view());
|
|
|
|
if (qobject_cast<const QTableView*>(view())) {
|
|
m_role = QAccessible::Table;
|
|
} else if (qobject_cast<const QTreeView*>(view())) {
|
|
m_role = QAccessible::Tree;
|
|
} else if (qobject_cast<const QListView*>(view())) {
|
|
m_role = QAccessible::List;
|
|
} else {
|
|
// is this our best guess?
|
|
m_role = QAccessible::Table;
|
|
}
|
|
}
|
|
|
|
QAccessibleTable2::~QAccessibleTable2()
|
|
{
|
|
}
|
|
|
|
QHeaderView *QAccessibleTable2::horizontalHeader() const
|
|
{
|
|
QHeaderView *header = 0;
|
|
if (false) {
|
|
#ifndef QT_NO_TABLEVIEW
|
|
} else if (const QTableView *tv = qobject_cast<const QTableView*>(view())) {
|
|
header = tv->horizontalHeader();
|
|
#endif
|
|
#ifndef QT_NO_TREEVIEW
|
|
} else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view())) {
|
|
header = tv->header();
|
|
#endif
|
|
}
|
|
return header;
|
|
}
|
|
|
|
QHeaderView *QAccessibleTable2::verticalHeader() const
|
|
{
|
|
QHeaderView *header = 0;
|
|
if (false) {
|
|
#ifndef QT_NO_TABLEVIEW
|
|
} else if (const QTableView *tv = qobject_cast<const QTableView*>(view())) {
|
|
header = tv->verticalHeader();
|
|
#endif
|
|
}
|
|
return header;
|
|
}
|
|
|
|
void QAccessibleTable2::modelReset()
|
|
{}
|
|
|
|
void QAccessibleTable2::rowsInserted(const QModelIndex &, int first, int last)
|
|
{
|
|
lastChange.firstRow = first;
|
|
lastChange.lastRow = last;
|
|
lastChange.firstColumn = 0;
|
|
lastChange.lastColumn = 0;
|
|
lastChange.type = QAccessible2::TableModelChangeInsert;
|
|
}
|
|
|
|
void QAccessibleTable2::rowsRemoved(const QModelIndex &, int first, int last)
|
|
{
|
|
lastChange.firstRow = first;
|
|
lastChange.lastRow = last;
|
|
lastChange.firstColumn = 0;
|
|
lastChange.lastColumn = 0;
|
|
lastChange.type = QAccessible2::TableModelChangeDelete;
|
|
}
|
|
|
|
void QAccessibleTable2::columnsInserted(const QModelIndex &, int first, int last)
|
|
{
|
|
lastChange.firstRow = 0;
|
|
lastChange.lastRow = 0;
|
|
lastChange.firstColumn = first;
|
|
lastChange.lastColumn = last;
|
|
lastChange.type = QAccessible2::TableModelChangeInsert;
|
|
}
|
|
|
|
void QAccessibleTable2::columnsRemoved(const QModelIndex &, int first, int last)
|
|
{
|
|
lastChange.firstRow = 0;
|
|
lastChange.lastRow = 0;
|
|
lastChange.firstColumn = first;
|
|
lastChange.lastColumn = last;
|
|
lastChange.type = QAccessible2::TableModelChangeDelete;
|
|
}
|
|
|
|
void QAccessibleTable2::rowsMoved( const QModelIndex &, int, int, const QModelIndex &, int)
|
|
{
|
|
lastChange.firstRow = 0;
|
|
lastChange.lastRow = 0;
|
|
lastChange.firstColumn = 0;
|
|
lastChange.lastColumn = 0;
|
|
lastChange.type = QAccessible2::TableModelChangeUpdate;
|
|
}
|
|
|
|
void QAccessibleTable2::columnsMoved( const QModelIndex &, int, int, const QModelIndex &, int)
|
|
{
|
|
lastChange.firstRow = 0;
|
|
lastChange.lastRow = 0;
|
|
lastChange.firstColumn = 0;
|
|
lastChange.lastColumn = 0;
|
|
lastChange.type = QAccessible2::TableModelChangeUpdate;
|
|
}
|
|
|
|
QAccessibleTable2Cell *QAccessibleTable2::cell(const QModelIndex &index) const
|
|
{
|
|
if (index.isValid())
|
|
return new QAccessibleTable2Cell(view(), index, cellRole());
|
|
return 0;
|
|
}
|
|
|
|
QAccessibleTable2CellInterface *QAccessibleTable2::cellAt(int row, int column) const
|
|
{
|
|
if (!view()->model())
|
|
return 0;
|
|
Q_ASSERT(role(0) != QAccessible::Tree);
|
|
QModelIndex index = view()->model()->index(row, column, view()->rootIndex());
|
|
//Q_ASSERT(index.isValid());
|
|
if (!index.isValid()) {
|
|
qWarning() << "QAccessibleTable2::cellAt: invalid index: " << index << " for " << view();
|
|
return 0;
|
|
}
|
|
return cell(index);
|
|
}
|
|
|
|
QAccessibleInterface *QAccessibleTable2::caption() const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
QString QAccessibleTable2::columnDescription(int column) const
|
|
{
|
|
if (!view()->model())
|
|
return QString();
|
|
return view()->model()->headerData(column, Qt::Horizontal).toString();
|
|
}
|
|
|
|
int QAccessibleTable2::columnCount() const
|
|
{
|
|
if (!view()->model())
|
|
return 0;
|
|
return view()->model()->columnCount();
|
|
}
|
|
|
|
int QAccessibleTable2::rowCount() const
|
|
{
|
|
if (!view()->model())
|
|
return 0;
|
|
return view()->model()->rowCount();
|
|
}
|
|
|
|
int QAccessibleTable2::selectedCellCount() const
|
|
{
|
|
if (!view()->selectionModel())
|
|
return 0;
|
|
return view()->selectionModel()->selectedIndexes().count();
|
|
}
|
|
|
|
int QAccessibleTable2::selectedColumnCount() const
|
|
{
|
|
if (!view()->selectionModel())
|
|
return 0;
|
|
return view()->selectionModel()->selectedColumns().count();
|
|
}
|
|
|
|
int QAccessibleTable2::selectedRowCount() const
|
|
{
|
|
if (!view()->selectionModel())
|
|
return 0;
|
|
return view()->selectionModel()->selectedRows().count();
|
|
}
|
|
|
|
QString QAccessibleTable2::rowDescription(int row) const
|
|
{
|
|
if (!view()->model())
|
|
return QString();
|
|
return view()->model()->headerData(row, Qt::Vertical).toString();
|
|
}
|
|
|
|
QList<QAccessibleTable2CellInterface*> QAccessibleTable2::selectedCells() const
|
|
{
|
|
QList<QAccessibleTable2CellInterface*> cells;
|
|
if (!view()->selectionModel())
|
|
return cells;
|
|
Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedIndexes()) {
|
|
cells.append(cell(index));
|
|
}
|
|
return cells;
|
|
}
|
|
|
|
QList<int> QAccessibleTable2::selectedColumns() const
|
|
{
|
|
QList<int> columns;
|
|
if (!view()->selectionModel())
|
|
return columns;
|
|
Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedColumns()) {
|
|
columns.append(index.column());
|
|
}
|
|
return columns;
|
|
}
|
|
|
|
QList<int> QAccessibleTable2::selectedRows() const
|
|
{
|
|
if (!view()->selectionModel())
|
|
return QList<int>();
|
|
QList<int> rows;
|
|
Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedRows()) {
|
|
rows.append(index.row());
|
|
}
|
|
return rows;
|
|
}
|
|
|
|
QAccessibleInterface *QAccessibleTable2::summary() const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
bool QAccessibleTable2::isColumnSelected(int column) const
|
|
{
|
|
if (!view()->selectionModel())
|
|
return false;
|
|
return view()->selectionModel()->isColumnSelected(column, QModelIndex());
|
|
}
|
|
|
|
bool QAccessibleTable2::isRowSelected(int row) const
|
|
{
|
|
if (!view()->selectionModel())
|
|
return false;
|
|
return view()->selectionModel()->isRowSelected(row, QModelIndex());
|
|
}
|
|
|
|
bool QAccessibleTable2::selectRow(int row)
|
|
{
|
|
if (!view()->model() || !view()->selectionModel())
|
|
return false;
|
|
QModelIndex index = view()->model()->index(row, 0, view()->rootIndex());
|
|
if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection)
|
|
return false;
|
|
view()->selectionModel()->select(index, QItemSelectionModel::Select);
|
|
return true;
|
|
}
|
|
|
|
bool QAccessibleTable2::selectColumn(int column)
|
|
{
|
|
if (!view()->model() || !view()->selectionModel())
|
|
return false;
|
|
QModelIndex index = view()->model()->index(0, column, view()->rootIndex());
|
|
if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection)
|
|
return false;
|
|
view()->selectionModel()->select(index, QItemSelectionModel::Select);
|
|
return true;
|
|
}
|
|
|
|
bool QAccessibleTable2::unselectRow(int row)
|
|
{
|
|
if (!view()->model() || !view()->selectionModel())
|
|
return false;
|
|
QModelIndex index = view()->model()->index(row, 0, view()->rootIndex());
|
|
if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection)
|
|
return false;
|
|
view()->selectionModel()->select(index, QItemSelectionModel::Deselect);
|
|
return true;
|
|
}
|
|
|
|
bool QAccessibleTable2::unselectColumn(int column)
|
|
{
|
|
if (!view()->model() || !view()->selectionModel())
|
|
return false;
|
|
QModelIndex index = view()->model()->index(0, column, view()->rootIndex());
|
|
if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection)
|
|
return false;
|
|
view()->selectionModel()->select(index, QItemSelectionModel::Columns | QItemSelectionModel::Deselect);
|
|
return true;
|
|
}
|
|
|
|
QAccessible2::TableModelChange QAccessibleTable2::modelChange() const
|
|
{
|
|
QAccessible2::TableModelChange change;
|
|
// FIXME
|
|
return change;
|
|
}
|
|
|
|
QAccessible::Role QAccessibleTable2::role(int child) const
|
|
{
|
|
Q_ASSERT(child >= 0);
|
|
if (child > 0)
|
|
return QAccessible::Cell;
|
|
return m_role;
|
|
}
|
|
|
|
QAccessible::State QAccessibleTable2::state(int child) const
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
return QAccessible::Normal;
|
|
}
|
|
|
|
int QAccessibleTable2::childAt(int x, int y) const
|
|
{
|
|
QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0));
|
|
QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset);
|
|
// FIXME: if indexPosition < 0 in one coordinate, return header
|
|
|
|
QModelIndex index = view()->indexAt(indexPosition);
|
|
if (index.isValid()) {
|
|
return logicalIndex(index);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int QAccessibleTable2::childCount() const
|
|
{
|
|
if (!view()->model())
|
|
return 0;
|
|
int vHeader = verticalHeader() ? 1 : 0;
|
|
int hHeader = horizontalHeader() ? 1 : 0;
|
|
return (view()->model()->rowCount()+hHeader) * (view()->model()->columnCount()+vHeader);
|
|
}
|
|
|
|
int QAccessibleTable2::indexOfChild(const QAccessibleInterface *iface) const
|
|
{
|
|
if (!view()->model())
|
|
return -1;
|
|
Q_ASSERT(iface->role(0) != QAccessible::TreeItem); // should be handled by tree class
|
|
if (iface->role(0) == QAccessible::Cell || iface->role(0) == QAccessible::ListItem) {
|
|
const QAccessibleTable2Cell* cell = static_cast<const QAccessibleTable2Cell*>(iface);
|
|
return logicalIndex(cell->m_index);
|
|
} else if (iface->role(0) == QAccessible::ColumnHeader){
|
|
const QAccessibleTable2HeaderCell* cell = static_cast<const QAccessibleTable2HeaderCell*>(iface);
|
|
return cell->index + (verticalHeader() ? 1 : 0) + 1;
|
|
} else if (iface->role(0) == QAccessible::RowHeader){
|
|
const QAccessibleTable2HeaderCell* cell = static_cast<const QAccessibleTable2HeaderCell*>(iface);
|
|
return (cell->index+1) * (view()->model()->columnCount()+1) + 1;
|
|
} else if (iface->role(0) == QAccessible::Pane) {
|
|
return 1; // corner button
|
|
} else {
|
|
qWarning() << "WARNING QAccessibleTable2::indexOfChild Fix my children..."
|
|
<< iface->role(0) << iface->text(QAccessible::Name, 0);
|
|
}
|
|
// FIXME: we are in denial of our children. this should stop.
|
|
return -1;
|
|
}
|
|
|
|
QString QAccessibleTable2::text(Text t, int child) const
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
if (t == QAccessible::Description)
|
|
return view()->accessibleDescription();
|
|
return view()->accessibleName();
|
|
}
|
|
|
|
QRect QAccessibleTable2::rect(int child) const
|
|
{
|
|
Q_ASSERT(!child);
|
|
if (!view()->isVisible())
|
|
return QRect();
|
|
QPoint pos = view()->mapToGlobal(QPoint(0, 0));
|
|
return QRect(pos.x(), pos.y(), view()->width(), view()->height());
|
|
}
|
|
|
|
int QAccessibleTable2::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const
|
|
{
|
|
*iface = 0;
|
|
if ((index < 0) || (!view()->model()))
|
|
return -1;
|
|
|
|
switch (relation) {
|
|
case Ancestor: {
|
|
if (index == 1 && view()->parent()) {
|
|
*iface = QAccessible::queryAccessibleInterface(view()->parent());
|
|
if (*iface)
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
case QAccessible::Child: {
|
|
Q_ASSERT(index > 0);
|
|
*iface = childFromLogical(index);
|
|
if (*iface) {
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
QAccessible::Relation QAccessibleTable2::relationTo(int, const QAccessibleInterface *, int) const
|
|
{
|
|
return QAccessible::Unrelated;
|
|
}
|
|
|
|
#ifndef QT_NO_ACTION
|
|
int QAccessibleTable2::userActionCount(int) const
|
|
{
|
|
return 0;
|
|
}
|
|
QString QAccessibleTable2::actionText(int, Text, int) const
|
|
{
|
|
return QString();
|
|
}
|
|
bool QAccessibleTable2::doAction(int, int, const QVariantList &)
|
|
{
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
|
|
// TREE VIEW
|
|
|
|
QModelIndex QAccessibleTree::indexFromLogical(int row, int column) const
|
|
{
|
|
if (!isValid() || !view()->model())
|
|
return QModelIndex();
|
|
|
|
const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
|
|
if (treeView->d_func()->viewItems.count() <= row) {
|
|
qWarning() << "QAccessibleTree::indexFromLogical: invalid index: " << row << column << " for " << treeView;
|
|
return QModelIndex();
|
|
}
|
|
QModelIndex modelIndex = treeView->d_func()->viewItems.at(row).index;
|
|
|
|
if (modelIndex.isValid() && column > 0) {
|
|
modelIndex = view()->model()->index(modelIndex.row(), column, modelIndex.parent());
|
|
}
|
|
return modelIndex;
|
|
}
|
|
|
|
int QAccessibleTree::childAt(int x, int y) const
|
|
{
|
|
QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0));
|
|
QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset);
|
|
|
|
QModelIndex index = view()->indexAt(indexPosition);
|
|
if (!index.isValid())
|
|
return -1;
|
|
|
|
const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
|
|
int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0);
|
|
int column = index.column();
|
|
|
|
int i = row * view()->model()->columnCount() + column + 1;
|
|
Q_ASSERT(i > view()->model()->columnCount());
|
|
return i;
|
|
}
|
|
|
|
int QAccessibleTree::childCount() const
|
|
{
|
|
const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
|
|
Q_ASSERT(treeView);
|
|
if (!view()->model())
|
|
return 0;
|
|
|
|
int hHeader = horizontalHeader() ? 1 : 0;
|
|
return (treeView->d_func()->viewItems.count() + hHeader)* view()->model()->columnCount();
|
|
}
|
|
|
|
int QAccessibleTree::rowCount() const
|
|
{
|
|
const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
|
|
Q_ASSERT(treeView);
|
|
return treeView->d_func()->viewItems.count();
|
|
}
|
|
|
|
int QAccessibleTree::indexOfChild(const QAccessibleInterface *iface) const
|
|
{
|
|
if (!view()->model())
|
|
return -1;
|
|
if (iface->role(0) == QAccessible::TreeItem) {
|
|
const QAccessibleTable2Cell* cell = static_cast<const QAccessibleTable2Cell*>(iface);
|
|
const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
|
|
Q_ASSERT(treeView);
|
|
int row = treeView->d_func()->viewIndex(cell->m_index) + (horizontalHeader() ? 1 : 0);
|
|
int column = cell->m_index.column();
|
|
|
|
int index = row * view()->model()->columnCount() + column + 1;
|
|
//qDebug() << "QAccessibleTree::indexOfChild r " << row << " c " << column << "index " << index;
|
|
Q_ASSERT(index > treeView->model()->columnCount());
|
|
return index;
|
|
} else if (iface->role(0) == QAccessible::ColumnHeader){
|
|
const QAccessibleTable2HeaderCell* cell = static_cast<const QAccessibleTable2HeaderCell*>(iface);
|
|
//qDebug() << "QAccessibleTree::indexOfChild header " << cell->index << "is: " << cell->index + 1;
|
|
return cell->index + 1;
|
|
} else {
|
|
qWarning() << "WARNING QAccessibleTable2::indexOfChild invalid child"
|
|
<< iface->role(0) << iface->text(QAccessible::Name, 0);
|
|
}
|
|
// FIXME: add scrollbars and don't just ignore them
|
|
return -1;
|
|
}
|
|
|
|
int QAccessibleTree::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const
|
|
{
|
|
*iface = 0;
|
|
if ((index < 0) || (!view()->model()))
|
|
return -1;
|
|
|
|
switch (relation) {
|
|
case QAccessible::Child: {
|
|
Q_ASSERT(index > 0);
|
|
--index;
|
|
int hHeader = horizontalHeader() ? 1 : 0;
|
|
|
|
if (hHeader) {
|
|
if (index < view()->model()->columnCount()) {
|
|
*iface = new QAccessibleTable2HeaderCell(view(), index, Qt::Horizontal);
|
|
return 0;
|
|
} else {
|
|
index -= view()->model()->columnCount();
|
|
}
|
|
}
|
|
|
|
int row = index / view()->model()->columnCount();
|
|
int column = index % view()->model()->columnCount();
|
|
QModelIndex modelIndex = indexFromLogical(row, column);
|
|
if (modelIndex.isValid()) {
|
|
*iface = cell(modelIndex);
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
// handle everything except child
|
|
return QAccessibleTable2::navigate(relation, index, iface);
|
|
}
|
|
|
|
QAccessible::Relation QAccessibleTree::relationTo(int, const QAccessibleInterface *, int) const
|
|
{
|
|
return QAccessible::Unrelated;
|
|
}
|
|
|
|
QAccessibleTable2CellInterface *QAccessibleTree::cellAt(int row, int column) const
|
|
{
|
|
QModelIndex index = indexFromLogical(row, column);
|
|
if (!index.isValid()) {
|
|
qWarning() << "Requested invalid tree cell: " << row << column;
|
|
return 0;
|
|
}
|
|
return new QAccessibleTable2Cell(view(), index, cellRole());
|
|
}
|
|
|
|
QString QAccessibleTree::rowDescription(int) const
|
|
{
|
|
return QString(); // no headers for rows in trees
|
|
}
|
|
|
|
bool QAccessibleTree::isRowSelected(int row) const
|
|
{
|
|
if (!view()->selectionModel())
|
|
return false;
|
|
QModelIndex index = indexFromLogical(row);
|
|
return view()->selectionModel()->isRowSelected(index.row(), index.parent());
|
|
}
|
|
|
|
bool QAccessibleTree::selectRow(int row)
|
|
{
|
|
if (!view()->selectionModel())
|
|
return false;
|
|
QModelIndex index = indexFromLogical(row);
|
|
if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection)
|
|
return false;
|
|
view()->selectionModel()->select(index, QItemSelectionModel::Select);
|
|
return true;
|
|
}
|
|
|
|
// TABLE CELL
|
|
|
|
QAccessibleTable2Cell::QAccessibleTable2Cell(QAbstractItemView *view_, const QModelIndex &index_, QAccessible::Role role_)
|
|
: /* QAccessibleSimpleEditableTextInterface(this), */ view(view_), m_index(index_), m_role(role_)
|
|
{
|
|
Q_ASSERT(index_.isValid());
|
|
}
|
|
|
|
int QAccessibleTable2Cell::columnExtent() const { return 1; }
|
|
int QAccessibleTable2Cell::rowExtent() const { return 1; }
|
|
|
|
QList<QAccessibleInterface*> QAccessibleTable2Cell::rowHeaderCells() const
|
|
{
|
|
QList<QAccessibleInterface*> headerCell;
|
|
if (verticalHeader()) {
|
|
headerCell.append(new QAccessibleTable2HeaderCell(view, m_index.row(), Qt::Vertical));
|
|
}
|
|
return headerCell;
|
|
}
|
|
|
|
QList<QAccessibleInterface*> QAccessibleTable2Cell::columnHeaderCells() const
|
|
{
|
|
QList<QAccessibleInterface*> headerCell;
|
|
if (horizontalHeader()) {
|
|
headerCell.append(new QAccessibleTable2HeaderCell(view, m_index.column(), Qt::Horizontal));
|
|
}
|
|
return headerCell;
|
|
}
|
|
|
|
QHeaderView *QAccessibleTable2Cell::horizontalHeader() const
|
|
{
|
|
QHeaderView *header = 0;
|
|
|
|
if (false) {
|
|
#ifndef QT_NO_TABLEVIEW
|
|
} else if (const QTableView *tv = qobject_cast<const QTableView*>(view)) {
|
|
header = tv->horizontalHeader();
|
|
#endif
|
|
#ifndef QT_NO_TREEVIEW
|
|
} else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view)) {
|
|
header = tv->header();
|
|
#endif
|
|
}
|
|
|
|
return header;
|
|
}
|
|
|
|
QHeaderView *QAccessibleTable2Cell::verticalHeader() const
|
|
{
|
|
QHeaderView *header = 0;
|
|
#ifndef QT_NO_TABLEVIEW
|
|
if (const QTableView *tv = qobject_cast<const QTableView*>(view))
|
|
header = tv->verticalHeader();
|
|
#endif
|
|
return header;
|
|
}
|
|
|
|
int QAccessibleTable2Cell::columnIndex() const
|
|
{
|
|
return m_index.column();
|
|
}
|
|
|
|
int QAccessibleTable2Cell::rowIndex() const
|
|
{
|
|
if (role(0) == QAccessible::TreeItem) {
|
|
const QTreeView *treeView = qobject_cast<const QTreeView*>(view);
|
|
Q_ASSERT(treeView);
|
|
int row = treeView->d_func()->viewIndex(m_index);
|
|
return row;
|
|
}
|
|
return m_index.row();
|
|
}
|
|
|
|
bool QAccessibleTable2Cell::isSelected() const
|
|
{
|
|
return view->selectionModel()->isSelected(m_index);
|
|
}
|
|
|
|
void QAccessibleTable2Cell::rowColumnExtents(int *row, int *column, int *rowExtents, int *columnExtents, bool *selected) const
|
|
{
|
|
*row = m_index.row();
|
|
*column = m_index.column();
|
|
*rowExtents = 1;
|
|
*columnExtents = 1;
|
|
*selected = isSelected();
|
|
}
|
|
|
|
QAccessibleTable2Interface* QAccessibleTable2Cell::table() const
|
|
{
|
|
return QAccessible::queryAccessibleInterface(view)->table2Interface();
|
|
}
|
|
|
|
QAccessible::Role QAccessibleTable2Cell::role(int child) const
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
return m_role;
|
|
}
|
|
|
|
QAccessible::State QAccessibleTable2Cell::state(int child) const
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
State st = Normal;
|
|
|
|
QRect globalRect = view->rect();
|
|
globalRect.translate(view->mapToGlobal(QPoint(0,0)));
|
|
if (!globalRect.intersects(rect(0)))
|
|
st |= Invisible;
|
|
|
|
if (view->selectionModel()->isSelected(m_index))
|
|
st |= Selected;
|
|
if (view->selectionModel()->currentIndex() == m_index)
|
|
st |= Focused;
|
|
if (m_index.model()->data(m_index, Qt::CheckStateRole).toInt() == Qt::Checked)
|
|
st |= Checked;
|
|
|
|
Qt::ItemFlags flags = m_index.flags();
|
|
if (flags & Qt::ItemIsSelectable) {
|
|
st |= Selectable;
|
|
st |= Focusable;
|
|
if (view->selectionMode() == QAbstractItemView::MultiSelection)
|
|
st |= MultiSelectable;
|
|
if (view->selectionMode() == QAbstractItemView::ExtendedSelection)
|
|
st |= ExtSelectable;
|
|
}
|
|
if (m_role == QAccessible::TreeItem) {
|
|
const QTreeView *treeView = qobject_cast<const QTreeView*>(view);
|
|
if (treeView->isExpanded(m_index))
|
|
st |= Expanded;
|
|
}
|
|
return st;
|
|
}
|
|
|
|
bool QAccessibleTable2Cell::isExpandable() const
|
|
{
|
|
return view->model()->hasChildren(m_index);
|
|
}
|
|
|
|
QRect QAccessibleTable2Cell::rect(int child) const
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
|
|
QRect r = view->visualRect(m_index);
|
|
|
|
if (!r.isNull()) {
|
|
r.translate(view->viewport()->mapTo(view, QPoint(0,0)));
|
|
r.translate(view->mapToGlobal(QPoint(0, 0)));
|
|
}
|
|
return r;
|
|
}
|
|
|
|
QString QAccessibleTable2Cell::text(Text t, int child) const
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
QAbstractItemModel *model = view->model();
|
|
QString value;
|
|
switch (t) {
|
|
case QAccessible::Value:
|
|
case QAccessible::Name:
|
|
value = model->data(m_index, Qt::AccessibleTextRole).toString();
|
|
if (value.isEmpty())
|
|
value = model->data(m_index, Qt::DisplayRole).toString();
|
|
break;
|
|
case QAccessible::Description:
|
|
value = model->data(m_index, Qt::AccessibleDescriptionRole).toString();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
void QAccessibleTable2Cell::setText(Text /*t*/, int child, const QString &text)
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
if (!(m_index.flags() & Qt::ItemIsEditable))
|
|
return;
|
|
view->model()->setData(m_index, text);
|
|
}
|
|
|
|
bool QAccessibleTable2Cell::isValid() const
|
|
{
|
|
return view && view->model() && m_index.isValid();
|
|
}
|
|
|
|
int QAccessibleTable2Cell::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const
|
|
{
|
|
if (relation == Ancestor && index == 1) {
|
|
if (m_role == QAccessible::TreeItem) {
|
|
*iface = new QAccessibleTree(view);
|
|
} else {
|
|
*iface = new QAccessibleTable2(view);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
*iface = 0;
|
|
if (!view)
|
|
return -1;
|
|
|
|
switch (relation) {
|
|
|
|
case Child: {
|
|
return -1;
|
|
}
|
|
case Sibling:
|
|
if (index > 0) {
|
|
QAccessibleInterface *parent = queryAccessibleInterface(view);
|
|
int ret = parent->navigate(QAccessible::Child, index, iface);
|
|
delete parent;
|
|
if (*iface)
|
|
return ret;
|
|
}
|
|
return -1;
|
|
|
|
// From table1 implementation:
|
|
// case Up:
|
|
// case Down:
|
|
// case Left:
|
|
// case Right: {
|
|
// // This is in the "not so nice" category. In order to find out which item
|
|
// // is geometrically around, we have to set the current index, navigate
|
|
// // and restore the index as well as the old selection
|
|
// view()->setUpdatesEnabled(false);
|
|
// const QModelIndex oldIdx = view()->currentIndex();
|
|
// QList<QModelIndex> kids = children();
|
|
// const QModelIndex currentIndex = index ? kids.at(index - 1) : QModelIndex(row);
|
|
// const QItemSelection oldSelection = view()->selectionModel()->selection();
|
|
// view()->setCurrentIndex(currentIndex);
|
|
// const QModelIndex idx = view()->moveCursor(toCursorAction(relation), Qt::NoModifier);
|
|
// view()->setCurrentIndex(oldIdx);
|
|
// view()->selectionModel()->select(oldSelection, QItemSelectionModel::ClearAndSelect);
|
|
// view()->setUpdatesEnabled(true);
|
|
// if (!idx.isValid())
|
|
// return -1;
|
|
|
|
// if (idx.parent() != row.parent() || idx.row() != row.row())
|
|
// *iface = cell(idx);
|
|
// return index ? kids.indexOf(idx) + 1 : 0; }
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
QAccessible::Relation QAccessibleTable2Cell::relationTo(int child, const QAccessibleInterface *other, int otherChild) const
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
Q_ASSERT(otherChild == 0);
|
|
// we only check for parent-child relationships in trees
|
|
if (m_role == QAccessible::TreeItem && other->role(0) == QAccessible::TreeItem) {
|
|
QModelIndex otherIndex = static_cast<const QAccessibleTable2Cell*>(other)->m_index;
|
|
// is the other our parent?
|
|
if (otherIndex.parent() == m_index)
|
|
return QAccessible::Ancestor;
|
|
// are we the other's child?
|
|
if (m_index.parent() == otherIndex)
|
|
return QAccessible::Child;
|
|
}
|
|
return QAccessible::Unrelated;
|
|
}
|
|
|
|
#ifndef QT_NO_ACTION
|
|
int QAccessibleTable2Cell::userActionCount(int) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
QString QAccessibleTable2Cell::actionText(int, Text, int) const
|
|
{
|
|
return QString();
|
|
}
|
|
|
|
bool QAccessibleTable2Cell::doAction(int, int, const QVariantList &)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
QAccessibleTable2HeaderCell::QAccessibleTable2HeaderCell(QAbstractItemView *view_, int index_, Qt::Orientation orientation_)
|
|
: view(view_), index(index_), orientation(orientation_)
|
|
{
|
|
Q_ASSERT(index_ >= 0);
|
|
}
|
|
|
|
QAccessible::Role QAccessibleTable2HeaderCell::role(int child) const
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
if (orientation == Qt::Horizontal)
|
|
return QAccessible::ColumnHeader;
|
|
return QAccessible::RowHeader;
|
|
}
|
|
|
|
QAccessible::State QAccessibleTable2HeaderCell::state(int child) const
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
return QAccessible::Normal;
|
|
}
|
|
|
|
QRect QAccessibleTable2HeaderCell::rect(int child) const
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
|
|
QHeaderView *header = 0;
|
|
if (false) {
|
|
#ifndef QT_NO_TABLEVIEW
|
|
} else if (const QTableView *tv = qobject_cast<const QTableView*>(view)) {
|
|
if (orientation == Qt::Horizontal) {
|
|
header = tv->horizontalHeader();
|
|
} else {
|
|
header = tv->verticalHeader();
|
|
}
|
|
#endif
|
|
#ifndef QT_NO_TREEVIEW
|
|
} else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view)) {
|
|
header = tv->header();
|
|
#endif
|
|
}
|
|
if (!header)
|
|
return QRect();
|
|
QPoint zero = header->mapToGlobal(QPoint(0, 0));
|
|
int sectionSize = header->sectionSize(index);
|
|
int sectionPos = header->sectionPosition(index);
|
|
return orientation == Qt::Horizontal
|
|
? QRect(zero.x() + sectionPos, zero.y(), sectionSize, header->height())
|
|
: QRect(zero.x(), zero.y() + sectionPos, header->width(), sectionSize);
|
|
}
|
|
|
|
QString QAccessibleTable2HeaderCell::text(Text t, int child) const
|
|
{
|
|
Q_ASSERT(child == 0);
|
|
QAbstractItemModel *model = view->model();
|
|
QString value;
|
|
switch (t) {
|
|
case QAccessible::Value:
|
|
case QAccessible::Name:
|
|
value = model->headerData(index, orientation, Qt::AccessibleTextRole).toString();
|
|
if (value.isEmpty())
|
|
value = model->headerData(index, orientation, Qt::DisplayRole).toString();
|
|
break;
|
|
case QAccessible::Description:
|
|
value = model->headerData(index, orientation, Qt::AccessibleDescriptionRole).toString();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
void QAccessibleTable2HeaderCell::setText(Text, int, const QString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool QAccessibleTable2HeaderCell::isValid() const
|
|
{
|
|
return view && view->model() && (index >= 0)
|
|
&& ((orientation == Qt::Horizontal) ? (index < view->model()->columnCount()) : (index < view->model()->rowCount()));
|
|
}
|
|
|
|
int QAccessibleTable2HeaderCell::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const
|
|
{
|
|
if (relation == QAccessible::Ancestor && index == 1) {
|
|
if (false) {
|
|
#ifndef QT_NO_TREEVIEW
|
|
} else if (qobject_cast<const QTreeView*>(view)) {
|
|
*iface = new QAccessibleTree(view);
|
|
return 0;
|
|
#endif
|
|
} else {
|
|
*iface = new QAccessibleTable2(view);
|
|
return 0;
|
|
}
|
|
}
|
|
*iface = 0;
|
|
return -1;
|
|
}
|
|
|
|
QAccessible::Relation QAccessibleTable2HeaderCell::relationTo(int, const QAccessibleInterface *, int) const
|
|
{
|
|
return QAccessible::Unrelated;
|
|
}
|
|
|
|
#ifndef QT_NO_ACTION
|
|
int QAccessibleTable2HeaderCell::userActionCount(int) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
QString QAccessibleTable2HeaderCell::actionText(int, Text, int) const
|
|
{
|
|
return QString();
|
|
}
|
|
|
|
bool QAccessibleTable2HeaderCell::doAction(int, int, const QVariantList &)
|
|
{
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif // QT_NO_ITEMVIEWS
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
#endif // QT_NO_ACCESSIBILITY
|