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

Set context property of a custom object is an object true



  • I'm trying to have access to a method of a custom object in QML through context.

    // C++
    // item is type MyClass
    QQuickWidget *infoView = new QQuickWidget();
    QQmlContext *rootCtx = infoView->rootContext();
    rootCtx->setContextProperty( "pl_item", item ); // item is the object I want to access
    infoView->setSource( QUrl::fromLocalFile(":/playlist/InfoMovie.qml") );
    
    viewStack->addWidget( infoView ); // viewStack is a QStackedLayout displayed
    viewStack->setCurrentWidget( infoView );
    
    // HPP of MyClass
    class MyClass : public QObject
    {
        Q_OBJECT
    public:
        MyClass( );
        Q_INVOKABLE QString getT() { return QString("plop"); };
    };
    
    //InfoMovie.qml
    Item {
        Text {
            text: "<b>"+pl_item.getT()+"</b>"
        }
        // Other stuff displayed
    

    When executing this code I get the following error :

    file::/playlist/InfoMovie.qml:39: TypeError: Property 'getT' of object true is not a function
    

    What i understand is that for the QML, pl_item is of type "true" (??) and not "MyClass" (so it can't invoke the methods) but I don't get why the type is "true". When setting a breakpoint on the c++ line with setContextProperty, I can see that item is really a well instantiated MyClass object. And the qml file is displayed properly for the rest of the file. So where can the error be ? I really have no idea where this "object true" comes from.



  • I did further tests and here is what i found. Either I didn't understand something or there is a bug :

    //C++
    // Same as above
    QQuickWidget *infoView = new QQuickWidget();
    QQmlContext *rootCtx = infoView->rootContext();
    
    // New
    log(typeid(item).name());
    rootCtx->setContextProperty( "pl_item", item );
    QVariant test = rootCtx->contextProperty("pl_item");
    log(typeid(item).name());
    log(test.typeName());
    
    // Same as above
    infoView->setSource( QUrl::fromLocalFile(":/playlist/InfoMovie.qml") );
    viewStack->addWidget( infoView ); // viewStack is a QStackedLayout displayed
    viewStack->setCurrentWidget( infoView );
    

    The debugger gives me item of type MyClass (same memory address as the object i want) and test of type QVariant (bool) (value true). And the log output :

    PK7MyClass
    PK7MyClass
    bool
    

    At least that's coherent with the fact that i'm getting a true value in the QML part.... But where does that boolean comes from ?! This code + the qml above is exactly what i've written (not simplified code). I don't understand ...



  • @MoaMoaK try

    rootCtx->setContextProperty( "pl_item", &item );
    


  • @MoaMoaK Ok, I did some demangling and testing and found out that if you create your item like this:

    MyClass const* item =  new MyClass();
    

    it gives the error, but without const it works as expected. I hope in the future you will give all the relevant information - in this case you left out the code which created the item object.



  • @MoaMoaK You could say this is a permanent bug by design in C++; it does implicit type conversion from any pointer (const or not) to bool. setContextProperty accepts const* because it accepts a QVariant, which can be created with bool.

    In any case it wouldn't make much sense to be able to pass QObject const* to setContextProperty because the data constness would be lost.



  • OH Thx a lot that was it. Without the const, it works.
    So my code went from

    void AnotherClass::showInfo(MyClass const *item)
    {
        // Same stuff as above (2nd post)
    }
    

    to

    void AnotherClass::showInfo(MyClass *item)
    {
        // Same stuff as above (2nd post)
    }
    

Log in to reply