Solved 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?
-
headerData
parameters areint section, Qt::Orientation orientation, int role
.
0 is not a correct value for the orientation, you should passQt.Horizontal
orQt.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, usingQt.DisplayRole
for the third parameter instead of0
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.
-
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 entirecolumnHeaders
property has changed when receivingheaderDataChanged
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) } } } } }