Example #1
0
void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event)
{
    // if there is no cache yet, we don't update anything
    if (childToId.isEmpty())
        return;

    switch (event->modelChangeType()) {
    case QAccessibleTableModelChangeEvent::ModelReset:
        Q_FOREACH (QAccessible::Id id, childToId)
            QAccessible::deleteAccessibleInterface(id);
        childToId.clear();
        break;

    // rows are inserted: move every row after that
    case QAccessibleTableModelChangeEvent::RowsInserted:
    case QAccessibleTableModelChangeEvent::ColumnsInserted: {
        int newRows = event->lastRow() - event->firstRow() + 1;
        int newColumns = event->lastColumn() - event->firstColumn() + 1;

        ChildCache newCache;
        ChildCache::ConstIterator iter = childToId.constBegin();

        while (iter != childToId.constEnd()) {
            QAccessible::Id id = iter.value();
            QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
            Q_ASSERT(iface);
            if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
                Q_ASSERT(iface->tableCellInterface());
                QAccessibleTableCell *cell = static_cast<QAccessibleTableCell*>(iface->tableCellInterface());
                if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted
                        && cell->m_index.row() >= event->firstRow()) {
                    int newRow = cell->m_index.row() + newRows;
                    cell->m_index = cell->m_index.sibling(newRow, cell->m_index.column());
                } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted
                        && cell->m_index.column() >= event->firstColumn()) {
                    int newColumn = cell->m_index.column() + newColumns;
                    cell->m_index = cell->m_index.sibling(cell->m_index.row(), newColumn);
                }
            } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted
                       && iface->role() == QAccessible::RowHeader) {
                QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
                if (cell->index >= event->firstRow()) {
                    cell->index += newRows;
                }
            } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted
                   && iface->role() == QAccessible::ColumnHeader) {
                QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
                if (cell->index >= event->firstColumn()) {
                    cell->index += newColumns;
                }
            }
            if (indexOfChild(iface) >= 0) {
                newCache.insert(indexOfChild(iface), id);
            } else {
                // ### This should really not happen,
                // but it might if the view has a root index set.
                // This needs to be fixed.
                QAccessible::deleteAccessibleInterface(id);
            }
            ++iter;
        }
        childToId = newCache;
        break;
    }

    case QAccessibleTableModelChangeEvent::ColumnsRemoved:
    case QAccessibleTableModelChangeEvent::RowsRemoved: {
        int deletedColumns = event->lastColumn() - event->firstColumn() + 1;
        int deletedRows = event->lastRow() - event->firstRow() + 1;
        ChildCache newCache;
        ChildCache::ConstIterator iter = childToId.constBegin();
        while (iter != childToId.constEnd()) {
            QAccessible::Id id = iter.value();
            QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
            Q_ASSERT(iface);
            if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
                Q_ASSERT(iface->tableCellInterface());
                QAccessibleTableCell *cell = static_cast<QAccessibleTableCell*>(iface->tableCellInterface());
                if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved) {
                    if (cell->m_index.row() < event->firstRow()) {
                        newCache.insert(indexOfChild(cell), id);
                    } else if (cell->m_index.row() > event->lastRow()) {
                        int newRow = cell->m_index.row() - deletedRows;
                        cell->m_index = cell->m_index.sibling(newRow, cell->m_index.column());
                        newCache.insert(indexOfChild(cell), id);
                    } else {
                        QAccessible::deleteAccessibleInterface(id);
                    }
                } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved) {
                    if (cell->m_index.column() < event->firstColumn()) {
                        newCache.insert(indexOfChild(cell), id);
                    } else if (cell->m_index.column() > event->lastColumn()) {
                        int newColumn = cell->m_index.column() - deletedColumns;
                        cell->m_index = cell->m_index.sibling(cell->m_index.row(), newColumn);
                        newCache.insert(indexOfChild(cell), id);
                    } else {
                        QAccessible::deleteAccessibleInterface(id);
                    }
                }
            } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved
                       && iface->role() == QAccessible::RowHeader) {
                QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
                if (cell->index < event->firstRow()) {
                    newCache.insert(indexOfChild(cell), id);
                } else if (cell->index > event->lastRow()) {
                    cell->index -= deletedRows;
                    newCache.insert(indexOfChild(cell), id);
                } else {
                    QAccessible::deleteAccessibleInterface(id);
                }
            } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved
                   && iface->role() == QAccessible::ColumnHeader) {
                QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
                if (cell->index < event->firstColumn()) {
                    newCache.insert(indexOfChild(cell), id);
                } else if (cell->index > event->lastColumn()) {
                    cell->index -= deletedColumns;
                    newCache.insert(indexOfChild(cell), id);
                } else {
                    QAccessible::deleteAccessibleInterface(id);
                }
            }
            ++iter;
        }
        childToId = newCache;
        break;
    }

    case QAccessibleTableModelChangeEvent::DataChanged:
        // nothing to do in this case
        break;
    }
}