Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

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

    QML and Qt Quick
    2
    7
    2166
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • vikramg
      vikramg last edited by

      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.]

      1 Reply Last reply Reply Quote 0
      • dheerendra
        dheerendra Qt Champions 2022 last edited by dheerendra

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

        Dheerendra
        @Community Service
        Certified Qt Specialist
        http://www.pthinks.com

        1 Reply Last reply Reply Quote 0
        • vikramg
          vikramg last edited by

          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.

          1 Reply Last reply Reply Quote 0
          • dheerendra
            dheerendra Qt Champions 2022 last edited by dheerendra

            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 ?

            Dheerendra
            @Community Service
            Certified Qt Specialist
            http://www.pthinks.com

            1 Reply Last reply Reply Quote 0
            • vikramg
              vikramg last edited by vikramg

              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?

              1 Reply Last reply Reply Quote 0
              • dheerendra
                dheerendra Qt Champions 2022 last edited by dheerendra

                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");

                Dheerendra
                @Community Service
                Certified Qt Specialist
                http://www.pthinks.com

                1 Reply Last reply Reply Quote 1
                • vikramg
                  vikramg last edited by

                  That does indeed work! Thank you!

                  qmlRegisterSingletonType(QUrl(QStringLiteral("qrc:/AppConfig/Config.qml")), "com.test.Config", 1, 0, "Config");
                  
                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post