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. issue with Custom type to use it as a value property and to receive it from a C++ method...
Forum Update on Monday, May 27th 2025

issue with Custom type to use it as a value property and to receive it from a C++ method...

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
6 Posts 3 Posters 773 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.
  • mbruelM Offline
    mbruelM Offline
    mbruel
    wrote on last edited by
    #1

    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 a ModelId in seed_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 used previousIndex 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 a ModelId
    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 be print("[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?

    1 Reply Last reply
    0
    • IntruderExcluderI Offline
      IntruderExcluderI Offline
      IntruderExcluder
      wrote on last edited by
      #2

      You need to pass yor ModelId object as Qbject*, but your method objId() returns copy of ModelId which is inherited from QObject. You can change your function to return pointer to your member and then use something like return 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 your QObject* with gc call which can lead to double free of same pointer. To make it proper see data ownership in Qt.

      mbruelM 1 Reply Last reply
      0
      • IntruderExcluderI IntruderExcluder

        You need to pass yor ModelId object as Qbject*, but your method objId() returns copy of ModelId which is inherited from QObject. You can change your function to return pointer to your member and then use something like return 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 your QObject* with gc call which can lead to double free of same pointer. To make it proper see data ownership in Qt.

        mbruelM Offline
        mbruelM Offline
        mbruel
        wrote on last edited by mbruel
        #3

        @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 my ModelIds as I want to keep them on the stack and don't want to make their ModelObject real owner derived from QObject...

        1 Reply Last reply
        0
        • mbruelM Offline
          mbruelM Offline
          mbruel
          wrote on last edited by
          #4

          so it seems we need to use pointers on custom types to use them as QML property.
          it is kind of working to exchange custom types by value between C++ and QML but we can't use their methods in QML...
          good to know...

          1 Reply Last reply
          0
          • GrecKoG Offline
            GrecKoG Offline
            GrecKo
            Qt Champions 2018
            wrote on last edited by
            #5

            If you want to use value semantics, don't inherit from QObject and use Q_GADGET instead of Q_OBJECT.

            mbruelM 1 Reply Last reply
            0
            • GrecKoG GrecKo

              If you want to use value semantics, don't inherit from QObject and use Q_GADGET instead of Q_OBJECT.

              mbruelM Offline
              mbruelM Offline
              mbruel
              wrote on last edited by mbruel
              #6

              @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 using Q_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 from QObject and use Q_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?

              1 Reply Last reply
              0

              • Login

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