Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QML ListView on prepend items to QAbstractListModel, ListView jumps to first element

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

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
qmllistviewscrollingmobileqlistmodel
1 Posts 1 Posters 889 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    blacky_i
    wrote on 6 Jan 2019, 15:19 last edited by
    #1

    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?

    1 Reply Last reply
    0

    1/1

    6 Jan 2019, 15:19

    • Login

    • Login or register to search.
    1 out of 1
    • First post
      1/1
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved