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. ListView issue when updated (current index set to 0)

ListView issue when updated (current index set to 0)

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
8 Posts 3 Posters 2.7k Views 1 Watching
  • 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.
  • M Offline
    M Offline
    Mickael 22
    wrote on last edited by
    #1

    Hi all,
    I meet an issue with listView when the model is updated from C++.
    After each update from C++, the current index is set to 0 and the view return to beginning of it !
    In the C++ side, the model exposed is declared like this :

    Q_PROPERTY(QList<QObject*> debugList READ getDebugList NOTIFY debugListChanged)
    

    in qml :

     Component {
                        id: nameDelegate
                        Item {
                            id: delegateItem
                            height: ListView.isCurrentItem ? 25 : textDebug.height
                            width:debugRx.width
                            Behavior on height {
                                NumberAnimation {
                                    duration: 750
                                    easing.type: "InOutQuint"
                                }
                            }
                            Text {
                                id:textDebug
                                text: model.modelData.data
                                color: model.modelData.color
                                width: debugRx.width
                                //height: 20
                                lineHeight: 15
                                lineHeightMode:  Text.FixedHeight
                                scale: parent.height/height
                                transformOrigin: Item.Left
                                wrapMode: Text.WordWrap
                                font{
                                    family: "arial"
                                    pixelSize:16
                                }
                            }
                        }
                    }
    
                    ListView {
                        id:listViewDebug
                        snapMode: ListView.SnapOneItem
                        property string name: "listeDebug"
                        property bool scrollDebugAuto: true
                        property int scrollDebugIndex: 0
                        bottomMargin: 5
                        anchors.fill: parent
                        anchors.topMargin: 5
                        anchors.bottomMargin: 5
                        anchors.leftMargin: 2
                        anchors.rightMargin: 2
                        clip:true
                        model:device.debugList
                        focus:true
                        delegate: nameDelegate
                        ScrollBar.vertical: ScrollBar{
                            id:scrollBarDebug
                        }
    
                        highlight: Rectangle {
                            width: listViewDebug.width;
                            border.color: "gray"
                            border.width: 2
                            color : "green"
                            opacity: 0.3
                            radius:5
                            Behavior on y {
                                SpringAnimation {
                                    spring: 3
                                    damping: 0.2
                                }
                            }
                        }
                        highlightFollowsCurrentItem: true
                        //highlightRangeMode : ListView.StrictlyEnforceRange
                        currentIndex: scrollDebugAuto ? listViewDebug.count-1 : scrollDebugIndex
                        onCurrentIndexChanged:{
                            console.log("current index update :"+currentIndex)
                        }
                        onModelChanged: {
                            console.log("current index :"+currentIndex);
                            console.log("save index : "+scrollDebugIndex)
                        }
                        Component.onCompleted: positionViewAtIndex(count - 1, ListView.Beginning)
    
                    }
                }
    

    When the property scrollDebugAuto is true it work fine (the view stay et end of the listView) but when it false the view goes to beginning (current index : 0)
    false--> i 'm trying to add a functionality to disable the list update continuously when the user click to a button

                    CheckBox {
                        id: checkBox
                        text: "\uf0c1"
                        checked: true
                        onCheckedChanged:
                        {
                            if(checked)
                                listViewDebug.scrollDebugAuto=true
                            else
                            {
                                listViewDebug.scrollDebugAuto=false
                                listViewDebug.scrollDebugIndex=listViewDebug.count-1
                                console.log("scroll debug index : "+listViewDebug.scrollDebugIndex)
                            }
                        }
                    }
    

    That's strange is when the model is updated from C++, the listView index is set to 0 !
    When the scrollDebugAuto is true i have this on the log :

    qml: current index update :52
    qml: current index update :0
    qml: current index update :52
    qml: current index :53
    qml: save index : 0

    when is false

    qml: current index update :0
    qml: current index :89
    qml: save index : 72

    we can see that the current index is set to 0 during C++ model update .
    Do you have an idea how i can resolve this ?

    KroMignonK 1 Reply Last reply
    0
    • M Mickael 22

      Hi all,
      I meet an issue with listView when the model is updated from C++.
      After each update from C++, the current index is set to 0 and the view return to beginning of it !
      In the C++ side, the model exposed is declared like this :

      Q_PROPERTY(QList<QObject*> debugList READ getDebugList NOTIFY debugListChanged)
      

      in qml :

       Component {
                          id: nameDelegate
                          Item {
                              id: delegateItem
                              height: ListView.isCurrentItem ? 25 : textDebug.height
                              width:debugRx.width
                              Behavior on height {
                                  NumberAnimation {
                                      duration: 750
                                      easing.type: "InOutQuint"
                                  }
                              }
                              Text {
                                  id:textDebug
                                  text: model.modelData.data
                                  color: model.modelData.color
                                  width: debugRx.width
                                  //height: 20
                                  lineHeight: 15
                                  lineHeightMode:  Text.FixedHeight
                                  scale: parent.height/height
                                  transformOrigin: Item.Left
                                  wrapMode: Text.WordWrap
                                  font{
                                      family: "arial"
                                      pixelSize:16
                                  }
                              }
                          }
                      }
      
                      ListView {
                          id:listViewDebug
                          snapMode: ListView.SnapOneItem
                          property string name: "listeDebug"
                          property bool scrollDebugAuto: true
                          property int scrollDebugIndex: 0
                          bottomMargin: 5
                          anchors.fill: parent
                          anchors.topMargin: 5
                          anchors.bottomMargin: 5
                          anchors.leftMargin: 2
                          anchors.rightMargin: 2
                          clip:true
                          model:device.debugList
                          focus:true
                          delegate: nameDelegate
                          ScrollBar.vertical: ScrollBar{
                              id:scrollBarDebug
                          }
      
                          highlight: Rectangle {
                              width: listViewDebug.width;
                              border.color: "gray"
                              border.width: 2
                              color : "green"
                              opacity: 0.3
                              radius:5
                              Behavior on y {
                                  SpringAnimation {
                                      spring: 3
                                      damping: 0.2
                                  }
                              }
                          }
                          highlightFollowsCurrentItem: true
                          //highlightRangeMode : ListView.StrictlyEnforceRange
                          currentIndex: scrollDebugAuto ? listViewDebug.count-1 : scrollDebugIndex
                          onCurrentIndexChanged:{
                              console.log("current index update :"+currentIndex)
                          }
                          onModelChanged: {
                              console.log("current index :"+currentIndex);
                              console.log("save index : "+scrollDebugIndex)
                          }
                          Component.onCompleted: positionViewAtIndex(count - 1, ListView.Beginning)
      
                      }
                  }
      

      When the property scrollDebugAuto is true it work fine (the view stay et end of the listView) but when it false the view goes to beginning (current index : 0)
      false--> i 'm trying to add a functionality to disable the list update continuously when the user click to a button

                      CheckBox {
                          id: checkBox
                          text: "\uf0c1"
                          checked: true
                          onCheckedChanged:
                          {
                              if(checked)
                                  listViewDebug.scrollDebugAuto=true
                              else
                              {
                                  listViewDebug.scrollDebugAuto=false
                                  listViewDebug.scrollDebugIndex=listViewDebug.count-1
                                  console.log("scroll debug index : "+listViewDebug.scrollDebugIndex)
                              }
                          }
                      }
      

      That's strange is when the model is updated from C++, the listView index is set to 0 !
      When the scrollDebugAuto is true i have this on the log :

      qml: current index update :52
      qml: current index update :0
      qml: current index update :52
      qml: current index :53
      qml: save index : 0

      when is false

      qml: current index update :0
      qml: current index :89
      qml: save index : 72

      we can see that the current index is set to 0 during C++ model update .
      Do you have an idea how i can resolve this ?

      KroMignonK Offline
      KroMignonK Offline
      KroMignon
      wrote on last edited by
      #2

      @Mickael-22 said in ListView issue when updated (current index set to 0):

      Do you have an idea how i can resolve this ?

      AFAIK, this is the normal behavior when using QList<Object *>() or QStringList() as model, because each model update will generate a full new model.
      If you wan't a smooth update, you have to use QAbstractItemModel , cf. https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html

      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

      M 1 Reply Last reply
      0
      • KroMignonK KroMignon

        @Mickael-22 said in ListView issue when updated (current index set to 0):

        Do you have an idea how i can resolve this ?

        AFAIK, this is the normal behavior when using QList<Object *>() or QStringList() as model, because each model update will generate a full new model.
        If you wan't a smooth update, you have to use QAbstractItemModel , cf. https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html

        M Offline
        M Offline
        Mickael 22
        wrote on last edited by
        #3

        @KroMignon Thanks for this explanations, it's more clear now.
        I will have a look on QAbstractItemModel class, it just pity to add more complexity with this class to just keep list current index to it's value !

        KroMignonK 1 Reply Last reply
        0
        • M Mickael 22

          @KroMignon Thanks for this explanations, it's more clear now.
          I will have a look on QAbstractItemModel class, it just pity to add more complexity with this class to just keep list current index to it's value !

          KroMignonK Offline
          KroMignonK Offline
          KroMignon
          wrote on last edited by
          #4

          @Mickael-22 Yes QAbstractItemModel is not easy to use.

          I use since many years now a template class create by Thomas Boutroue which creates an QAbstractListModel by introspection of the base QObject.
          Take a look at Qt QML Models and Qt SuperMacros.

          Here are some explanations at Qt World Summit 2015:
          https://resources.qt.io/videos/qtws15-lightning-talk-a-new-way-for-creating-qml-models-from-c-thomas-boutroue

          Perhaps this could help you.

          It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

          M 1 Reply Last reply
          1
          • jeremy_kJ Offline
            jeremy_kJ Offline
            jeremy_k
            wrote on last edited by
            #5

            This is an undocumented behavior of ListView. When the model is changed, currentIndex is set to 0, or -1 if the model if the empty.

            https://code.woboq.org/qt5/qtdeclarative/src/quick/items/qquickitemview.cpp.html#239:

            if (d->model) {
                    ...
                    if (isComponentComplete()) {
                        ...
                        setCurrentIndex(d->model->count() > 0 ? 0 : -1);
            

            If you have the option, updating the model rather than changing to a new one is probably a better method.

            Asking a question about code? http://eel.is/iso-c++/testcase/

            1 Reply Last reply
            1
            • KroMignonK KroMignon

              @Mickael-22 Yes QAbstractItemModel is not easy to use.

              I use since many years now a template class create by Thomas Boutroue which creates an QAbstractListModel by introspection of the base QObject.
              Take a look at Qt QML Models and Qt SuperMacros.

              Here are some explanations at Qt World Summit 2015:
              https://resources.qt.io/videos/qtws15-lightning-talk-a-new-way-for-creating-qml-models-from-c-thomas-boutroue

              Perhaps this could help you.

              M Offline
              M Offline
              Mickael 22
              wrote on last edited by Mickael 22
              #6

              @KroMignon Thanks a lot !

              @jeremy_k
              in the C++ code i just emit a signal that the list changed like this :

                  m_debugList.append(new BleData(data,color,this));
                  emit debugListChanged();
              
              class BleData : public QObject
              {
                  Q_OBJECT
              
              public:
                  explicit BleData(QObject *parent = nullptr);
                  BleData(QString data,QString color = "black",QObject *parent = nullptr);
              
                  Q_PROPERTY(QString data READ getData NOTIFY dataChanged)
                  Q_PROPERTY(QString color READ getColor NOTIFY colorChanged)
              
              signals:
              
                  void dataChanged(QString data);
                  void colorChanged(QString color);
              
              public slots:
                  QString getData() const;
                  QString getColor() const;
                  void addData(QString data,QString color="black");
              
              private :
                  QString m_data;
                  QString m_color;
              };
              

              I don't know how to proceed in another way

              jeremy_kJ 1 Reply Last reply
              0
              • M Mickael 22

                @KroMignon Thanks a lot !

                @jeremy_k
                in the C++ code i just emit a signal that the list changed like this :

                    m_debugList.append(new BleData(data,color,this));
                    emit debugListChanged();
                
                class BleData : public QObject
                {
                    Q_OBJECT
                
                public:
                    explicit BleData(QObject *parent = nullptr);
                    BleData(QString data,QString color = "black",QObject *parent = nullptr);
                
                    Q_PROPERTY(QString data READ getData NOTIFY dataChanged)
                    Q_PROPERTY(QString color READ getColor NOTIFY colorChanged)
                
                signals:
                
                    void dataChanged(QString data);
                    void colorChanged(QString color);
                
                public slots:
                    QString getData() const;
                    QString getColor() const;
                    void addData(QString data,QString color="black");
                
                private :
                    QString m_data;
                    QString m_color;
                };
                

                I don't know how to proceed in another way

                jeremy_kJ Offline
                jeremy_kJ Offline
                jeremy_k
                wrote on last edited by
                #7

                @Mickael-22 said in ListView issue when updated (current index set to 0):

                @KroMignon Thanks a lot !

                @jeremy_k
                in the C++ code i just emit a signal that the list changed like this :

                    m_debugList.append(new BleData(data,color,this));
                    emit debugListChanged();
                

                That's the entire problem. Emitting the change signal for the list of QObjects says the entire list has changed, and should be treated as a new model.

                The item models that @KroMignon refers to have signals to indicate changes within the model. If implementing a new QAbstractItemModel sounds like too much work, using a QStandardItemModel, or a QML ListView might work. QStringListView could also, with some changes to the delegate.

                Asking a question about code? http://eel.is/iso-c++/testcase/

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  Mickael 22
                  wrote on last edited by
                  #8

                  Thanks for this precisions.
                  i will have a look on the different options and let you know the more convenient way i will use

                  1 Reply Last reply
                  0

                  • Login

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