Moving data in QML Listview using QSortFilterProxyModel
-
i am creating a music player and trying to implement a now playing queue, the queue is implemented using a QAbstractItemModel and I am using a QSortFilterProxyModel to only allow songs that are queued but not played yet to be visible.
my problem arises when switchinig to using the QSortFilterProxyModel as the model for the DelegateModel in my listview. when using the proxy model as the source model, when moving the songs, i cannot move it freely within the listview, its like once i move it to a specific index, the move happens but then the drag cancels, the drag should only stop once the user releases the mouse button. This does not happen when I use a normal QAbstractItemModel as the model for the DelegateModel.
Below is the code
relevant part of QML file holding the listview:
//part of component used for listview delegate DropArea { anchors { fill: parent margins: 10 } onEntered: (drag) => { let src_index = drag.source.DelegateModel.itemsIndex let target_index = dragArea.DelegateModel.itemsIndex visualModel.items.move(src_index, target_index) MusicHandler.nowPlaying.moveSong(src_index, target_index) } } } } DelegateModel { id: visualModel model: MusicHandler.nowPlaying.queueProxyModel delegate: dragDelegate } ListView { id: view anchors { top: seperator.bottom left:parent.left right: parent.right rightMargin: 5 bottom: parent.bottom bottomMargin: 5 topMargin: 10 } model: visualModel spacing: 4 clip: true ScrollBar.vertical: ScrollBar { id:viewScrollBar policy: ScrollBar.AlwaysOn width: 10 contentItem: Rectangle { implicitWidth: 10 radius: 3 color: "#2e2e2e" } background: Rectangle { implicitWidth: 10 color: "#7a7a7a" radius: 3 } } } }
slot called from qml to move the song
void NowPlaying::moveSong(int from, int to) { QModelIndex proxyIndexFrom = m_queueProxyModel->index(from, 0); QModelIndex sourceIndexFrom = m_queueProxyModel->mapToSource(proxyIndexFrom); QModelIndex proxyIndexTo = m_queueProxyModel->index(to, 0); QModelIndex sourceIndexTo = m_queueProxyModel->mapToSource(proxyIndexTo); const int sourceRowFrom = sourceIndexFrom.row(); const int sourceRowTo = sourceIndexTo.row(); m_queueModel->moveSong(from, to); //m_queueProxyModel->moveSong(from, to); }
actual moving
void QueueModel::moveSong(int from, int to) { if (from < 0 || from >= rowCount() || to < 0 || to >= rowCount()) { return; } int adjustedTo = (from < to) ? to + 1 : to; beginMoveRows(QModelIndex(), from, from, QModelIndex(), adjustedTo); qDebug() << "moving" << m_queue.at(from)->song->title << "at index" << from << "to index" << to << m_queue.at(to)->song->title; m_queue.move(from, to); endMoveRows(); }
proxy model implementation
#include "queuemodelfilter.h" QueueModelFilter::QueueModelFilter(QueueModel *source_model, QObject *parent) : QSortFilterProxyModel{parent} { setSourceModel(source_model); setDynamicSortFilter(false); } bool QueueModelFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { QModelIndex index = sourceModel()->index(source_row, 0, source_parent); return sourceModel()->data(index, QueueModel::VisibleInQueueRole).toBool(); }