PDA

View Full Version : Delayed QAbstractItemModel population



BlackDemon
8th December 2009, 01:17
Right now I'm looking for a more efficient way to populate an Item Model. All the data my application loads is from external files to reduce memory usage since the file being read is a pointer indexed sprite database, I have reimplemented


QVariant QAbstractListModel::data( const QModelIndex &index, int role ) const

To retrieve the sprite from the database, the problem with this is that I have maybe 40,000 32x32 ARGB32 images (Storing this in memory is a very bad idea) so I used this reimplementation to read the sprites from the file directly by index location using the file loader class. This works, low memory usage, but the real problem is that scrolling for the first time in this gigantic 40k sprite list lags and freezes the UI for about 10 seconds because its loading every sprite in order (I'm also using QTreeView because QListView does not contain the Vista style while hovering over ModelIndexes)

What I want to do to solve this is "delay" the actual request of the DecorationRole and limit it to a small number of indexes in the viewport so I can scroll to the end of the list without it lagging for a good 10 seconds, and I could have it slowly populate the decoration (I believe Explorer does something similar with its thumbnails, shows the default icons and slowly loads the thumbnails that are in your current viewport)

Though if there are any alternative methods that would work better for reading and displaying a very large amount of images without consuming a lot of memory while maintaining speed, that would be really helpful.

This is my current reimplementation

resourceList - internal QList of "SharedResource" kept in the model itself.
g_resourceHandler - Global class that passes resources
Sprite - Class containing QImage and other basic required information, only intialized when read by the file handler
SpriteResource - Class containing reference information used to access proper files


typedef QSharedPointer<SpriteResource> SharedResource;


QVariant SpriteModel::data( const QModelIndex &index, int role ) const
{
if ( !index.isValid() )
return QVariant();

if( role == Qt::DecorationRole || role == Qt::DisplayRole || role == Qt::UserRole )
{
SharedResource resource = resourceList.value( index.row() );
if( role == Qt::DecorationRole )
{
Sprite sprite = g_resourceHandler.getSpriteByResource( resource );
if( sprite.image.height() > 128 || sprite.image.width() > 128 )
return QVariant( sprite.image.scaled( 128, 128, Qt::KeepAspectRatio ) );

return QVariant( sprite.image );
}
else if( role == Qt::DisplayRole )
{
if( resource.data() )
{
if( resource.data()->isPicture() )
return QVariant( resource.data()->getIdentifier() - PICTURE_OFFSET );

return QVariant( resource.data()->getIdentifier() );
}
}
else if( role == Qt::UserRole )
{
return QVariant::fromValue( resource );
}
}

return QVariant();
}