issue with Custom type to use it as a value property and to receive it from a C++ method...
-
Hi,
I've created ModelId to be used in both my C++ and QML.My goal was to use it in models
QAbstractListModel
cf VarietyModel2::data, using this method.It is working but I've two issues in my Delegate:
My Delegate is getting aModelId
inseed_company_id
from the model.1.: I'd like to use it as a property of a Combobox and I'm getting this error:
qrc:/qml/SettingsVarietyDelegate.qml:73:21: Unable to assign ModelId to ModelId*
So a property on a custom type has to be a pointer? can't we use it as a value? What solution would I have?
In this particular example I've usedpreviousIndex
int variable but I guess this trick won't always work...2.: it seems QML gets
QVariant<ModelId>
from the return of a C++ method instead of directly aModelId
In this piece of code:onCurrentIndexChanged: { if (!initialized) return; let newCompanyId = cppFamily.seedCompanyIdFromProxyRow(currentIndex); let currentCompanyId = cppFamily.seedCompanyIdFromProxyRow(previousIndex) print("[MB_TRACE][seedCompanyField] newCompanyId: " + newCompanyId); print("[MB_TRACE][seedCompanyField] currentCompanyId: " + currentCompanyId) if (currentCompanyId !== newCompanyId) cppFamily.updateVarietyCompanySeed(varietyModel.sourceRow(index), crop_id, variety_id, currentCompanyId, newCompanyId); previousIndex = currentIndex; }
seedCompanyIdFromProxyRow returns a
ModelId
(from C++) but here is the print result:qml: [MB_TRACE][seedCompanyField] newCompanyId: QVariant(ModelId) qml: [MB_TRACE][seedCompanyField] currentCompanyId: QVariant(ModelId)
And I'm not able to use any
ModelId
methods like ModelId::str() to be able to print the value.
If I update the log to beprint("[MB_TRACE][seedCompanyField] newCompanyId: " + newCompanyId.str());
Then I'm getting this error:qrc:/qml/SettingsVarietyDelegate.qml:95: TypeError: Property 'str' of object QVariant(ModelId) is not a function
Why is that? How can I access the methods of my object? -
You need to pass yor
ModelId
object asQbject*
, but your methodobjId()
returns copy ofModelId
which is inherited fromQObject
. You can change your function to return pointer to your member and then use something likereturn QVariant::fromValue(qobject_cast<QObject*>(ur_ptr));
in your model.
But keep in mind that you need proper memory management in this case: QML may delete yourQObject*
with gc call which can lead to double free of same pointer. To make it proper see data ownership in Qt. -
You need to pass yor
ModelId
object asQbject*
, but your methodobjId()
returns copy ofModelId
which is inherited fromQObject
. You can change your function to return pointer to your member and then use something likereturn QVariant::fromValue(qobject_cast<QObject*>(ur_ptr));
in your model.
But keep in mind that you need proper memory management in this case: QML may delete yourQObject*
with gc call which can lead to double free of same pointer. To make it proper see data ownership in Qt.@IntruderExcluder
Yep I came to the same conclusion, we need to use pointers to share custom types... That's quite boring, gonna have to update plenty of methods... I'll give it a try next week.
I know for the ownership. That's quite boring that Qt doesn't provide a Macro (or a way) to use on Custom Types in order to prevent QML to take ownership of any of their instances... This would be really convenient!
But all right, I'll set a C++ fake parent for all myModelIds
as I want to keep them on the stack and don't want to make theirModelObject
real owner derived fromQObject
... -
If you want to use value semantics, don't inherit from QObject and use Q_GADGET instead of Q_OBJECT.
-
If you want to use value semantics, don't inherit from QObject and use Q_GADGET instead of Q_OBJECT.
@GrecKo hum are you sure about that?
I spent the whole day updating my code to use pointers... :'( anyway I will get some advantages doing so, my code will be faster but still...
I kind of doubt that even usingQ_GADGET
I'd be able to use a custom type by value in QML.
Are you sure I'd be able to affect a value to a QML property?Edit: just to check I've made my
ModelId
not inherit fromQObject
and useQ_GADGET
instead.
I'm getting a compilation error on the QML type registration:qmlRegisterType<ModelId>(packageURI, ver.maj, ver.min, "ModelId");
:/opt/Qt/5.12.6/gcc_64/include/QtQml/qqmlprivate.h:106: error: ‘QQmlPrivate::QQmlElement<T>::~QQmlElement() [with T = ModelId]’ marked ‘override’, but does not override In file included from /opt/Qt/5.12.6/gcc_64/include/QtQml/qqml.h:43, from /opt/Qt/5.12.6/gcc_64/include/QtQml/qqmlengine.h:47, from /opt/Qt/5.12.6/gcc_64/include/QtQuick/qquickimageprovider.h:46, from /opt/Qt/5.12.6/gcc_64/include/QtQuick/QQuickImageProvider:1, from /home/bruel/Documents/tieum/myDev/c++/QT/github/qrop/core/qrpimageprovider.h:6, from /home/bruel/Documents/tieum/myDev/c++/QT/github/qrop/desktop/main.cpp:24: /opt/Qt/5.12.6/gcc_64/include/QtQml/qqmlprivate.h: In instantiation of ‘class QQmlPrivate::QQmlElement<ModelId>’: /opt/Qt/5.12.6/gcc_64/include/QtQml/qqmlprivate.h:124:37: required from ‘void QQmlPrivate::createInto(void*) [with T = ModelId]’ /opt/Qt/5.12.6/gcc_64/include/QtQml/qqml.h:287:31: required from ‘int qmlRegisterType(const char*, int, int, const char*) [with T = ModelId]’ /home/bruel/Documents/tieum/myDev/c++/QT/github/qrop/desktop/main.cpp:108:69: required from here /opt/Qt/5.12.6/gcc_64/include/QtQml/qqmlprivate.h:106:9: error: ‘QQmlPrivate::QQmlElement<T>::~QQmlElement() [with T = ModelId]’ marked ‘override’, but does not override ~QQmlElement() override { ^
I believe we need
QObjects
for QML no?