Models: QList<QObject*> vs QList<Derived*>



  • Hi,

    Fairly simple question: It seems that when I use a GridView with a model of QList<Derived*>, where Derived inherits from QObject, the delegate of my GridView doesn't show anything. If, OTOH I stick with a model QList<QObject*>, it works as expected. (Each QObject pointer points to a Derived).

    Is this normal and expected? Can I use a QList<Derived*> as a model instead, iow. have I just missed something?


  • Lifetime Qt Champion

    Hi,

    I'm no QML specialist yet, but did you register your custom type ? Have a look "here":http://qt-project.org/doc/qt-5/qtqml-cppintegration-data.html#qobject-derived-types

    Hope it helps



  • If by that, you mean:
    @qmlRegisterType<Derived>("MyApp", 1,0, "Derived");@

    then yes, I did.


  • Lifetime Qt Champion

    Also the QList<Derived *> type ?



  • I'm not sure I see why that would be required, but I tried it anyway:

    @qmlRegisterType<QList<Derived*> >("MyApp", 1,0, "DerivedList");@

    This causes a compile-error:

    /usr/include/qt5/QtQml/qqml.h:204: error: 'staticMetaObject' is not a member of 'QList<Derived*>'

    I find this even weirder, since /usr/include/qt5 does not exist. I'm using the SailfishSDK and it's under /opt, not /usr. Ah well, I guess the compiler just reports the path incorrectly.



  • Also, you may using "QQmlListProperty":http://qt-project.org/doc/qt-5/qqmllistproperty.html



  • [quote author="qragnar" date="1410240330"]I'm not sure I see why that would be required, but I tried it anyway:

    @qmlRegisterType<QList<Derived*> >("MyApp", 1,0, "DerivedList");@

    This causes a compile-error:

    /usr/include/qt5/QtQml/qqml.h:204: error: 'staticMetaObject' is not a member of 'QList<Derived*>'
    [/quote]

    I think this is because QList is not QObject subclass


  • Lifetime Qt Champion

    Indeed, I've mixed two different things together. Sorry



  • [quote author="Ildar" date="1410240434"]Also, you may using "QQmlListProperty":http://qt-project.org/doc/qt-5/qqmllistproperty.html[/quote]

    I'm not really sure I understand how this applies to a model. Are you suggesting I simply wrap the QList as a property of a model?



  • Yes, you may create simple wrap for QList<Derived*>
    I think QQmlListProperty more appropriate way to set collection from C++ to QML. For example:
    @Q_PROPERTY(QQmlListProperty<Derived> derivedList READ derivedListProperty NOTIFY derivedListChanged)

    private:
    QQmlListProperty<Derived> derivedListProperty()
    {
    return QQmlListProperty<Derived>(this,
    NULL,
    &MyClass::append,
    &MyClass::count,
    &MyClass::at,
    &MyClass::clear);
    }

    static void append(QQmlListProperty<Derived> *property, Derived *value)
    {
    MyClass myClass = qobject_cast<MyClass>(property->object);

    if(myClass != NULL)
    {
            myClass->add(value);
    }
    

    }

    static Derived *at(QQmlListProperty<Derivedt> *property, int index)
    {
    MyClacc myClass = qobject_cast<MyClass>(property->object);

    if(myClass != NULL)
    {
        return myClass->at(index);
    }
    else
    {
        return NULL;
    }
    

    }

    static void clear(QQmlListProperty<Derived> *property)
    {
    MyClass myClass = qobject_cast<MyClass>(property->object);

    if(myClass != NULL)
    {
        myClass->clear();
    }
    

    }

    static int count(QQmlListProperty<Derived> *property)
    {
    MyClass myClass = qobject_cast<MyClass>(property->object);

    if(myClass != NULL)
    {
        return myClass->size();
    }
    else
    {
        return 0;
    }
    

    }
    @

    And now in QML you can using myClass.derivedList as simple QML list



  • Hmm... Still not sure I'm getting this. I tried your code. Thank you very much for that, btw! However, the GridView doesn't get populated with anything:

    @GridView {
    id: buttonGrid
    anchors.fill: parent
    model: MyClass.derivedList
    // ...
    }@

    buttonGrid is empty. I've inserted some qDebug() calls and it seems that derivedListProperty() does not even get called...



  • Did you register your custom type?
    @qmlRegisterType<MyClass>("MyApp", 1,0, "MyClass");@

    And did you export MyClass instance to QML?
    @
    QQmlApplicationEngine *qmlEngine = new QQmlApplicationEngine(this);
    qmlEngine->rootContext()->setContextProperty("myClass", new MyClass());
    @
    Or did you create MyClass instance in QML?
    @
    MyClass {
    id: myClass
    }
    GridView {
    id: buttonGrid
    anchors.fill: parent
    model: myClass.derivedList
    // ...
    }@



  • Yes, I have registered the type using qmlRegisterType. And main.cpp contains the following:

    @QGuiApplication *app = SailfishApp::application(argc, argv);
    QQuickView *view = SailfishApp::createView();
    QQmlContext *ctxt = view->rootContext();
    
    MyClass mc;
    // this is irrelevant here, but included for clarity
    // it is just to make it possible for mc to use setContectProperty
    // in this case, it isn't used, though
    mc.setQmlContext(ctxt);
    mc.loadData("default");
    view->setResizeMode(QQuickView::SizeRootObjectToView);
    ctxt->setContextProperty("MyClass", QVariant::fromValue(&mc));
    

    @

    As you can see, this is really a SailFish app



  • Try ctxt->setContextProperty("myClass", QVariant::fromValue(&mc));
    and using as model: myClass.derivedList (start with lower letter "m").
    P.S.
    MyClass - this is type
    myClass - this is instance of object



  • And more better set parents to objects. For example:
    @MyClass *myClass = new MyClass(this);@
    This is because if object parent is null than QML take ownership of object.



  • Well, to be precise the type could start with a lower case and the instance name with an upper case, but I suppose using the same name for both could be more problematic.

    In any case, it is now working and I can set the model to derivedList. Thanks very much for that suggestion. However, I still have my original problem, which is the reason wanting to use something other than QList<QObject*>. The original problem is that I can't called a method defined in Derived from the Delegate, since QML doesn't know that model is Derived, only QObject.

    Update:
    Actuallly, I realised after posting this that I can dereference like this:

    @onClicked: {
    myClass.derivedList[index].doSomeStuff()
    myClass.derivedList[index].callAnotherMethod()
    }
    @

    So my original issue is actually solved now. Thanks!



  • bq. Well, to be precise the type could start with a lower case and the instance name with an upper case, but I suppose using the same name for both could be more problematic.

    Of cource) Simply, I using "Qt coding style":http://qt-project.org/wiki/Qt_Coding_Style


Log in to reply
 

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