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. [SOLVED] Nested ListViews - Problem with indexing - QtQuick 2.0

[SOLVED] Nested ListViews - Problem with indexing - QtQuick 2.0

Scheduled Pinned Locked Moved QML and Qt Quick
6 Posts 2 Posters 4.3k 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.
  • A Offline
    A Offline
    admiralfluff
    wrote on last edited by
    #1

    I am working on an application in which a ListView may have multiple delegate types, one of which may itself be a list view.

    The following screenshots demonstrate the basic functionality.

    Vertical scrolling through main ListView:
    !https://lh3.googleusercontent.com/twdgan47Mj8zvwBGTJeTRdQiCzRw118l4k5b6bOp5fMLmVdCuDfbUQm2bVd3cxvAayKscDgJ10k(img 1)! !https://lh6.googleusercontent.com/ePeMrXYgHzE8PB_KReKjzd6E1F31mPdtwebQ5a0XN4ocC11KnxSSCpFaZb3s97-awYysiNAA-4M(img 2)! !https://lh5.googleusercontent.com/hjj8TywMDqKQm8U5RJ_rqvduA77xkvTMTp0TYsJMfR2FLv0duGS3Jplp8nuEj3NUcRrGXVkh6ec(img 3)!

    Horizontal scrolling through nested ListView:
    !https://lh3.googleusercontent.com/twdgan47Mj8zvwBGTJeTRdQiCzRw118l4k5b6bOp5fMLmVdCuDfbUQm2bVd3cxvAayKscDgJ10k(img 1)! !https://lh4.googleusercontent.com/AMKHGqlYWWSeRFUddPQ7cepKw0QAlgYKTbd0PAXR4PC5w-lifgVTwjrbnkG7B6qUPCtk4dqH3hY(img 4)! !https://lh4.googleusercontent.com/qgSkpXDKEpoirB1ojWxjNxKPoKfL4ncu9EnBPGG-SInBILYTM91yU3f_61nHaZEg5CUS-RagKes(img 5)!

    Nested ListView maintains its currentIndex when scrolling through main ListView:
    !https://lh5.googleusercontent.com/oXY-Bsjum56eBozKtWK8Yrg67BpfF38d7jzQgVEahQWwjIPeAowb06_wgCknja0fjcyBOZn93rE(img 6)! !https://lh6.googleusercontent.com/O4XPzM2uDLrG0B58tRJTtd2N4knkEZ16Sfg_LwLu-beRmZhrlFx4kqaylPKbMEJ1oLDgWGIiMDk(img 7)!

    I'm able to get most of the functionality I'm after, but I have not been able to find a way to access and store the index state of the nested ListViews when a different element is selected in the main list (it is ~faked in the screenshots).

    1 Reply Last reply
    0
    • A Offline
      A Offline
      admiralfluff
      wrote on last edited by
      #2

      CODE
      The simplified version of the views/model

      MenuTest.qml

      Create a simple vertical ListView
      @import QtQuick 2.0

      Rectangle {
      id: root
      width: 200
      height: 280

      ListView {  //Main Vertical ListView
          id: list
          anchors.fill: parent
          model: TestModel{}
          delegate: testDelegate
          highlight:Rectangle{color: "#FF404040";}
      }@
      

      The delegate component selects from 2 different components based on the a 'type' role in the ListItem.
      @Component{ //Delegate Component
      id:testDelegate
      Item{
      id: delegateItem
      width: root.width
      height:45
      //Loader picks correct delegate based on 'type' role in listModel
      Loader {
      anchors.fill: parent
      sourceComponent: chooseDelegate(type)
      }
      function chooseDelegate(type){
      if (type=="text") return textDelegate;
      else if (type=="quick") return rowDelegate;
      }@

      The textDelegate simply displays the 'name' role
      @//Delegate for 'text' elements
      Component{
      id: textDelegate
      Text{
      text: name
      font.pixelSize: 32
      color: {if(delegateItem.ListView.isCurrentItem) return "white";else return "darkgrey";}
      }
      }//end text delegate@

      The rowDelegate creates an embedded horizontal ListView
      @//Delegate for 'row' elements
      Component{
      id: rowDelegate
      ListView{
      id: rowView
      spacing: 20
      orientation: ListView.Horizontal
      highlight:Rectangle{color:"gray"}
      model: attributes
      currentIndex: list.model.get(0).index
      delegate: Text{
      id:rowItemDelegate
      text: name
      font.pixelSize: 24
      color:if(rowItemDelegate.ListView.isCurrentItem && delegateItem.ListView.isCurrentItem) return "white";else return "darkgrey";
      }
      }//end row listview
      }//end row delegate
      }//end delegate item
      }//end delegate component@
      The nested ListView retrieves its 'currentIndex' from the 'index' role of the first ListElement in the ListModel.
      currentIndex: list.model.get(0).index
      The problem with this is that only 1 nested ListView element can be in the main list, and I have to know its position in the list to pass to the get method. I can change the line to currentIndex: list.model.get(list.currentIndex).index and scrolling the nested ListView will work, but as soon as I select a new element in the main ListView, the 'index' role is no longer valid, and the nested ListView bounces back to the beginning.

      I use the keyboard to directly augment the 'index' role of the ListModel
      @ focus:true
      Keys.onPressed: {
      if( event.key === Qt.Key_Q )
      {
      event.accepted = true;
      Qt.quit();
      }
      else if( event.key === Qt.Key_Left)
      {
      event.accepted = true;
      if(list.model.get(list.currentIndex).type=="quick"){
      if(list.model.get(list.currentIndex).index>0){
      list.model.get(list.currentIndex).index--;
      console.debug("quick item "+list.model.get(list.currentIndex).index);
      }
      }

          }
          else if( event.key === Qt.Key_Right)
          {
              event.accepted = true;
              if(list.model.get(list.currentIndex).type=="quick"){
                  if(list.model.get(list.currentIndex).index<list.model.get(list.currentIndex).attributes.count-1){
                      list.model.get(list.currentIndex).index++;
                      console.debug("quick item "+list.model.get(list.currentIndex).index);
                  }
              }
          }
      
          else if( event.key === Qt.Key_Down){
              event.accepted = true;
              if(list.currentIndex<list.count-1) list.currentIndex++;
          }
          else if( event.key === Qt.Key_Up){
              event.accepted = true;
              if(list.currentIndex>0) list.currentIndex--;
          }
      }//end key event handler
      

      }// end root Rectangle@

      Finally, the ListModel: TestModel.qml
      @import QtQuick 2.0

      ListModel{
      ListElement{
      name: "shortcuts"
      type: "quick"
      index: 0
      attributes{
      ListElement {type: "text"; name: "A "}
      ListElement {type: "text"; name: "B "}
      ListElement {type: "text"; name: "C "}
      ListElement {type: "text"; name: "D "}
      ListElement {type: "text"; name: "E "}
      }
      }
      ListElement{type: "text"; name: "1"}
      ListElement{type: "text"; name: "2"}
      ListElement{type: "text"; name: "3"}
      ListElement{type: "text"; name: "4"}
      ListElement{type: "text"; name: "5"}
      }@

      So there may be 3 potential solutions -

      Is there any way for the nested ListView, which is part of a delegate component, to retrieve the index of the ListElement it is associated with?

      Is there any way to directly access the nested ListView.currentIndex property in the key handlers?

      Or do I need to subclass one of the Qt abstract models and extend a custom tree data model to QML?

      greatly appreciate any help,

      AF

      1 Reply Last reply
      0
      • D Offline
        D Offline
        dmcr
        wrote on last edited by
        #3

        Hello,

        I have read -carefully- your code.... and eventually i have an alternative point of view :)
        If i have understood correctly, you have different ways of displaying your elements.
        So you choose to have two delegates.
        Why don't you create only one delegate, "embedding" the two you have created, and then choosing if the "inside View" is displayed or not ?
        I know that a bit different, but it will probably be simplier for you to manage your indexes.

        Democrie

        dmcr

        1 Reply Last reply
        0
        • A Offline
          A Offline
          admiralfluff
          wrote on last edited by
          #4

          [quote author="dmcr" date="1348739606"]
          Why don't you create only one delegate, "embedding" the two you have created, and then choosing if the "inside View" is displayed or not ?
          Democrie
          [/quote]

          This is essentially what I'm doing - the main ListView always uses the testDelegate component. I use a Loader in the testDelegate component to decide what to display because I thought it would be more resource efficient (especially in the real application, where there will be far more delegate types icons etc.).

          I don't see how your suggestions would solve my problem; I still need a way to access data stored in a delegate instance from outside, or for a delegate instance to retrieve its index in a listview.

          1 Reply Last reply
          0
          • A Offline
            A Offline
            admiralfluff
            wrote on last edited by
            #5

            I figured it out. The problem was that by defining an 'index' role in my ListModel, which I use to track the index in the embedded attributes model, I ended up overwriting the built in 'index' role of the ListElements. I changed this new role to 'subIndex', and changed
            currentIndex: list.model.get(0).index to currentIndex: list.model.get(index).subIndex
            and it works fine now.

            1 Reply Last reply
            0
            • D Offline
              D Offline
              dmcr
              wrote on last edited by
              #6

              Sometimes i read the code given too fast.....
              However yeah it was a nasty bug!--

              dmcr

              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