QML ListView on prepend items to QAbstractListModel, ListView jumps to first element
Unsolved
QML and Qt Quick
-
Hello everyone!
I'm writing messaging app and want to implement fetching older messages. On
atYBeginning
I callprependFetchMore()
and it adds toQAbstractListModel
new items. But it immediately jumps to element with index0
, but I'm looking to stay on previous elementHere is listView.qml:
import QtQuick 2.6 import QtQuick.Window 2.2 import org.test1.0 Window { id:window visible: true width: 640 height: 480 title: qsTr("Hello World") Column { width:parent.width Rectangle { id:busyInd property bool running: false color:"black" width: parent.width height:running ? 40 : 0 focus: running } ListView{ id:listView onContentYChanged: if ( atYBeginning ) { modelRef.prependFetchMore() } onCurrentIndexChanged: console.log("current index - " + currentIndex) width: parent.width height: window.height - busyInd.height model: MyModel { id:modelRef initialIndex: 100 } delegate: Rectangle { width:parent.width height: 100 border.color: 'black' border.width: 2 color: element_ref > 0 ? "cyan" : "transparent" Row { anchors.horizontalCenter: parent.horizontalCenter Text { text: "index = " + index } Item { width: 50 height: 1 } Text { id: elementId text: "id = " + element_id } Item { width: 50 height: 1 } Text { id: elementRef text: "ref_id = " + element_ref } } } header: Rectangle { z:1000 width: parent.width height: 20 color: "red" MouseArea { anchors.fill: parent onClicked: listView.positionViewAtBeginning() } } headerPositioning:ListView.OverlayHeader footerPositioning:ListView.OverlayFooter footer: Rectangle { z:1000 width: parent.width height: 20 color: "blue" MouseArea { anchors.fill: parent onClicked: listView.positionViewAtEnd() } } } } }
Here is my model:
#include "mymodel.h" #include <QDebug> MyModel::MyModel(QObject *parent) : QAbstractListModel(parent), m_initialIndex(0), m_currentStack(0) { Top.append(-1); //int[] ids = {8,260,370}; } int MyModel::rowCount(const QModelIndex &parent) const { return m_elements.size(); } QVariant MyModel::data(const QModelIndex &index, int role) const { if( index.row() < 0) return QVariant(); int rowIndex = index.row(); switch (role) { case ID: return m_elements[rowIndex].id; break; case REF: return m_elements[rowIndex].ref; break; } return QVariant(); } void MyModel::fetchMore(const QModelIndex &parent) { if(!fetching) { fetching = true; if (m_elements.size() == 0) { auto elements = getNewElements(m_initialIndex,MAX_PER_PAGE); appendElements(elements,m_currentStack); } else { auto elements = getNewElements(m_elements[Top[m_currentStack]].id,MAX_PER_PAGE); appendElements(elements,m_currentStack); } fetching = false; } } bool MyModel::canFetchMore(const QModelIndex &/* parent*/) const { return !fetching && m_elements.size() < 600; } QHash<int, QByteArray> MyModel::roleNames() const { QHash<int, QByteArray> roles; roles[ID] = "element_id"; roles[REF] = "element_ref"; return roles; } int MyModel::initialIndex() const { return m_initialIndex; } void MyModel::setInitialIndex(int initialIndex) { if (m_initialIndex == initialIndex) return; m_initialIndex = initialIndex; emit initialIndexChanged(m_initialIndex); } void MyModel::prependFetchMore() { if(!fetching) { if (m_elements.size() != 0) { fetching = true; auto elements = getNewElements(m_elements.first().id - MAX_PER_PAGE - 1,MAX_PER_PAGE); if(elements.size()>0) prependElements(elements,m_currentStack); } fetching = false; } } QList<Element> MyModel::getNewElements(const int lastId, const int size) { QList<Element> result; if(lastId >=600) return result; int off_size = size; if(lastId+size >=600) off_size = 600 - lastId; if(lastId >= 0) { for (int i = lastId + 1; i < lastId + 1 + off_size;i++) { if(i == 0) result.append(Element(i,250)); else if(i == 250) result.append(Element(i,350)); else if(i == 350) result.append(Element(i,550)); else result.append(Element(i,0)); } } return result; } void MyModel::appendElements(const QList<Element> &elements, const int &stackNumber) { int lastIndex = Top[stackNumber]; if(elements.size() > 0) { beginInsertRows(QModelIndex(),lastIndex + 1,lastIndex + elements.size()); foreach (auto el, elements) { lastIndex++; m_elements.insert(lastIndex,el); } for (int i = stackNumber; i < Top.size(); i++) Top[i] = Top[i] + elements.size(); endInsertRows(); } } void MyModel::prependElements(const QList<Element> &elements, const int &stackNumber) { int lastIndex = 0; if(stackNumber != 0) lastIndex = Top[stackNumber - 1] + 1; beginInsertRows(QModelIndex(),lastIndex,lastIndex + elements.size() - 1); for(int i = elements.size() - 1; i >= 0; i--) { m_elements.insert(lastIndex, elements[i]); } for (int i = stackNumber; i < Top.size(); i++) Top[i] = Top[i] + elements.size(); endInsertRows(); }
So how to preverve element position?