[Interest] QML ListView is not updated on model reset
Elvis Stansvik
elvstone at gmail.com
Mon Feb 27 19:11:25 CET 2017
2017-02-27 19:04 GMT+01:00 Alexander Dyagilev <alervdvcw at gmail.com>:
> I have another ListView wich uses C++ model derived from another class -
> QSqlQueryModel.
>
> The same things happens: model is not updated and existing items gets
> damaged. E.g. model.id for an item was 2 and became 0 after a new item has
> been added (all existing item's model.id becomes 0).
>
> Something very wrong is happening. Look like I misunderstand something...
This is just a wild guess, but could it be because you're using "id"
for your role name, which is special in the QML world? Not sure how
QML plays with that..
Elvis
>
>
> On 2/27/2017 8:59 PM, Alexander Dyagilev wrote:
>
> Hello,
>
> I've created a question on SO but nobody answered still...
> (http://stackoverflow.com/questions/42468811/qml-listview-is-not-updated-on-model-reset)
>
> Qt 5.8, Windows 10.
>
> Quick Controls 2 application. In QML I have a ListView with a model derived
> from QAbstractListModel.
>
> In the model I have the following code:
>
> void MediaPlaylistModel::update()
> {
> beginResetModel();
> {
> std::unique_lock<std::mutex> lock(m_mutex);
> m_ids = m_playlist->itemsIds();
> }
> endResetModel();
> }
>
> Nothing happens in QML view after calling this method: list is not updated.
> If I go back and then forward (to the page with the ListView) - it'll
> contain updated data. Model object instance is the same always.
>
> Am I doing something wrong?
>
> Update #2:
>
> C++ model code:
>
> MediaPlaylistModel::MediaPlaylistModel(
> QSharedPointer<AbstractMediaPlaylist> playlist,
> QObject *parent) :
> base_t(parent),
> m_playlist(playlist)
> {
> Q_ASSERT(m_playlist);
>
> connect(playlist.data(), &AbstractMediaPlaylist::changed,
> this, &MediaPlaylistModel::update);
>
> update();
> }
>
> QHash<int, QByteArray> MediaPlaylistModel::roleNames() const
> {
> QHash<int, QByteArray> result;
> result[IdRole] = "id";
> result[TitleRole] = "title";
> result[DurationRole] = "duration";
> return result;
> }
>
> void MediaPlaylistModel::update()
> {
> Q_ASSERT_SAME_THREAD;
> beginResetModel();
> {
> std::unique_lock<std::mutex> lock(m_mutex);
> m_ids = m_playlist->itemsIds();
> }
> endResetModel();
> }
>
> int MediaPlaylistModel::rowCount(
> const QModelIndex &parent) const
> {
> Q_UNUSED(parent);
> std::unique_lock<std::mutex> lock(m_mutex);
> return static_cast<int>(m_ids.size());
> }
>
> QVariant MediaPlaylistModel::data(
> const QModelIndex &index,
> int role) const
> {
> auto row = static_cast<size_t>(index.row());
> int id = 0;
>
> {
> std::unique_lock<std::mutex> lock(m_mutex);
> if (row >= m_ids.size())
> return QVariant();
> id = m_ids[row];
> }
>
> if (role == IdRole)
> return id;
>
> QVariant result;
>
> auto item = m_playlist->item(id);
>
> switch(role)
> {
> case Qt::DisplayRole:
> case TitleRole:
> result = item.title;
> break;
> case DurationRole:
> result = item.duration;
> break;
> }
>
> return result;
> }
>
> QML code:
>
> import QtQuick 2.7
> import QtQuick.Controls 2.0
> import com.company.application 1.0
>
> Page
> {
> id : root
>
> property int playlistId
> property var playlistApi: App.playlists.playlist(playlistId)
>
> ListView
> {
> id : playlist
> anchors.fill: parent
> model: playlistApi.model
> delegate: ItemDelegate
> {
> text: model.title
> width: parent.width
> onClicked: App.player.play(playlistId, model.id)
> }
> ScrollIndicator.vertical: ScrollIndicator {}
> }
> }
>
> Update #3:
>
> When the model is updated (one item added), something strange happens with
> QML ListView: in addition to fact that it's not updated (and it does not
> call MediaPlaylistModel::data to retrieve new items), existing items got
> damaged. When I click on existed item, it's model.id property is always 0.
> E.g. at app start its model.id was 24, after one item added its model.id
> became 0.
>
> Update #4:
>
> App.playlists.playlist(playlistId) returns pointer to this class instance:
>
> class CppQmlPlaylistApi :
> public QObject
> {
> Q_OBJECT
> Q_PROPERTY(QObject* model READ model NOTIFY modelChanged)
> Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
>
> public:
> explicit CppQmlPlaylistApi(
> int playlistId,
> QWeakPointer<CorePlaylistsManager> playlistsMgr,
> QObject *parent = 0);
>
> QObject* model() const;
>
> QString title() const;
> void setTitle(const QString &title);
>
> signals:
> void modelChanged();
> void titleChanged();
> void loadPlaylistRequested(int id);
>
> protected slots:
> void onPlaylistLoaded(int id);
> void onPlaylistRemoved(int id);
>
> protected:
> int m_playlistId = 0;
> QWeakPointer<CorePlaylistsManager> m_playlistsMgr;
> QSharedPointer<QAbstractItemModel> m_model;
> };
>
>
>
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest
>
More information about the Interest
mailing list