HOWTO access members of a Singleton QML Object type from C++



  • I'm trying to access properties of an "App Settings" QML object from C++. Per various examples, I have made it a singleton, since its only purpose is to provide some settings properties.

    I tried to follow the examples here:
    http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html
    to access these properties from C++ via:

    QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/AppConfig/Config.qml")));
    QObject *object = component.create();
    int myWidth = QQmlProperty::read(object, "width").toInt();
    

    But this works only when the object is not marked pragma Singleton -- presumably because we are actually instantiating the object in the component.create(), which the singleton disallows.

    Is there any way around this? [Incidentally, the other QQuickView method doesn't work at all, even on non-singleton objects, because the object is a QtObject and not an Item.]


  • Qt Champions 2017

    It should work as is. It should not make any difference.. Can you post your config.qml ?



  • AppConfig/Config.qml:

    import QtQuick 2.0
    pragma Singleton
    
    QtObject {
    
        objectName: "Config"
    
        readonly property int width: 37
        readonly property int height: 43
    }
    

    main.cpp:

    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/AppConfig/Config.qml")));
        QObject *object = component.create();
    
        int cfgWidth = QQmlProperty::read(object, "width").toInt();
        qDebug("Config width = %d", cfgWidth);
    
        delete object;
        return app.exec();
    }
    

    This works only if I comment out the pragma Singleton from Config.qml. Otherwise it prints QQmlComponent: Component is not ready and the width read is 0.


  • Qt Champions 2017

    I have exactly same program and tried. It works like champ. Do you have only above code in Config.qml or something also exist ? Reason is that if the component is not ready, component.create and read function should crash your program. So is it crashing ?
    Also check for isError from Component and try to get all the errors using errors() function. It should give some hints.

    Which version of Qt & platform ?



  • Huh!? Wow that's strange. To answer your questions:

    • Yes, that is the entirety of code in Config.qml (I deliberately created a simple example project to illustrate the problem).
    • No, the program does not crash. The default "Hello World" application window does pop up on screen. The entirety of Application Output is:
    QML debugging is enabled. Only use this in a safe environment.
    QQmlComponent: Component is not ready
    Config width = 0
    

    (When the pragma Singleton is commented out, it correctly prints Config width = 37, and the "not ready" message is not seen). I checked in the debugger, and the object is indeed a null pointer in the failing case, but surprisingly the QQmlProperty::read function does not crash; instead, it returns 0.

    • Qt version 5.9.0; platform Linux x86-64.

    I added the isError/errors() debug instrumentation as you suggested:

        QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/AppConfig/Config.qml")));
        QObject *object = component.create();
    
        if (component.isError()) {
            for (auto e : component.errors()) {
                qDebug() << e;
            }
        }
    

    and in the failing case, it prints out:

    QML debugging is enabled. Only use this in a safe environment.
    QQmlComponent: Component is not ready
    <Unknown File>: No matching type found, pragma Singleton files cannot be used by QQmlComponent.
    Config width = 0
    

    This seems to bear out my original hunch that Singleton QML elements cannot be instantiated. But then how does it work for you?? Did this behavior change in later Qt versions?


  • Qt Champions 2017

    Can you register the Config.qml component as singleton using the following statement & then try ?
    qmlRegisterSingletonType(QStringLiteral("qrc:/MyStyles.qml"),"pthinks.styles",1,0,"PthinkStyle");



  • That does indeed work! Thank you!

    qmlRegisterSingletonType(QUrl(QStringLiteral("qrc:/AppConfig/Config.qml")), "com.test.Config", 1, 0, "Config");
    

Log in to reply
 

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