[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