QML ListView on prepend items to QAbstractListModel, ListView jumps to first element



  • Hello everyone!

    I'm writing messaging app and want to implement fetching older messages. On atYBeginning I call prependFetchMore() and it adds to QAbstractListModel new items. But it immediately jumps to element with index 0, but I'm looking to stay on previous element

    Here 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?



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.