Is there any way to get a list of currently visible items in QAbstractItemView
? And, if it possible, to receive any notifications about changing of this list.
Upd:
I'm asking exactly about QAbstractItemView
or QTreeView
with non-plain structure, not QTableView
.
Upd2:
I'm implementing tree view model with checkboxes. I want next behavior (same for checking/uncheking):
- If one of checkbox is checked - then all childs must be checked
- If all child checkboxes are checked - then parent check box should be checked too. And same for parent of parent, and so on...
Check state are monitored/modified by external data source, so I need a mechanism to update all changed children/parents. dataChanged
signal is not enough for me because it is very expansive to build a list of all changed QModelIndex
for updating. And it is not necessary at all, because all fresh data will be picked from QAbstractItemModel::data
.
I found next dirty hack to update all items: emit dataChanged( QModelIndex(), QModelIndex() );
but it's undocumented for invalid indexes.
So, I need a way to force all visible items redraw they content with fresh data.
You can get the topleft and bottom right cell by calling:
tableview->indexAt(tableview->rect().topLeft())
tableview->indexAt(tableview->rect().bottomRight())
To get notification of change, reimplement the virtual function of qabstractscrollarea
scrollContentsBy
This function is called when the view port is scrolled.
call QTableView::scrollContentsBy and then do whatever you need to.
For QTreeView
, the list of visible items can be traversed like this:
QTreeView& tv (yourTreeView);
// Get model index for first visible item
QModelIndex modelIndex = tv.indexAt(tv.rect().topLeft());
while (modelIndex.isValid())
{
// do something with the item indexed by modelIndex
...
// This navigates to the next visible item
modelIndex = tv.indexBelow(modelIndex);
}
I think that there are no cases where list of visible items is requred. In case of correct model implementation all items are updated automatically.
Hard part of implementation - force children and parents to update. I wrote following code:
bool TreeModel::setData( const QModelIndex &index, const QVariant &value, int role )
case Qt::CheckStateRole:
{
TreeItemList updateRangeList; // Filled with items, in which all childred must be updated
TreeItemList updateSingleList; // Filled with items, which must be updated
item->setCheckState( value.toBool(), updateRangeList, updateSingleList ); // All magic there
foreach ( TreeAbstractItem *i, updateRangeList )
{
const int nRows = i->rowCount();
QModelIndex topLeft = indexForItem( i->m_childs[0] );
QModelIndex bottomRight = indexForItem( i->m_childs[nRows - 1] );
emit dataChanged( topLeft, bottomRight );
}
foreach ( TreeAbstractItem *i, updateSingleList )
{
QModelIndex updateIndex = indexForItem( i );
emit dataChanged( updateIndex, updateIndex );
}
}
i always update whole QAbstractTableModel with:
emit dataChanged(index(0, 0), index(rowCount(), columnCount()-1)); // update whole view