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

How to get the return value of a function of a QAbstractItemModelReplica from qml



  • I have some problems to get the return value, e.g. of the function headerData, of a QAbstractItemModelReplica in qml.

    // QML
    TabBar {
        id: tabBar
        width: parent.width
        Repeater {
            model: client.modelCount
            TabButton {
                text: client.listModels[index].headerData(0,0,0) // <-- always undefined
            }
        }
    }
    
    // Client header
    class Client : public QObject {
        Q_OBJECT
        // QVariantList contains QVariants of QAbstractItemModelReplica*
        Q_PROPERTY(QVariantList listModels READ listModels NOTIFY listModelsChanged)
        Q_PROPERTY(int modelCount READ modelCount NOTIFY modelCountChanged)
    ...
    

    The return value of headerData() is always undefined. The corresponding headerData() function in the source model is called, but because of the client server communication, the response takes a while.

    Does anyone know how to get notified when the response arrived?


  • Qt Champions 2018

    headerData parameters are int section, Qt::Orientation orientation, int role.
    0 is not a correct value for the orientation, you should pass Qt.Horizontal or Qt.Vertical.
    Do you know for sure that your model has header data for the display role (role value of 0)? If that's the case, using Qt.DisplayRole for the third parameter instead of 0 would help with the readability.

    What text are you trying to display on your tab button? Does your model only have one column?

    We'll deal with the asynchronous problem in a second time.



  • This post is deleted!


  • Thank for the fast answer.

    The headerData call now look like this:

    text: client.listModels[index].headerData(0, Qt.Horizontal, Qt.DisplayRole)
    

    My implementaion of the headerData function in my source model looks like this and is also called and returns m_tabName.

    QVariant MyListModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
        if (section != 0)
            return {};
        
        if (role != Qt::DisplayRole)
            return {};
        
        return m_tabName;
    }
    

    Yes every model (QAbstractListModel) represents a column or more precisely the content of a tab. The property client.listModels returns for every tab a model. And the headerData should contain the tab name.


  • Qt Champions 2018

    Ok.

    The easiest (but ugliest way) would be to listen for the headerDataChanged signal of the replica model.

    Something like this :

    TabButton {
        id: modelTabButton
        readonly property var model: client.listModels[index]
        property var dummyHeaderProp
        text: { dummyHeaderProp; return model.headerData(0,0,0) }
        Connections {
            target: modelTabButton.button
            onHeaderDataChanged: modelTabButton.dummyHeaderPropChanged() // this will force the re-evaluation of the text binding
        }
    }
    

    Another solution would be to use an helper class to do that, I wrote an helper class to retrieve model informations but I didn't implement header stuff : https://github.com/oKcerG/QmlModelHelper
    You could inspire you from it or add the missing functionnality to it (shouldn't be too hard).

    The syntax could then be: text: model.ModelHelper.columnHeaders[0].display ( I guess notifying that the entire columnHeaders property has changed when receiving headerDataChanged for only one column is ok).

    ps: Why don't use client.listModels as your Repeater's model ?



  • Thank you very much, that helped me a lot. You're right, the solution is very ugly but I found a more beautiful way.

    TabBar {
        id: tabBar
        width: parent.width
        Repeater {
            model: client.listModels
            TabButton {
                text: modelData.headerData(0, Qt.Horizontal, Qt.DisplayRole)
                Connections {
                    target: modelData
                    onHeaderDataChanged: {
                        text = modelData.headerData(0, Qt.Horizontal, Qt.DisplayRole)
                    }
                }
            }
        }
    }
    

Log in to reply