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

How to export complex C++ data to qml



  • I'm trying to export from c++ into qml a c++ class that has QList<QObject *> to other classes. I've registered all of the classes, but I haven't been able to figure out how to tell qml what type of object the QList<QObject *> points to.

    I use a xxx.rootContext()->setContextProperty() call to tell qml about the top level object structure, but I don't know how to tell qml what the QList<QObject *>'s point to (if there is a way).

    I need to pass the QList<QObject *>'s to other QtQuick display elements as models.

    In a straight c++ description what I'm trying to pass along looks like:

    class class_a {
    QString name_a;
    int num_a;
    int num_b;
    }
    class class_b {
    QString name_b;
    int num_x;
    int numY;
    }

    class class_C {
    QString name_c;
    int num_a;
    int num_b;
    class_a a_array[];
    class_b b_array[];
    }

    In the QML'd version I have:

    class class_C {
    Q_OBJECT

    Q_PROPERTY(QString nodeName READ nodeName)
    Q_PROPERTY(int numA READ numA)
    Q_PROPERTY(int numB READ numB)

    Q_PROPERTY(QList<QObject*> class_a)
    Q_PROPERTY(QList<QObject*> class_b)

    ...
    }

    then in main:

    qmlRegisterUncreatableType<class_a>("Class_a", 1, 0, "Class_a",
    QStringLiteral("CanNodeInfo should not be created in QML."));
    qmlRegisterUncreatableType<class_b>("Class_b", 1, 0, "Class_c",
    QStringLiteral("CanNodeInfo should not be created in QML."));
    qmlRegisterUncreatableType<class_C>("Class_c", 1, 0, "Class_c",
    QStringLiteral("CanNodeInfo should not be created in QML."));

    and:

    engine.rootContext()->setContextProperty(QStringLiteral("class_c_List"), QVariant::fromValue(Cpp2QmlInterfaceClass::getClassC()));

    This has allowed me to access the members of Class c in qml, but (as I have said) I don't see any way to tell qml what the QList<QObject *>'s point to.

    Am I missing something, and if so can someone point me to the relevant documentation? Or is this just something that qml can't do yet (or maybe ever)?

    How have others handled complex nested data structures?

    Regards,
    Greg


  • Lifetime Qt Champion

    @GregWilsonLindberg said in How to export complex C++ data to qml:

    QList<QObject*> class_a

    Why not

    QList<class_a*> classA;
    

    ?
    Why do you want to use QObject*?
    class_a and class_b do not even inherit from QObject...



  • I'm sorry, jsulm, I messed up on my example, class_a & class_b do inherit from Q_OBJECT.

    As to why I don't use the class names directly, I hadn't thought about that, all of the examples and descriptions that I have been able to find show using <QObject *>. Using the class does make more sense, I will try that.

    Thanks,
    Greg



  • Ok, I changed the definition and all accesses to class * from QObject *. I still can't access the lists.
    The actual Q_PROPERTY now is:
    Q_PROPERTY(QList<class_a *> a_array)

    On the qml side, if I say:

    print(class_c.a_array);

    I get 'a_array undefined'.

    Has anyone had any experience passing complex data types into qml?



  • Create a small side project of working code that illustrates this problem and post it here. Its really hard to tell what is wrong without that.


  • Qt Champions 2018

    Qt Quick views can't handle QList<Foo*> even if Foo inherits from QObject.
    You have to expose QList<QObject*> or a proper QAbstractListModel.


  • Lifetime Qt Champion

    @GrecKo So, I was wrong with my suggestion to use QList<Foo*> instead of QList<QObject*>? :-)
    I'm not a QML expert.
    @GregWilsonLindberg looks like my suggestion was wrong, sorry.



  • @GrecKo So, the example that I have found has only one list of items in it.

    The data model that I have has a top level list (this I have working, accessed as an array), and each if these top level elements have several lists.

    If I implement the top level as an abstract item model then I would need to have several of the data roles return abstract item models. This is the part that I am not understanding.

    If you look back to my first post, I have an array of the class_C items, and each of those has arrays of class_a & class_b items. I am accessing all of the simple elements of the class_C items, but when it comes to the internal arrays of class_a & class_b and even strings in a QStringList, I can't access any of the sub elements.

    I created a project that shows what I'm trying to do with the <foo*> notation, while this is incorrect, it does show what is not working.

    It is available at:
    https://pastebin.com/mRMwFC0A

    While it is not surprising that I can't access the structure arrays contained in the top level array, I can't even access the QStringList elements. I just get 0 for the length of the QStringList on the qml side.

    I will be wanting to use the embedded class arrays as models for other QtQuick elements.

    Hope this clears up some more of what I'm trying to do. I'm going to do some more research on QAbstractItmeModels.

    Thanks,
    Greg



  • In pouring over my code and trying different things I noticed a warning, not an error, that said that I was missing the READ routine for one of my Q_PROPERTY's. And I had included that error in the code example that I put into my first post.

    I added those in and everything started to work correctly.

    So, at this point I can access all of the properties in my top level data element and I can also access the properties in the included QList's.

    Thanks for the suggestions and insights,
    Greg


Log in to reply