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. Cant access model data from dialog
Forum Updated to NodeBB v4.3 + New Features

Cant access model data from dialog

Scheduled Pinned Locked Moved Solved QML and Qt Quick
4 Posts 2 Posters 423 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.
  • F Offline
    F Offline
    FrecciaGLT
    wrote on last edited by
    #1

    Hello everyone,

    I am currently using a ListView to display data about a type of smart plug. The data I get from the plug is stored inside the associated ListModel.
    I can access the model data from inside the ListViews delegate.

    Now here is my problem: Inside of the delegate I have a button that opens a dialog to set a timer. The dialog itself does open fine inside the displayed device delegate and I can use it, the problem is I cannot access the associated model data (e.g. the time I set in the timer).

    Is there no way to access the model data from outside the delegate? What would be the better way of going about this?

    The following code illustrates my problem:

    main.qml

    import QtQuick 2.7
    import QtQuick.Controls 2.4
    import QtQuick.Layouts 1.11
    import QtQuick.Window 2.11
    
    Window {
        width: 640
        height: 480
        visible: true
        title: qsTr("Hello World")
    
        SwipeView {
            id: view
            currentIndex: 0
            anchors.fill: parent
            Item {
                id: firstPage
                    ListView {
                       id: plugListView
                       model: PlugModel {}
                       delegate: PlugDelegate {}
                       anchors.fill: parent
                       }
                    PlugModel {
                        id: plugModel
                    }
                    PlugDialog {
                       id: plugDialog
                       x: Math.round((parent.width - width) / 2)
                       y: Math.round((parent.height - height) / 2)
                       plugModel: plugListView.model
                    }
                    RoundButton {
                        id: addplugButton
                        text: "+"
                        anchors.bottom: parent.bottom
                        anchors.bottomMargin: 16
                        anchors.horizontalCenter: parent.horizontalCenter
                        onClicked: plugDialog.open()
                       }
                    TimerDialog {
                        id: timerDialog
                        x: Math.round((parent.width - width) / 2)
                        y: Math.round((parent.height - height) / 2)
                        plugModel: plugModel
                    }
         }
       }
    }
    

    PlugDelegate.qml

    import QtQuick 2.9
    import QtQuick.Controls 2.4
    import QtQuick.Layouts 1.11
    
    ItemDelegate {
        id: root
        width: parent.width
        checkable: true
        onClicked: ListView.view.currentIndex = index
    
                 Label {
                     id: nameLabel
                     font.pixelSize: Qt.application.font.pixelSize * 2
                     text: model.name
                    }
                 Button {
                     id: alarmButton
                     text: qsTr("Set timer")
                     width: 40
                     height: 20
                     visible: root.checked
                     onClicked:  timerDialog.open()
                 }
      }
    

    PlugDialog.qml

    import QtQuick 2.11
    import QtQuick.Controls 2.4
    import QtQuick.Layouts 1.11
    import QtQuick.Window 2.11
    
    Dialog {
        id: plugDialog
        title: "Add new plug"
        width: 200
        height: 200
        modal: true
        standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
    
        property PlugModel plugModel
    
        TextField {
            Layout.fillWidth: true
            anchors.left: parent.left
            id: plugDescriptionTextField
            width: 150
            placeholderText: qsTr("Enter plug name...")
            cursorVisible: true
            visible: plugModel.checked
            text: PlugModel.name
            onTextEdited: PlugModel.name = text
        }
        TextField {
            Layout.fillWidth: true
            anchors.top: plugDescriptionTextField.bottom
            id: plugIpAdrTextField
            width: 150
            placeholderText: qsTr("Enter plug IpAdr...")
            cursorVisible: true
            visible: PlugModel.checked
            text: PlugModel.ipadr
            onTextEdited: PlugModel.ipadr = text
        }
        onAccepted: {
               plugModel.append({
               "name": plugDescriptionTextField.text,
               "ipadr": plugIpAdrTextField.text,
               "timerduration": 0
            })
    
        }
        onRejected: plugDialog.close()
    }
    

    PlugModel.qml

    import QtQuick 2.13
    
    ListModel {
        id: plugModel
        ListElement {
            name: "Test plug"
            ipadr: "192.168.1.1"
            timerduration: 12
        }
    }
    

    TimerDialog.qml

    import QtQuick 2.11
    import QtQuick.Controls 2.4
    import QtQuick.Layouts 1.11
    import QtQuick.Window 2.11
    
    Dialog {
        id: timerDialog
        title: "Set new timer"
        modal: true
        standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
    
        property PlugModel plugModel
    
        function formatNumber(number) {
            return number < 10 && number >= 0 ? "0" + number : number.toString()
        }
        onAccepted: {
                var timer = hoursTumbler.currentIndex * 3600 + minutesTumbler.currentIndex * 60 + secondsTumbler.currentIndex +1
                PlugModel.timerduration = timer
                var ip = plugModel.currentItem.ipadr
                console.log(PlugModel.timerduration)
                }
        onRejected: timerDialog.close()
        RowLayout {
            id: rowTumbler
            Tumbler {
                id: hoursTumbler
                model: 24
                delegate: TumblerDelegate {
                    text: formatNumber(modelData)
                }
            }
            Tumbler {
                id: minutesTumbler
                model: 60
                delegate: TumblerDelegate {
                    text: formatNumber(modelData)
                }
            }
            Tumbler {
                id: secondsTumbler
                model: 60
                delegate: TumblerDelegate {
                    text: formatNumber(modelData)
                }
            }
        }
    }
    

    TumblerDelegate.qml

    import QtQuick 2.11
    import QtQuick.Controls 2.4
    import QtQuick.Controls.Material 2.4
    
    Text {
        text: modelData
        color: Tumbler.tumbler.Material.foreground
        font: Tumbler.tumbler.font
        opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
    }
    

    After clicking on the device you can open the dialog to set a timer. Accepting the timer dialog always yields some form of "Cannot read property x of undefined"/Unable to assign undefined to QString etc.. I have tried accessing the model data via PlugModel, plugModel, plugListView.model etc.

    Thanks for the help.

    sierdzioS 1 Reply Last reply
    0
    • F FrecciaGLT

      Hello everyone,

      I am currently using a ListView to display data about a type of smart plug. The data I get from the plug is stored inside the associated ListModel.
      I can access the model data from inside the ListViews delegate.

      Now here is my problem: Inside of the delegate I have a button that opens a dialog to set a timer. The dialog itself does open fine inside the displayed device delegate and I can use it, the problem is I cannot access the associated model data (e.g. the time I set in the timer).

      Is there no way to access the model data from outside the delegate? What would be the better way of going about this?

      The following code illustrates my problem:

      main.qml

      import QtQuick 2.7
      import QtQuick.Controls 2.4
      import QtQuick.Layouts 1.11
      import QtQuick.Window 2.11
      
      Window {
          width: 640
          height: 480
          visible: true
          title: qsTr("Hello World")
      
          SwipeView {
              id: view
              currentIndex: 0
              anchors.fill: parent
              Item {
                  id: firstPage
                      ListView {
                         id: plugListView
                         model: PlugModel {}
                         delegate: PlugDelegate {}
                         anchors.fill: parent
                         }
                      PlugModel {
                          id: plugModel
                      }
                      PlugDialog {
                         id: plugDialog
                         x: Math.round((parent.width - width) / 2)
                         y: Math.round((parent.height - height) / 2)
                         plugModel: plugListView.model
                      }
                      RoundButton {
                          id: addplugButton
                          text: "+"
                          anchors.bottom: parent.bottom
                          anchors.bottomMargin: 16
                          anchors.horizontalCenter: parent.horizontalCenter
                          onClicked: plugDialog.open()
                         }
                      TimerDialog {
                          id: timerDialog
                          x: Math.round((parent.width - width) / 2)
                          y: Math.round((parent.height - height) / 2)
                          plugModel: plugModel
                      }
           }
         }
      }
      

      PlugDelegate.qml

      import QtQuick 2.9
      import QtQuick.Controls 2.4
      import QtQuick.Layouts 1.11
      
      ItemDelegate {
          id: root
          width: parent.width
          checkable: true
          onClicked: ListView.view.currentIndex = index
      
                   Label {
                       id: nameLabel
                       font.pixelSize: Qt.application.font.pixelSize * 2
                       text: model.name
                      }
                   Button {
                       id: alarmButton
                       text: qsTr("Set timer")
                       width: 40
                       height: 20
                       visible: root.checked
                       onClicked:  timerDialog.open()
                   }
        }
      

      PlugDialog.qml

      import QtQuick 2.11
      import QtQuick.Controls 2.4
      import QtQuick.Layouts 1.11
      import QtQuick.Window 2.11
      
      Dialog {
          id: plugDialog
          title: "Add new plug"
          width: 200
          height: 200
          modal: true
          standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
      
          property PlugModel plugModel
      
          TextField {
              Layout.fillWidth: true
              anchors.left: parent.left
              id: plugDescriptionTextField
              width: 150
              placeholderText: qsTr("Enter plug name...")
              cursorVisible: true
              visible: plugModel.checked
              text: PlugModel.name
              onTextEdited: PlugModel.name = text
          }
          TextField {
              Layout.fillWidth: true
              anchors.top: plugDescriptionTextField.bottom
              id: plugIpAdrTextField
              width: 150
              placeholderText: qsTr("Enter plug IpAdr...")
              cursorVisible: true
              visible: PlugModel.checked
              text: PlugModel.ipadr
              onTextEdited: PlugModel.ipadr = text
          }
          onAccepted: {
                 plugModel.append({
                 "name": plugDescriptionTextField.text,
                 "ipadr": plugIpAdrTextField.text,
                 "timerduration": 0
              })
      
          }
          onRejected: plugDialog.close()
      }
      

      PlugModel.qml

      import QtQuick 2.13
      
      ListModel {
          id: plugModel
          ListElement {
              name: "Test plug"
              ipadr: "192.168.1.1"
              timerduration: 12
          }
      }
      

      TimerDialog.qml

      import QtQuick 2.11
      import QtQuick.Controls 2.4
      import QtQuick.Layouts 1.11
      import QtQuick.Window 2.11
      
      Dialog {
          id: timerDialog
          title: "Set new timer"
          modal: true
          standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
      
          property PlugModel plugModel
      
          function formatNumber(number) {
              return number < 10 && number >= 0 ? "0" + number : number.toString()
          }
          onAccepted: {
                  var timer = hoursTumbler.currentIndex * 3600 + minutesTumbler.currentIndex * 60 + secondsTumbler.currentIndex +1
                  PlugModel.timerduration = timer
                  var ip = plugModel.currentItem.ipadr
                  console.log(PlugModel.timerduration)
                  }
          onRejected: timerDialog.close()
          RowLayout {
              id: rowTumbler
              Tumbler {
                  id: hoursTumbler
                  model: 24
                  delegate: TumblerDelegate {
                      text: formatNumber(modelData)
                  }
              }
              Tumbler {
                  id: minutesTumbler
                  model: 60
                  delegate: TumblerDelegate {
                      text: formatNumber(modelData)
                  }
              }
              Tumbler {
                  id: secondsTumbler
                  model: 60
                  delegate: TumblerDelegate {
                      text: formatNumber(modelData)
                  }
              }
          }
      }
      

      TumblerDelegate.qml

      import QtQuick 2.11
      import QtQuick.Controls 2.4
      import QtQuick.Controls.Material 2.4
      
      Text {
          text: modelData
          color: Tumbler.tumbler.Material.foreground
          font: Tumbler.tumbler.font
          opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
          horizontalAlignment: Text.AlignHCenter
          verticalAlignment: Text.AlignVCenter
      }
      

      After clicking on the device you can open the dialog to set a timer. Accepting the timer dialog always yields some form of "Cannot read property x of undefined"/Unable to assign undefined to QString etc.. I have tried accessing the model data via PlugModel, plugModel, plugListView.model etc.

      Thanks for the help.

      sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      First: when reporting a problem, please try to condense it into a minimal amount of code and text that describes it. It is hard to get through all this and reason about it. And it is even harder when one realizes most of this code does not matter for the issue at hand.

      @FrecciaGLT said in Cant access model data from dialog:

      [...]
      property PlugModel plugModel
      [...]
      After clicking on the device you can open the dialog to set a timer. Accepting the timer dialog always yields some form of "Cannot read property x of undefined"/Unable to assign undefined to QString etc.. I have tried accessing the model data via PlugModel, plugModel, plugListView.model etc.

      I think you may be mixing up 2 ideas: model and view. You are passing the model to your dialog, but model by itself does not know anything about currently selected index in a particular view. Model is there to serve (and manipulate) data, it can handle multiple views at once etc. It has no idea which index is "current". The view knows which index is current or selected.

      So, you can get out of this problem in several ways:

      • pass index to your dialog before (or while) you are opening it. Then the dialog can operate on your model using this index (using data() and setData() methods of the model)
      • if your model items are QObjects, you can just pass the data object instead, and operate directly on it

      (Z(:^

      1 Reply Last reply
      1
      • F Offline
        F Offline
        FrecciaGLT
        wrote on last edited by
        #3

        @sierdzio
        Thank you for your answer, that gave me the nudge in the right direction.
        I managed to access the data via

        plugModel.get(plugListView.currentIndex).timerduration
        

        I'll keep the code condensed in future posts, thank you.

        1 Reply Last reply
        1
        • sierdzioS Offline
          sierdzioS Offline
          sierdzio
          Moderators
          wrote on last edited by
          #4

          Nice, thanks for posting the solution, it might help others, too!

          (Z(:^

          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