Den 27 feb. 2017 11:27 em skrev "Alexander Dyagilev" <alervd...@gmail.com>: > > It seems the reason is that the model object is located in non-GUI thread... > > Is there a way to work around this? I would prefer to keep my model in non GUI thread. > > Is it a mandatory requirement to keep models in GUI thread only?
I think so. Due to signal connections becoming queued if they're on separate threads, and the model/view machinery working with begin/end style emissions, I don't think it's safe. May be other problems as well. If you really have CPU intensive work to do when updating your model, use a worker thread, but synchronize with your GUI thread when results are ready. QtConcurrent can simplify a little here, depending on your use case. If you're only blocking on I/O, consider making the I/O operations asynchronous on top of the Qt event loop, if at all possible, and avoid threading. 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@qt-project.org > http://lists.qt-project.org/mailman/listinfo/interest >
_______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest