Use QPersistentModelIndex for storing a model index

QModelIndex is not safe to be used to store an index as it is designed
to be discarded right after use as the index information can change.

Therefore a QPersistentModelIndex should be used instead to store the
index. Subsequently the m_index does not need to be updated whenever
the model changes anymore as this is already done for us.

Task-number: QTBUG-49907
Change-Id: Icc93e410de2821c503ea15a7a1dd9ae32634914e
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
bb10
Andy Shaw 2016-10-21 17:14:31 +02:00
parent bebbaa43fd
commit bd591064be
3 changed files with 12 additions and 37 deletions

View File

@ -550,20 +550,8 @@ void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event)
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) {
if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted
&& iface->role() == QAccessible::RowHeader) {
QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
if (cell->index >= event->firstRow()) {
cell->index += newRows;
@ -602,27 +590,11 @@ void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event)
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);
}
}
// Since it is a QPersistentModelIndex, we only need to check if it is valid
if (cell->m_index.isValid())
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);

View File

@ -207,7 +207,7 @@ private:
QHeaderView *verticalHeader() const;
QHeaderView *horizontalHeader() const;
QPointer<QAbstractItemView > view;
QModelIndex m_index;
QPersistentModelIndex m_index;
QAccessible::Role m_role;
void selectCell();

View File

@ -2903,7 +2903,10 @@ void tst_QAccessibility::listTest()
QAccessibleInterface *cellMunich3 = table2->cellAt(2,0);
QCOMPARE(cell4, cellMunich3);
QCOMPARE(axidMunich, QAccessible::uniqueId(cellMunich3));
delete listView->takeItem(2);
// list: Oslo, Helsinki
// verify that it doesn't return an invalid item from the cache
QVERIFY(table2->cellAt(2,0) == 0);
delete listView;
}