Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Accessing QAbstractListModel's Data Through Properties In QML



  • I have a custom c++ class CustomListModel that extends QAbstractListModel. I am looking for a way to access data for an item in that model through properties in QML.

    In QML I have the following:

    CustomListModel { //Contains people information
      id: customDataModel
    }
    
    Text {
      id: nameLabel
    }
    

    To set the label's text to the first person in the CustomListModel, I could do something like the following which uses the "data" method of CustomListModel requiring specifying the index and role:

    Button {
      id: personOneButton
      text: "Show Person One"
    
      onClicked: {
         var sourceIndex = customDataModel.index(0,0)
         nameLabel.text = customDataModel.data(sourceIndex,  customDataModel.roleName("name"))
      }
    }
    

    Instead I would like to bind the label text to a specific item in the CustomListModel. The following is an example of a simpler interface I'd like to have.

    function getDataItem(){ //todo }
    property var currentDataItem //object of unknown type acting as proxy to a item in the model
    
    Button {
    id: personOneButton
    text: "Show Person One"
      onClicked: {
        var sourceIndex =  customDataModel.index(0,0)
        currentDataItem = getDataItem(customDataModel, sourceIndex)
      }
    }
    
    Text {
      id: nameLabel
      text: currentDataItem.name //the target interface to achieve
    }
    

    Is there any existing functionality in Qt that has the functionality of this "currentDataItem"? Or some other mechanism for binding to an item's roles.

    The only existing functionality I'm aware of that makes these role properties available is when using a GridView's delegate https://doc.qt.io/qt-5/qml-qtquick-gridview.html#delegate-prop. Within that GridView's delegate there is a "model" property of type "QQmlDMAbstractItemModelData” which allows for reading and writing to a role with the syntax "model.name".



  • Hello,

    I think you may use a .json file to get the properties from the model or a listView and assign the model to the listView.



  • You use a view of the needed type. Then the items exposed by the different roles are available to delegates. You use a redefined data/setData to read the write to those roles. Search for QML model view objects available to QML.



  • Is there a QML view object that can be used for showing detailed information of a single item within a model? The only views I'm aware of are GridView, ListView, TableView, and PathView. These seem to be primary for visualizing the entire set or subset of the items in a model.

    The high level problem I'm trying to address is the following:
    I have a source model(QAbstractListModel), a filter model(QSortFilterProxyModel) used to show only items matching a criteria, and a gridview and listview for displaying a list of items in the filter model. When an item in the gridview/listview is clicked on, the delegate's "model" property for that gridview item is being passed to another qml item that is used for displaying detailed information and editing that item's data in the model. The problem is that if that gridview item is filtered out while displaying/using the delegate's property, the property is destroyed in the detail information qml item even though the item still exists in the source model. Is there another way do this or best practice to display/edit a single item within a source model?

    Ideally, I would like to just create a delegate to an item in a model without having to use a view. Is that possible?



  • @qtyler
    You might be able to do something like that with an Instantiator. The problem is it doesn't seem to have a concept of a currentItem like a ListView does. Maybe a visible and separate ListView that only shows the item pointed by its current index.



  • I'm not sure how I would use an Instanitator. My guess is that if I created an Instanitator tied to a source model, it would then create a delegate for every item in the model. I don't know if it would be possible to have it create only one delegate for one item in the model or if the object returned by objectAt would provide property bindings to all of the roles for an item in the model.

    A second listview with only one item visible at a time might work but might be inefficient.

    Could the DelegateModel type be used in some way to get an object with property bindings to an item in a model without using a view?



  • @qtyler said in Accessing QAbstractListModel's Data Through Properties In QML:

    Could the DelegateModel type be used in some way to get an object with property bindings to an item in a model without using a view?

    It might. You can specify the index for the item, but I am not sure if it would look for children of the index or not. So it might not work as expected.

    How big is your list? Can you filter it to a sublist? If you try the ListView route you could track what it accesses out of the data() function by printing something to console. You could also delay load things using a loader keyed off selection criteria. Not sure how well it would see the roles from the model. Might be tricky.


Log in to reply