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. how to cause view to update based on model change?

how to cause view to update based on model change?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
31 Posts 8 Posters 3.2k 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.
  • M Offline
    M Offline
    mzimmers
    wrote on 28 Sept 2024, 18:30 last edited by
    #3

    @SGaist that's actually a very good question, and the answer is "no." I thought dataChanged() was only a method of a proper QAbstractItemModel object - my model is just a JS array that is initialized by a call to an invokable function. Do I need to implement my own signal (and handler) for when the list changes?

    1 Reply Last reply
    0
    • A Offline
      A Offline
      ankou29666
      wrote on 28 Sept 2024, 19:37 last edited by
      #4

      if your data structure changes outside of the model, then your data has to emit a signal to the model, that the model itself will have to relay to the view. Assuming that the datastructure is a QObject derivative that can emit signals, which is probably not your case.

      With data not being a QObject, I would add a method to the model that would emit the signal. This method would have to be called upon any single data update

      If your data changes outside of the model, the model has to be notified of that change so that it can transmit to (the cascade of proxies if ever relevant and to) the view.

      M 1 Reply Last reply 28 Sept 2024, 21:15
      0
      • A ankou29666
        28 Sept 2024, 19:37

        if your data structure changes outside of the model, then your data has to emit a signal to the model, that the model itself will have to relay to the view. Assuming that the datastructure is a QObject derivative that can emit signals, which is probably not your case.

        With data not being a QObject, I would add a method to the model that would emit the signal. This method would have to be called upon any single data update

        If your data changes outside of the model, the model has to be notified of that change so that it can transmit to (the cascade of proxies if ever relevant and to) the view.

        M Offline
        M Offline
        mzimmers
        wrote on 28 Sept 2024, 21:15 last edited by
        #5

        @ankou29666 said in how to cause view to update based on model change?:

        With data not being a QObject, I would add a method to the model that would emit the signal.

        My model is a simple JS array. How does an array emit a signal?

        J A 2 Replies Last reply 28 Sept 2024, 21:39
        0
        • M mzimmers
          28 Sept 2024, 21:15

          @ankou29666 said in how to cause view to update based on model change?:

          With data not being a QObject, I would add a method to the model that would emit the signal.

          My model is a simple JS array. How does an array emit a signal?

          J Offline
          J Offline
          JoeCFD
          wrote on 28 Sept 2024, 21:39 last edited by JoeCFD
          #6
          This post is deleted!
          M 1 Reply Last reply 28 Sept 2024, 21:52
          0
          • J JoeCFD
            28 Sept 2024, 21:39

            This post is deleted!

            M Offline
            M Offline
            mzimmers
            wrote on 28 Sept 2024, 21:52 last edited by
            #7

            @JoeCFD that works for a C++ model, but in this instance, my model is just a JS array of strings. I don't have the context from which to make any of those calls.

            J 1 Reply Last reply 28 Sept 2024, 22:09
            0
            • M mzimmers
              28 Sept 2024, 21:52

              @JoeCFD that works for a C++ model, but in this instance, my model is just a JS array of strings. I don't have the context from which to make any of those calls.

              J Offline
              J Offline
              JoeCFD
              wrote on 28 Sept 2024, 22:09 last edited by
              #8

              @mzimmers Sorry my bad.

              1 Reply Last reply
              1
              • M mzimmers
                28 Sept 2024, 21:15

                @ankou29666 said in how to cause view to update based on model change?:

                With data not being a QObject, I would add a method to the model that would emit the signal.

                My model is a simple JS array. How does an array emit a signal?

                A Offline
                A Offline
                ankou29666
                wrote on 29 Sept 2024, 07:48 last edited by ankou29666
                #9

                @mzimmers said in how to cause view to update based on model change?:

                @ankou29666 said in how to cause view to update based on model change?:

                With data not being a QObject, I would add a method to the model that would emit the signal.

                My model is a simple JS array. How does an array emit a signal?

                As I said, you create a method in your model

                Item
                {
                    ListModel
                    {
                        id: yourListModel
                
                        function emitSignal ()
                        {
                             emit dataChanged ;
                        }
                    }
                }
                

                and you ensure that any modification to the data is followed by a call to this method.

                This is basically what I did by the past (but in C++ not in QML).
                but in the future, in order to make it fool proof, I would rather put the data structure as protected or private member of the model, such that any change that has been made outside of the views has to be done through public accessors of the model, that automatically trigger the appropriate signals.

                J 1 Reply Last reply 29 Sept 2024, 08:50
                0
                • A ankou29666
                  29 Sept 2024, 07:48

                  @mzimmers said in how to cause view to update based on model change?:

                  @ankou29666 said in how to cause view to update based on model change?:

                  With data not being a QObject, I would add a method to the model that would emit the signal.

                  My model is a simple JS array. How does an array emit a signal?

                  As I said, you create a method in your model

                  Item
                  {
                      ListModel
                      {
                          id: yourListModel
                  
                          function emitSignal ()
                          {
                               emit dataChanged ;
                          }
                      }
                  }
                  

                  and you ensure that any modification to the data is followed by a call to this method.

                  This is basically what I did by the past (but in C++ not in QML).
                  but in the future, in order to make it fool proof, I would rather put the data structure as protected or private member of the model, such that any change that has been made outside of the views has to be done through public accessors of the model, that automatically trigger the appropriate signals.

                  J Offline
                  J Offline
                  JonB
                  wrote on 29 Sept 2024, 08:50 last edited by JonB
                  #10

                  @ankou29666 , @mzimmers
                  I know nothing about QML! But I don't think emit will work from JavaScript, it's #defined to empty in C++? My guess would be you need to write just dataChanged(...) or maybe yourListModel.dataChanged(...)?

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    ankou29666
                    wrote on 29 Sept 2024, 09:26 last edited by
                    #11

                    not impossible, I had made a little pause with Qt and currently rather working on the UI than the code, so it's far from impossible that I make a few bullshits in my code snippets.

                    1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      mzimmers
                      wrote on 29 Sept 2024, 14:25 last edited by
                      #12

                      There's still something missing here -- again, my model isn't a QML list model; it's a simple JS array. According to the docs, this is a valid model. What the docs don't say, though (at least nowhere that I can find), is how such a model can generate a signal to update the view. Maybe this can't be done from an array model, but I imagine that somehow, I can effect the same thing.

                      J 1 Reply Last reply 29 Sept 2024, 16:26
                      0
                      • A Offline
                        A Offline
                        ankou29666
                        wrote on 29 Sept 2024, 14:35 last edited by
                        #13

                        I would rather formulate it this way : the doc doesn't say that such JS array data doesn't update the underlying Qt model, if any, and thus, the Qt views.

                        1 Reply Last reply
                        0
                        • M mzimmers
                          29 Sept 2024, 14:25

                          There's still something missing here -- again, my model isn't a QML list model; it's a simple JS array. According to the docs, this is a valid model. What the docs don't say, though (at least nowhere that I can find), is how such a model can generate a signal to update the view. Maybe this can't be done from an array model, but I imagine that somehow, I can effect the same thing.

                          J Offline
                          J Offline
                          JonB
                          wrote on 29 Sept 2024, 16:26 last edited by JonB
                          #14

                          @mzimmers
                          Yes, a JSON array is not going to be able to emit a signal. What is the problem with calling dataChanged() per above whenever you change existing data the underlying JS array? I mean even if we were in C++ and I altered an array or vector or QList or whatever was my model's actual data I would still have to emit dataChanged() explicitly correspondingly.

                          1 Reply Last reply
                          0
                          • M mzimmers
                            28 Sept 2024, 18:01

                            Hi all -

                            In this code:

                            ListView {
                                model: spaceProxyModel
                                delegate: GridView {
                                    required property Space space
                                    property var spaceFeatureList: 
                                        sceneModel.featureUuidList(false, space.uuid) // from a C++ function
                                    model: spaceFeatureList
                                    delegate: Item {
                                        ...
                            

                            The property spaceFeatureList gets updated from another screen, but my view doesn't reflect the change to the model (I've confirmed that spaceFeatureList is indeed being changed). What do I need to do to force the view update?

                            Thanks...

                            G Offline
                            G Offline
                            GrecKo
                            Qt Champions 2018
                            wrote on 29 Sept 2024, 23:00 last edited by
                            #15

                            Forget the dataChanged() discussion, it is not relevant here as you realized since no QAIM is involved.
                            @mzimmers said in how to cause view to update based on model change?:

                            The property spaceFeatureList gets updated from another screen, but my view doesn't reflect the change to the model (I've confirmed that spaceFeatureList is indeed being changed). What do I need to do to force the view update?

                            Nothing, it is handed automatically if the spaceFeatureList actually changes.
                            Are you sure it does? How did you confirm it?

                            M 1 Reply Last reply 30 Sept 2024, 02:30
                            1
                            • G GrecKo
                              29 Sept 2024, 23:00

                              Forget the dataChanged() discussion, it is not relevant here as you realized since no QAIM is involved.
                              @mzimmers said in how to cause view to update based on model change?:

                              The property spaceFeatureList gets updated from another screen, but my view doesn't reflect the change to the model (I've confirmed that spaceFeatureList is indeed being changed). What do I need to do to force the view update?

                              Nothing, it is handed automatically if the spaceFeatureList actually changes.
                              Are you sure it does? How did you confirm it?

                              M Offline
                              M Offline
                              mzimmers
                              wrote on 30 Sept 2024, 02:30 last edited by
                              #16

                              @GrecKo said in how to cause view to update based on model change?:

                              How did you confirm it?

                              I have a telltale printout.

                              My main QML file is SceneSetup.qml. On a button press, I push another component (SceneFeatureSelect.qml) onto my stack. I pass the model as a required property. When SceneFeatureSelect changes the list (the model) it uses a callback to notify SceneSetup. My printout in SceneSetup confirms the addition to the model, but my GridView doesn't change.

                              1 Reply Last reply
                              0
                              • G Offline
                                G Offline
                                GrecKo
                                Qt Champions 2018
                                wrote on 30 Sept 2024, 07:41 last edited by
                                #17

                                @mzimmers said in how to cause view to update based on model change?:

                                My printout in SceneSetup confirms the addition to the model, but my GridView doesn't change.

                                To which model?
                                That's too abstract for me to make the link with your code.
                                Does or does not the spaceFeatureList get reevaluated with a new value?
                                You didn't confirm it with onSpaceFeatureListChanged: print("space feature list changed" if I understand correctly.

                                In the following code:

                                ListView {
                                    model: spaceProxyModel
                                    delegate: GridView {
                                        required property Space space
                                        property var spaceFeatureList: 
                                            sceneModel.featureUuidList(false, space.uuid)
                                

                                The spaceFeatureList will get reevaluated if you change if sceneModel corresponding NOTIFY signal is emitted or if there's a dataChanged signal for the uuid role of the corresponding row in spaceProxyModel (or for a modelResest or layoutChanged).
                                It also may work if featureUuidList is a function implemented in JS but I doubt that's the case.

                                M 2 Replies Last reply 30 Sept 2024, 11:23
                                0
                                • G GrecKo
                                  30 Sept 2024, 07:41

                                  @mzimmers said in how to cause view to update based on model change?:

                                  My printout in SceneSetup confirms the addition to the model, but my GridView doesn't change.

                                  To which model?
                                  That's too abstract for me to make the link with your code.
                                  Does or does not the spaceFeatureList get reevaluated with a new value?
                                  You didn't confirm it with onSpaceFeatureListChanged: print("space feature list changed" if I understand correctly.

                                  In the following code:

                                  ListView {
                                      model: spaceProxyModel
                                      delegate: GridView {
                                          required property Space space
                                          property var spaceFeatureList: 
                                              sceneModel.featureUuidList(false, space.uuid)
                                  

                                  The spaceFeatureList will get reevaluated if you change if sceneModel corresponding NOTIFY signal is emitted or if there's a dataChanged signal for the uuid role of the corresponding row in spaceProxyModel (or for a modelResest or layoutChanged).
                                  It also may work if featureUuidList is a function implemented in JS but I doubt that's the case.

                                  M Offline
                                  M Offline
                                  mzimmers
                                  wrote on 30 Sept 2024, 11:23 last edited by
                                  #18
                                  This post is deleted!
                                  1 Reply Last reply
                                  0
                                  • G GrecKo
                                    30 Sept 2024, 07:41

                                    @mzimmers said in how to cause view to update based on model change?:

                                    My printout in SceneSetup confirms the addition to the model, but my GridView doesn't change.

                                    To which model?
                                    That's too abstract for me to make the link with your code.
                                    Does or does not the spaceFeatureList get reevaluated with a new value?
                                    You didn't confirm it with onSpaceFeatureListChanged: print("space feature list changed" if I understand correctly.

                                    In the following code:

                                    ListView {
                                        model: spaceProxyModel
                                        delegate: GridView {
                                            required property Space space
                                            property var spaceFeatureList: 
                                                sceneModel.featureUuidList(false, space.uuid)
                                    

                                    The spaceFeatureList will get reevaluated if you change if sceneModel corresponding NOTIFY signal is emitted or if there's a dataChanged signal for the uuid role of the corresponding row in spaceProxyModel (or for a modelResest or layoutChanged).
                                    It also may work if featureUuidList is a function implemented in JS but I doubt that's the case.

                                    M Offline
                                    M Offline
                                    mzimmers
                                    wrote on 30 Sept 2024, 17:02 last edited by
                                    #19

                                    @GrecKo said in how to cause view to update based on model change?:

                                    To which model?
                                    That's too abstract for me to make the link with your code.

                                    Sorry - this is a fairly complicated bit of stuff. Here's a snippet of the relevant code:

                                    Pane {
                                        id: sceneSetupPane
                                        signal featureListChanged(spaceId: string, activityId: string, status: bool)
                                        function changeCallback(spaceId, activityId, status)
                                        {
                                            featureListChanged(spaceId, activityId, status)
                                        }
                                        ListView {
                                            model: spaceProxyModel
                                            delegate: GridView {
                                                required property Space space
                                                property var spaceFeatureList: sceneModel.featureUuidList(false, space.uuid)
                                                model: spaceFeatureList
                                                delegate: Text { text: modelData }
                                    
                                                Connections {
                                                    target: sceneSetupPane
                                                    function onFeatureListChanged(spaceId, activityId, status) {
                                                        if (spaceId.localeCompare(space.uuid) === 0) {
                                                            if (status) {
                                                                if (spaceFeatureList.indexOf(activityId) === -1) {
                                                                    var i = spaceFeatureList.push(activityId)
                                                                }
                                                            } else {
                                                                var j = spaceFeatureList.indexOf(activityId)
                                                                if (j !== -1) {
                                                                    spaceFeatureList.splice(spaceFeatureList.indexOf(activityId), 1)
                                                                }
                                                            }
                                                            console.log("spaceFeatureList is now", spaceFeatureList)
                                                        }
                                                    }
                                                }
                                    

                                    I've verified that the callback is invoked appropriately, all the arguments are good, and the spaceFeatureList is correct after processing. Yet, my view doesn't change.

                                    jeremy_kJ 1 Reply Last reply 3 Oct 2024, 20:56
                                    0
                                    • M Offline
                                      M Offline
                                      mzimmers
                                      wrote on 3 Oct 2024, 04:33 last edited by
                                      #20

                                      BTT: anyone have an idea on this? Thanks...

                                      1 Reply Last reply
                                      0
                                      • F Offline
                                        F Offline
                                        flaudio
                                        wrote on 3 Oct 2024, 13:53 last edited by flaudio 10 Mar 2024, 14:04
                                        #21

                                        Hi @mzimmers,
                                        have you tried to use only the GridView (comment the ListView, in order to reduce the amount of code to test)? I suggest also to add the snippet of the used model (I'm not sure if it is a JS list or a ListModel - the featureUuidList method). And try to add (as @GrecKo suggested) onSpaceFeatureListChanged to understand if the GridView model is changing.

                                        GridView {
                                            required property Space space
                                            property var spaceFeatureList: sceneModel.featureUuidList(false, space.uuid)
                                            model: spaceFeatureList
                                            delegate: Text { text: modelData }
                                            onSpaceFeatureListChanged: {
                                                console.log("model changed!")
                                           }
                                        }
                                        
                                        1 Reply Last reply
                                        0
                                        • M Offline
                                          M Offline
                                          mzimmers
                                          wrote on 3 Oct 2024, 17:53 last edited by
                                          #22

                                          @flaudio featureUuidList is an invokable C++ function. I only use it to initialize my property/model.

                                          I did put the telltale in, and it's not getting hit. Tried it with and without the outer ListView. I'm clearly doing something wrong, because other telltales confirm that the array is indeed getting changed.

                                          1 Reply Last reply
                                          0

                                          12/31

                                          29 Sept 2024, 14:25

                                          • Login

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