[SOLVED] Cascaded QVariantList exposed to QML causes Error: Cannot assign [undefined] to QString



  • Hi All,

    I would need QVariantList for use as model in QML,.

    Q_Property in containing class header is:

     Q_PROPERTY( QVariantList CoatingCurrentCarrierOrders READ getQmlCoatingCurrentCarrierOrders NOTIFY guiRefresh)  
    

    The QVariantList is filled with:

        CoatingCurrentCarrierOrders .clear();
       
        /* get iterator of source elements */ 
        QListIterator<DA_Order*> myOrders_t = p_BL_Main->getOrders_t();
        
        /* insert all found elements to list */
        while(myOrders_t.hasNext())
        {
              /* append to list */
              CoatingCurrentCarrierOrders.append(QVariant(&myOrders_t.peekNext()));
              myOrders_t.next();
        }
    

    The QObject-based class DA_Order has the following property:

    Q_PROPERTY( QString DetailInformation_s READ getDetailInformation_s)
    

    When I try to use this list in QML like this, I get the error that the type (DA_Order) is undefined:
    (of course index 0 is only for testing purpose so far)

        Repeater
        {
            model: MyObject.CoatingCurrentCarrierOrders 
    
            Text {
                text:modelData.DetailInformation_s
                width:100
            }
        }
    }
    

    although the type DA_Order is registered in main.cpp via
    qmlRegisterType<DA_Order>("DA_Order", 1, 0, "DA_Order");

    Is there any cast I'm missing, QML should know the type DA_Order?!


  • Moderators

    Hi @CertaBit,
    What is modelData ?

    QML should know the type DA_Order?

    AFAIK. Not needed.



  • @p3c0 just read it somewhere else, does not work with or w/o it...
    was just a try...


  • Moderators

    @CertaBit So what is modelData ?



  • @p3c0 thought it's the current item. So if it's a variantlist of DA_Order it should be the current DA_Order item.

    the result is:

    Error: Cannot assign [undefined] to QString


  • Moderators

    @CertaBit Not I guess. Try following

    //Access first QVarianList and set as model
    model: MyObject.CoatingCurrentCarrierOrders[0] 
    ...
    //Access the individual item's property in that model
    text: MyObject.CoatingCurrentCarrierOrders[0][index].DetailInformation_s 
    

    Edit: Changed list to CoatingCurrentCarrierOrders in text



  • @p3c0 gives: TypeError: Cannot read property '0' of undefined


  • Moderators

    @CertaBit Did you notice the change that I edited in earlier post ?
    Changed list to CoatingCurrentCarrierOrders in text. Did you try this change ?



  • @p3c0 said:
    did not notice that, but tried now. result:

    TypeError: Cannot read property 'DetailInformation_s' of undefined.

    I followed every single step described here


  • Moderators

    @CertaBit Does the model work ? Just to test the model assign some hard coded string to text. If the ListView shows those many amount of list items with that hard coded text it means the model works correctly and the problem is in accessing the property of individual items in that list.



  • @p3c0
    good idea, tried this before posting here. this works correct, the problem is accessing the property.


  • Moderators

    @CertaBit Ok.. Can you post output of following ? Add it in Component.onCompleted handler of QML file where ListView is present.

    Component.onCompleted: {
        console.log(MyObject.CoatingCurrentCarrierOrders)
        console.log("\n",MyObject.CoatingCurrentCarrierOrders[0])
        console.log("\n",MyObject.CoatingCurrentCarrierOrders[0][0].DetailInformation_s)
    }
    


  • @p3c0
    Console shows:

    qml: [true,true,true]
    qml:
    true

    this points to console.log("\n",MyObject.CoatingCurrentCarrierOrders[0][0].DetailInformation_s):
    qrc:/qml/Coating.qml:168: TypeError: Cannot read property 'DetailInformation_s' of undefined

    seems that it handles it as bool type not DA_Order...


  • Moderators

    @CertaBit Try using QVariant::fromValue instead of QVariant()
    Tried simulating your problem. Try the following code. It should explain what I meant:
    myItem.h

    #ifndef MYITEM_H
    #define MYITEM_H
    
    #include <QObject>
    
    class MyItem : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    public:
        explicit MyItem(QObject *parent = 0);
        QString name() const;
    
    protected slots:
        void setName(QString name);
    
    signals:
        void nameChanged(QString arg);
    
    private:
        QString m_name;
    };
    
    #endif // MYITEM_H
    

    myitem.cpp

    #include "myitem.h"
    
    MyItem::MyItem(QObject *parent) : QObject(parent)
    {}
    
    void MyItem::setName(QString name)
    {
        m_name = name;
    }
    
    QString MyItem::name() const
    {
        return m_name;
    }
    

    myobject.h

    #ifndef MYOBJECT_H
    #define MYOBJECT_H
    
    #include <QObject>
    #include <QVariantList>
    #include "myitem.h"
    
    class MyObject : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QVariantList list READ list WRITE setList NOTIFY listChanged)
    
    public:
        explicit MyObject(QObject *parent = 0);
        QVariantList list() const;
    
    signals:
        void listChanged(QVariantList arg);
    
    public slots:
        void setList(QVariantList arg);
    
    private:
        QVariantList m_list;
    };
    
    #endif // MYOBJECT_H
    
    

    myobject.cpp

    #include "myobject.h"
    
    MyObject::MyObject(QObject *parent) : QObject(parent)
    {
         QVariantList tmpList1;
         for(int a=0;a<10;a++) {
             MyItem *i = new MyItem;
             i->setProperty("name","Item-A-"+QString::number(a));
             tmpList1 << QVariant::fromValue(i);
         }
    
         m_list.append(QVariant::fromValue(tmpList1));
    
         QVariantList tmpList2;
         for(int b=0;b<10;b++) {
             MyItem *i = new MyItem;
             i->setProperty("name","Item-B-"+QString::number(b));
             tmpList2 << QVariant::fromValue(i);
         }
    
         m_list.append(QVariant::fromValue(tmpList2));
    }
    
    QVariantList MyObject::list() const
    {
        return m_list;
    }
    
    void MyObject::setList(QVariantList arg)
    {
        if (m_list == arg)
            return;
    
        m_list = arg;
        emit listChanged(arg);
    }
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QtQuick>
    #include "myobject.h"
    
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        MyObject obj;
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("MyObject",&obj);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        return app.exec();
    }
    

    main.qml

    import QtQuick 2.4
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.3
    
    Window {
        visible: true
        width: 200
        height: 400
    
        ListView {
            anchors.fill: parent
            model: MyObject.list[0]
    
            delegate: Rectangle {
                width: 200
                height: 40
                Text {
                    anchors.centerIn: parent
                    text: MyObject.list[0][index].name
                }
            }
        }
    
        Component.onCompleted: {
            console.log(MyObject.list)
            console.log("\n",MyObject.list[0])
            console.log("\n",MyObject.list[0][0].name)
        }
    }
    
    


  • @p3c0 said:
    YES!!!! THIS IS IT!!! Thank's man!

    This is what did the job:

    myObject.cpp:
    tmpList << QVariant::fromValue(myOrders_t.peekNext());

    QML:

    model: myObject.CoatingCurrentCarrierOrders
    
    Text {
       text: modelData.DetailInformation_s
       width: 150
    }
    
    with "modelData" equal to your suggestion  
    
    `MyObject.list[0][index]`
    
    Seems that the hierarchy is model.modelData.Propertyname.
    
    So what actually was the issue? Qt handles added with QVariant() as boolean if its a pointer?

  • Moderators

    @CertaBit Well, use QVariant::fromValue() to construct variants from the pointer types as mentioned here. Not sure why it returned true though.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.