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. Expandable ListView delegate and other questions

Expandable ListView delegate and other questions

Scheduled Pinned Locked Moved Solved QML and Qt Quick
7 Posts 3 Posters 2.6k 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.
  • A Offline
    A Offline
    AndrzejO
    wrote on 6 Sept 2017, 13:56 last edited by
    #1

    Hello all

    This is my first question in this subforum/category and I'm afraid it won't be last since I'm just starting with QML/Quick.

    I've written simple example with which I'm having problems (explanations below):

    import QtQuick 2.7
    import QtQuick.Controls 2.1
    import QtQuick.Layouts 1.0
    
    ApplicationWindow {
        id: app
        visible: true
        width: 340
        height: 480
        title: qsTr("Simple test")
    
    
        Component {
            id: delComp
            Rectangle {
                width: view.width
                height: 80
                border.color: "red"
                border.width: 1
    
                Row {
                    id: row
                    anchors {
                        top: parent.top
                        horizontalCenter: parent.horizontalCenter
                    }
                    Rectangle {
                        width: 100
                        height: 40
                        color: "lightgray"
                        Text {
                            anchors.centerIn: parent
                            text: value
                        }
                    }
                    CheckBox {
                        text: "Active"
                        checked: active
                        onCheckedChanged:  {
                            active = checked
                        }
                    }
                    Text {
                        text: "\u2630"
                        font.pixelSize: 20
                        anchors.verticalCenter: parent.verticalCenter
                        MouseArea {
                            anchors.fill: parent
                            onClicked: {
                                console.log("Changing visible:" + details.visible)
                                details.visible = !details.visible
    //                            console.log("Opening popup")
    //                            schedDialog.row = index
    //                            schedDialog.auto = auto
    //                            schedDialog.open()
                            }
                        }
                    }
                }
    
                Rectangle {
                    id: details
                    visible: false
                    anchors {
                        top: row.bottom
                        bottom: parent.bottom
                        horizontalCenter: parent.horizontalCenter
                    }
                    height: 80
                    Text { text: "Details" }
                }
    
                Connections {
                    target: schedDialog
                    onAccepted: {
                        if (index === schedDialog.row) {
                            console.log("Delegate accept")
                            auto = schedDialog.auto
                        }
                    }
                }
            }
        }
    
        Dialog {
            id: schedDialog
            x: (parent.width - implicitWidth)/2
            y: (parent.height - implicitHeight)/2
            standardButtons: Dialog.Cancel | Dialog.Ok
            modal: true
            property int row: 0
            property alias auto: chkBox.checked
    //        property int start: 0
    //        property int stop: 0
    
            ColumnLayout {
                CheckBox {
                    id: chkBox
                    text: "Enable schedule"
                }
            }
    //        onAccepted: {
    //            // XXX - how can I update model here???
    //        }
        }
    
        ListView {
            id: view
            anchors.fill: parent
            model: simpleModel
            delegate: delComp
        }
    
        ListModel {
            id: simpleModel
            ListElement {
                value: 1023
                active: true
                auto: false
                start: 0 // TODO: What is QML equivalent of QTime
                stop: 0
            }
            ListElement {
                value: 0
                active: false
                auto: true
                start: 10
                stop: 20
            }
            ListElement {
                value: 5421
                active: true
                auto: true
                start: 1000
                stop: 2020
            }
            onDataChanged: {
                console.log("Data changed " + topLeft)
            }
        }
    }
    

    So this is a simple list view with some items and I want to show each item with simplified interface (not showing all details). This is quite simple and I've added "heaven" button which originally (now commented) was opening popup dialog with the remaining details for given item.

    First question(s):

    • if I have Dialog as part of delegate then there is no problem with access/modification of model's data but how can I position dialog popup from delegate relative to the app window (and not relative to the delegate) - setting y to (app.height - implicitHeight)/2 seems to position dialog correct distance but not from app.top but from the delegate.top - if I get this then below questions are only for my curiosity
    • if the dialog is outside of the delegate how can I access given model item data, any attached properties, modelData? Right now I copy values to Dialog.
    • if the dialog is outside of the delegate what would be the best method to update model - right now I have all delegates connected to the Dialog's accepted signal and they check row in order to see if they need to update model with Dialog's values or not

    Since I had problems with this dialog I thought about having different design and now I want to create list view in which delegate will be expanding a bit and showing hidden content. This is not really similar to "expandingdelegates" from the Qt Quick 'Views' example coming with Qt. In there the delegate expands to the whole screen and I want to have delegate expand a bit showing more controls and pushing other delegates down.
    I thought about adding second Rectangle (details) and changing its visibility but that does not work. The "Details" text visibility is changing as needed but the delegate is not sizing according to its visibility.

    How can I achieve that effect?

    For example setting height of the top level Rectangle in delComp to: details.visible ? row.height + details.height : row.height does not do anything. Is it possible to have list view with each delegate having different height? If so how can I achieve that?

    My apologies for a lengthy post, and thank you for reading it.

    Best regards
    Andrzej

    A E 2 Replies Last reply 6 Sept 2017, 16:57
    0
    • A AndrzejO
      6 Sept 2017, 13:56

      Hello all

      This is my first question in this subforum/category and I'm afraid it won't be last since I'm just starting with QML/Quick.

      I've written simple example with which I'm having problems (explanations below):

      import QtQuick 2.7
      import QtQuick.Controls 2.1
      import QtQuick.Layouts 1.0
      
      ApplicationWindow {
          id: app
          visible: true
          width: 340
          height: 480
          title: qsTr("Simple test")
      
      
          Component {
              id: delComp
              Rectangle {
                  width: view.width
                  height: 80
                  border.color: "red"
                  border.width: 1
      
                  Row {
                      id: row
                      anchors {
                          top: parent.top
                          horizontalCenter: parent.horizontalCenter
                      }
                      Rectangle {
                          width: 100
                          height: 40
                          color: "lightgray"
                          Text {
                              anchors.centerIn: parent
                              text: value
                          }
                      }
                      CheckBox {
                          text: "Active"
                          checked: active
                          onCheckedChanged:  {
                              active = checked
                          }
                      }
                      Text {
                          text: "\u2630"
                          font.pixelSize: 20
                          anchors.verticalCenter: parent.verticalCenter
                          MouseArea {
                              anchors.fill: parent
                              onClicked: {
                                  console.log("Changing visible:" + details.visible)
                                  details.visible = !details.visible
      //                            console.log("Opening popup")
      //                            schedDialog.row = index
      //                            schedDialog.auto = auto
      //                            schedDialog.open()
                              }
                          }
                      }
                  }
      
                  Rectangle {
                      id: details
                      visible: false
                      anchors {
                          top: row.bottom
                          bottom: parent.bottom
                          horizontalCenter: parent.horizontalCenter
                      }
                      height: 80
                      Text { text: "Details" }
                  }
      
                  Connections {
                      target: schedDialog
                      onAccepted: {
                          if (index === schedDialog.row) {
                              console.log("Delegate accept")
                              auto = schedDialog.auto
                          }
                      }
                  }
              }
          }
      
          Dialog {
              id: schedDialog
              x: (parent.width - implicitWidth)/2
              y: (parent.height - implicitHeight)/2
              standardButtons: Dialog.Cancel | Dialog.Ok
              modal: true
              property int row: 0
              property alias auto: chkBox.checked
      //        property int start: 0
      //        property int stop: 0
      
              ColumnLayout {
                  CheckBox {
                      id: chkBox
                      text: "Enable schedule"
                  }
              }
      //        onAccepted: {
      //            // XXX - how can I update model here???
      //        }
          }
      
          ListView {
              id: view
              anchors.fill: parent
              model: simpleModel
              delegate: delComp
          }
      
          ListModel {
              id: simpleModel
              ListElement {
                  value: 1023
                  active: true
                  auto: false
                  start: 0 // TODO: What is QML equivalent of QTime
                  stop: 0
              }
              ListElement {
                  value: 0
                  active: false
                  auto: true
                  start: 10
                  stop: 20
              }
              ListElement {
                  value: 5421
                  active: true
                  auto: true
                  start: 1000
                  stop: 2020
              }
              onDataChanged: {
                  console.log("Data changed " + topLeft)
              }
          }
      }
      

      So this is a simple list view with some items and I want to show each item with simplified interface (not showing all details). This is quite simple and I've added "heaven" button which originally (now commented) was opening popup dialog with the remaining details for given item.

      First question(s):

      • if I have Dialog as part of delegate then there is no problem with access/modification of model's data but how can I position dialog popup from delegate relative to the app window (and not relative to the delegate) - setting y to (app.height - implicitHeight)/2 seems to position dialog correct distance but not from app.top but from the delegate.top - if I get this then below questions are only for my curiosity
      • if the dialog is outside of the delegate how can I access given model item data, any attached properties, modelData? Right now I copy values to Dialog.
      • if the dialog is outside of the delegate what would be the best method to update model - right now I have all delegates connected to the Dialog's accepted signal and they check row in order to see if they need to update model with Dialog's values or not

      Since I had problems with this dialog I thought about having different design and now I want to create list view in which delegate will be expanding a bit and showing hidden content. This is not really similar to "expandingdelegates" from the Qt Quick 'Views' example coming with Qt. In there the delegate expands to the whole screen and I want to have delegate expand a bit showing more controls and pushing other delegates down.
      I thought about adding second Rectangle (details) and changing its visibility but that does not work. The "Details" text visibility is changing as needed but the delegate is not sizing according to its visibility.

      How can I achieve that effect?

      For example setting height of the top level Rectangle in delComp to: details.visible ? row.height + details.height : row.height does not do anything. Is it possible to have list view with each delegate having different height? If so how can I achieve that?

      My apologies for a lengthy post, and thank you for reading it.

      Best regards
      Andrzej

      A Offline
      A Offline
      AndrzejO
      wrote on 6 Sept 2017, 16:57 last edited by
      #2

      I've just found out that if instead of specifying height of the top level Rectangle in delComp to:

        height: details.visible ? row.height + details.height : row.height
      

      I do it as:

        height: row.height + (details.visible ? details.height : 0)
      

      then the delegate is expanding as I wanted. Could somebody explain the difference?

      Best regards
      Andrzej

      1 Reply Last reply
      0
      • 6 Offline
        6 Offline
        6thC
        wrote on 6 Sept 2017, 23:37 last edited by 6thC 9 Jun 2017, 23:42
        #3
        This post is deleted!
        1 Reply Last reply
        0
        • A Offline
          A Offline
          AndrzejO
          wrote on 7 Sept 2017, 13:05 last edited by
          #4

          I'm still interested in answer to my questions (anybody?) but since I now have the code working as I want I'm marking this topic as solved.

          1 Reply Last reply
          0
          • A AndrzejO
            6 Sept 2017, 13:56

            Hello all

            This is my first question in this subforum/category and I'm afraid it won't be last since I'm just starting with QML/Quick.

            I've written simple example with which I'm having problems (explanations below):

            import QtQuick 2.7
            import QtQuick.Controls 2.1
            import QtQuick.Layouts 1.0
            
            ApplicationWindow {
                id: app
                visible: true
                width: 340
                height: 480
                title: qsTr("Simple test")
            
            
                Component {
                    id: delComp
                    Rectangle {
                        width: view.width
                        height: 80
                        border.color: "red"
                        border.width: 1
            
                        Row {
                            id: row
                            anchors {
                                top: parent.top
                                horizontalCenter: parent.horizontalCenter
                            }
                            Rectangle {
                                width: 100
                                height: 40
                                color: "lightgray"
                                Text {
                                    anchors.centerIn: parent
                                    text: value
                                }
                            }
                            CheckBox {
                                text: "Active"
                                checked: active
                                onCheckedChanged:  {
                                    active = checked
                                }
                            }
                            Text {
                                text: "\u2630"
                                font.pixelSize: 20
                                anchors.verticalCenter: parent.verticalCenter
                                MouseArea {
                                    anchors.fill: parent
                                    onClicked: {
                                        console.log("Changing visible:" + details.visible)
                                        details.visible = !details.visible
            //                            console.log("Opening popup")
            //                            schedDialog.row = index
            //                            schedDialog.auto = auto
            //                            schedDialog.open()
                                    }
                                }
                            }
                        }
            
                        Rectangle {
                            id: details
                            visible: false
                            anchors {
                                top: row.bottom
                                bottom: parent.bottom
                                horizontalCenter: parent.horizontalCenter
                            }
                            height: 80
                            Text { text: "Details" }
                        }
            
                        Connections {
                            target: schedDialog
                            onAccepted: {
                                if (index === schedDialog.row) {
                                    console.log("Delegate accept")
                                    auto = schedDialog.auto
                                }
                            }
                        }
                    }
                }
            
                Dialog {
                    id: schedDialog
                    x: (parent.width - implicitWidth)/2
                    y: (parent.height - implicitHeight)/2
                    standardButtons: Dialog.Cancel | Dialog.Ok
                    modal: true
                    property int row: 0
                    property alias auto: chkBox.checked
            //        property int start: 0
            //        property int stop: 0
            
                    ColumnLayout {
                        CheckBox {
                            id: chkBox
                            text: "Enable schedule"
                        }
                    }
            //        onAccepted: {
            //            // XXX - how can I update model here???
            //        }
                }
            
                ListView {
                    id: view
                    anchors.fill: parent
                    model: simpleModel
                    delegate: delComp
                }
            
                ListModel {
                    id: simpleModel
                    ListElement {
                        value: 1023
                        active: true
                        auto: false
                        start: 0 // TODO: What is QML equivalent of QTime
                        stop: 0
                    }
                    ListElement {
                        value: 0
                        active: false
                        auto: true
                        start: 10
                        stop: 20
                    }
                    ListElement {
                        value: 5421
                        active: true
                        auto: true
                        start: 1000
                        stop: 2020
                    }
                    onDataChanged: {
                        console.log("Data changed " + topLeft)
                    }
                }
            }
            

            So this is a simple list view with some items and I want to show each item with simplified interface (not showing all details). This is quite simple and I've added "heaven" button which originally (now commented) was opening popup dialog with the remaining details for given item.

            First question(s):

            • if I have Dialog as part of delegate then there is no problem with access/modification of model's data but how can I position dialog popup from delegate relative to the app window (and not relative to the delegate) - setting y to (app.height - implicitHeight)/2 seems to position dialog correct distance but not from app.top but from the delegate.top - if I get this then below questions are only for my curiosity
            • if the dialog is outside of the delegate how can I access given model item data, any attached properties, modelData? Right now I copy values to Dialog.
            • if the dialog is outside of the delegate what would be the best method to update model - right now I have all delegates connected to the Dialog's accepted signal and they check row in order to see if they need to update model with Dialog's values or not

            Since I had problems with this dialog I thought about having different design and now I want to create list view in which delegate will be expanding a bit and showing hidden content. This is not really similar to "expandingdelegates" from the Qt Quick 'Views' example coming with Qt. In there the delegate expands to the whole screen and I want to have delegate expand a bit showing more controls and pushing other delegates down.
            I thought about adding second Rectangle (details) and changing its visibility but that does not work. The "Details" text visibility is changing as needed but the delegate is not sizing according to its visibility.

            How can I achieve that effect?

            For example setting height of the top level Rectangle in delComp to: details.visible ? row.height + details.height : row.height does not do anything. Is it possible to have list view with each delegate having different height? If so how can I achieve that?

            My apologies for a lengthy post, and thank you for reading it.

            Best regards
            Andrzej

            E Offline
            E Offline
            Eeli K
            wrote on 7 Sept 2017, 14:45 last edited by
            #5

            @AndrzejO said in Expandable ListView delegate and other questions:

            • if I have Dialog as part of delegate then there is no problem with access/modification of model's data but how can I position dialog popup from delegate relative to the app window (and not relative to the delegate) - setting y to (app.height - implicitHeight)/2 seems to position dialog correct distance but not from app.top but from the delegate.top

            You must translate the coordinates. See Item's mapTo... and mapFrom... methods. They are difficult to use so I don't even try to give any code. Having one dialog per delegate object is of course inefficient, one dialog is better.

            You don't access a delegate's properties from outside that delegate object. Instead you communicate through the model or set things from the delegate. Here it's done through the model, modifying your code:

            MouseArea {
                                    anchors.fill: parent
                                    onClicked: {
                                        schedDialog.row = index
                                        schedDialog.open()
                                    }
                                }
            
            Dialog {
                    id: schedDialog
                    x: (parent.width - implicitWidth)/2
                    y: (parent.height - implicitHeight)/2
                    standardButtons: Dialog.Close
                    modal: true
                    property int row: 0
                    ColumnLayout{
                        CheckBox {
                            id: chkB
                            text: "Enable schedule"
                        }
                    }
                    onOpened: chkB.checked = simpleModel.get(row).auto
                    onClosed: simpleModel.get(row).auto = chkB.checked // or use onCheckedChanged of chkB
                }
            

            Basically you use whatever means are available for manipulating the model data. ListModel has this get() method which lets you handle one item as a javascript object. C++ models have their own methods.

            I've just found out that if instead of specifying height of the top level Rectangle in delComp to:
            height: details.visible ? row.height + details.height : row.height
            I do it as:
            height: row.height + (details.visible ? details.height : 0)
            then the delegate is expanding as I wanted. Could somebody explain the difference?

            At least I can't. Very interesting.

            A 1 Reply Last reply 9 Sept 2017, 07:23
            0
            • E Eeli K
              7 Sept 2017, 14:45

              @AndrzejO said in Expandable ListView delegate and other questions:

              • if I have Dialog as part of delegate then there is no problem with access/modification of model's data but how can I position dialog popup from delegate relative to the app window (and not relative to the delegate) - setting y to (app.height - implicitHeight)/2 seems to position dialog correct distance but not from app.top but from the delegate.top

              You must translate the coordinates. See Item's mapTo... and mapFrom... methods. They are difficult to use so I don't even try to give any code. Having one dialog per delegate object is of course inefficient, one dialog is better.

              You don't access a delegate's properties from outside that delegate object. Instead you communicate through the model or set things from the delegate. Here it's done through the model, modifying your code:

              MouseArea {
                                      anchors.fill: parent
                                      onClicked: {
                                          schedDialog.row = index
                                          schedDialog.open()
                                      }
                                  }
              
              Dialog {
                      id: schedDialog
                      x: (parent.width - implicitWidth)/2
                      y: (parent.height - implicitHeight)/2
                      standardButtons: Dialog.Close
                      modal: true
                      property int row: 0
                      ColumnLayout{
                          CheckBox {
                              id: chkB
                              text: "Enable schedule"
                          }
                      }
                      onOpened: chkB.checked = simpleModel.get(row).auto
                      onClosed: simpleModel.get(row).auto = chkB.checked // or use onCheckedChanged of chkB
                  }
              

              Basically you use whatever means are available for manipulating the model data. ListModel has this get() method which lets you handle one item as a javascript object. C++ models have their own methods.

              I've just found out that if instead of specifying height of the top level Rectangle in delComp to:
              height: details.visible ? row.height + details.height : row.height
              I do it as:
              height: row.height + (details.visible ? details.height : 0)
              then the delegate is expanding as I wanted. Could somebody explain the difference?

              At least I can't. Very interesting.

              A Offline
              A Offline
              AndrzejO
              wrote on 9 Sept 2017, 07:23 last edited by
              #6

              Thanks @Eeli-K for taking a look at it.
              Would your onClosed work the same if the model was on the C++ side? I mean if the model is defined in C++ and e.g. set as a context property could you call model.get(row).auto = chkB.checked on it, or is it just the interface of ListModel QML type. If the latter how would you define function with Q_INVOKED that would provide such interface?

              Best regards
              Andrzej

              E 1 Reply Last reply 9 Sept 2017, 08:52
              0
              • A AndrzejO
                9 Sept 2017, 07:23

                Thanks @Eeli-K for taking a look at it.
                Would your onClosed work the same if the model was on the C++ side? I mean if the model is defined in C++ and e.g. set as a context property could you call model.get(row).auto = chkB.checked on it, or is it just the interface of ListModel QML type. If the latter how would you define function with Q_INVOKED that would provide such interface?

                Best regards
                Andrzej

                E Offline
                E Offline
                Eeli K
                wrote on 9 Sept 2017, 08:52 last edited by
                #7

                @AndrzejO As I said, "C++ models have their own methods". In the documentation of QAbstractItemModel you find insert..., move..., remove... and set... methods or you can implement your own custom interface as long as you send the corresponding signals which tell the listeners when the model is changed. For example you have Q_INVOKABLE changeSomeDataValueOnEveryRow(int argumentForCalculatingNewValues). You change all wanted data values there and choose the signal to send - dataChanged for each row, or maybe even modelAboutToBeReset and modelReset. Learn how to subclass QAbstractItemModel.

                1 Reply Last reply
                0

                5/7

                7 Sept 2017, 14:45

                • Login

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