dataChange signal ignored by GridView
-
Hello,
I am trying to update the content of a GridView with the dataChange signal. I studied the problem discussed here:
https://forum.qt.io/topic/78406/how-to-update-qabstractitemmodel-view-when-a-data-is-updated
After a day trying to bring my implementation closer to the example above and vice versa I like to ask for some help.The little game I am writing occurs on a Battlefield.qml:
GridView { id: grid; anchors.fill: parent cellWidth: elementWidth cellHeight: elementHeight interactive: false model: BattlefieldModel { id: bfModel columns: base.columns; rows: base.rows wallImage: "/images/wall.png" stoneImage: "/images/stone.png" bombImage: "/images/bomb.png" explosionImage: "/images/explosion.png" rangeExtension: "/images/rangeExtension.png" pickupBomb: "/images/pickupBomb.gif" } delegate: Rectangle { width: grid.cellWidth ; height: grid.cellHeight ; color: "transparent"; AnimatedImage { id: image anchors.fill: parent } Component.onCompleted: { if( content ) image.source = content }}}
The BF is fed by a BattlefieldModel.cpp:
class BattlefieldModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY( int columns READ columns WRITE setColumns ) Q_PROPERTY( int rows READ rows WRITE setRows ) Q_PROPERTY( QString wallImage READ wallImage WRITE setWallImage ) .. more properties the same type public: enum Roles { content = Qt::UserRole, }; // Define the game raster NOTHING TO DO WITH Qt-MODEL int columns(); void setColumns( int columns ); int rows(); void setRows( int rows ); <<setters getters removed>> // QAbstractItemModel interface int rowCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole ) const; QHash<int, QByteArray> roleNames() const; public slots: void refresh( const QSet< LinearCoordinate > & indices ); private: class BattlefieldModelPrivate; BattlefieldModelPrivate * d; };
The implementation:
class BattlefieldModel::BattlefieldModelPrivate { public: BattlefieldModelPrivate( BattlefieldModel * q ) : q(q) {} void initialize() { int rasterSize = rows * columns; if( rasterSize == 0 ) return; q->beginInsertRows( QModelIndex(), 0, rasterSize ); BF_instance.setColumns( columns ); BF_instance.setRows( rows ); q->endInsertRows(); } QString wallImage, stoneImage, bombImage, explosionImage, rangeExtension; QString pickupBomb; BattlefieldModel * q; uint columns = 0, rows = 0; }; BattlefieldModel::BattlefieldModel() : d( new BattlefieldModelPrivate( this ) ) { connect( &BF_instance, SIGNAL(tilesChanged(QSet<LinearCoordinate>)), this, SLOT(refresh(QSet<LinearCoordinate>))); } BattlefieldModel::~BattlefieldModel() { delete d; } int BattlefieldModel::columns() { return BF_instance.columns(); } void BattlefieldModel::setColumns(int columns) { d->columns = columns; d->initialize(); } int BattlefieldModel::rows() { return BF_instance.rows(); } void BattlefieldModel::setRows(int rows) { d->rows = rows; d->initialize(); } void BattlefieldModel::refreshTile(LinearCoordinate lc) { BF_instance.getTile( 0 )->setType( Tile::bomb ); BF_instance.getTile( 3 )->setType( Tile::bomb ); QModelIndex a = index( 3 ); emit dataChanged( a, a ); } int BattlefieldModel::rowCount(const QModelIndex &parent) const { if(parent.isValid()) return 0; return BF_instance.rasterSize(); } QVariant BattlefieldModel::data(const QModelIndex &index, int ) const { qDebug() << "refreshing? " << index; Tile * tile = BF_instance.getTile( index.row() ); switch( tile->type() ) { case Tile::wall: return QVariant(d->wallImage); case Tile::stone: return QVariant(d->stoneImage); case Tile::bomb: return QVariant(d->bombImage); case Tile::explosion: return QVariant(d->explosionImage); case Tile::pickupRangeExtension: return QVariant(d->rangeExtension); case Tile::pickupBomb: return QVariant(d->pickupBomb); default: return QVariant(); } } QHash<int, QByteArray> BattlefieldModel::roleNames() const { QHash<int, QByteArray> roles; roles[ Roles::content ] = "content"; return roles; } void BattlefieldModel::refresh( const QSet< LinearCoordinate > & indices ) { BF_instance.getTile( 0 )->setType( Tile::bomb ); BF_instance.getTile( 3 )->setType( Tile::bomb ); QModelIndex a = index( 3 ); emit dataChanged( a, a ); }
BF_instance is singleton holding all data for the BF and used throughout the game.
If I use:
beginResetModel();
endResetModel();The BF gets updated, but that is to slow. Bf is registered, but I tried also setting it as context, didn't work. On the other hand, registering the Animal from the above link works flawless. Also switching from GridView to ListView did not work for my game, but did work in the link.
Help is much appreciated.
-
You need to create a binding to
content
instead of assigning the image source once on component completion.For example:
source: content
Or if the check is necessary (not sure why):
source: content ? content : "" // or alternatively // source: content || ""