Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Do I need to add qmldir for python objects exposed as singleton instances?

Do I need to add qmldir for python objects exposed as singleton instances?

Scheduled Pinned Locked Moved Unsolved Qt for Python
5 Posts 2 Posters 204 Views 2 Watching
  • 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.
  • M Offline
    M Offline
    Munhz
    wrote last edited by
    #1

    I am working on vscode using the official extensions and I am registering a singleton instance as:

    QtQml.qmlRegisterSingletonInstance(
            controllers.AppController,
            "TodoApp",
            1,
            0,
            "AppController",
            context.app_controller,
        )
    

    Now My AppController doesnt use @QmlElement or @QmlSingleton bc as far as I understand I dont need those while registering a singleton instance this way. Now on my qml file I get a warning as TodoApp cant be imported:

    Warnings occurred while importing module "TodoApp": [import]qmllint
    Failed to import TodoApp. Are your import paths set up properly? Did you build your project? [import]qmllint
    

    That means that I dont get any autocompletion for my AppController and ofc the linter complains about that. Checking the output of the language server I can see:

    [Dom] Warning: Failed to find main qmldir file for TodoApp  in /usr/lib/qt6/qml/, /mnt/storage/Projects/todo/src/todo/frontend/qml_modules, /usr/lib/python3.14/site-packages/PySide6/Qt/qml, /home/runner/work/qmlls-workflow/qmlls-workflow/qt-build/qtbase/qml.
    

    So I am wondering if I need to create a qmldir for this TodoApp module (that is just a module at runtime) and if that will help the qmlls to recognize it and offer autocompletion. The code works just fine is just an issue with the linter/language server.

    JKSHJ 1 Reply Last reply
    0
    • M Munhz

      I am working on vscode using the official extensions and I am registering a singleton instance as:

      QtQml.qmlRegisterSingletonInstance(
              controllers.AppController,
              "TodoApp",
              1,
              0,
              "AppController",
              context.app_controller,
          )
      

      Now My AppController doesnt use @QmlElement or @QmlSingleton bc as far as I understand I dont need those while registering a singleton instance this way. Now on my qml file I get a warning as TodoApp cant be imported:

      Warnings occurred while importing module "TodoApp": [import]qmllint
      Failed to import TodoApp. Are your import paths set up properly? Did you build your project? [import]qmllint
      

      That means that I dont get any autocompletion for my AppController and ofc the linter complains about that. Checking the output of the language server I can see:

      [Dom] Warning: Failed to find main qmldir file for TodoApp  in /usr/lib/qt6/qml/, /mnt/storage/Projects/todo/src/todo/frontend/qml_modules, /usr/lib/python3.14/site-packages/PySide6/Qt/qml, /home/runner/work/qmlls-workflow/qmlls-workflow/qt-build/qtbase/qml.
      

      So I am wondering if I need to create a qmldir for this TodoApp module (that is just a module at runtime) and if that will help the qmlls to recognize it and offer autocompletion. The code works just fine is just an issue with the linter/language server.

      JKSHJ Offline
      JKSHJ Offline
      JKSH
      Moderators
      wrote last edited by
      #2

      Hi, and welcome!

      @Munhz said in Do I need to add qmldir for python objects exposed as singleton instances?:

      Now My AppController doesnt use @QmlElement or @QmlSingleton bc as far as I understand I dont need those while registering a singleton instance this way. Now on my qml file I get a warning as TodoApp cant be imported

      It's the other way round: If you use @QmlElement + @QmlSingleton, then you don't need to call qmlRegisterSingletonInstance() and you shouldn't get those warnings.

      Just remember that your main.py file must import the file that contains @QmlElement and the related decorators/variables before you initialize your QML engine.

      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

      M 1 Reply Last reply
      2
      • JKSHJ JKSH

        Hi, and welcome!

        @Munhz said in Do I need to add qmldir for python objects exposed as singleton instances?:

        Now My AppController doesnt use @QmlElement or @QmlSingleton bc as far as I understand I dont need those while registering a singleton instance this way. Now on my qml file I get a warning as TodoApp cant be imported

        It's the other way round: If you use @QmlElement + @QmlSingleton, then you don't need to call qmlRegisterSingletonInstance() and you shouldn't get those warnings.

        Just remember that your main.py file must import the file that contains @QmlElement and the related decorators/variables before you initialize your QML engine.

        M Offline
        M Offline
        Munhz
        wrote last edited by
        #3

        @JKSH I am not sure that I follow you. My understanding was that when I use @QmlElement/QmlSingleton I was making the types available for QML to instantiate. In my case, I am creating an instance of my class on the python side that I am registering after, so I can inject some dependencies into it before the QML engine gets it.

        Are you saying that if I just use both decorators in my class, I can still instantiate it before loading the engine and then my QML code can use the instance I created on the python side? I actually did a quick test just changing that and it fails with:

        <Unknown File>: qmlRegisterSingletonType(): "AppController" is not available because the callback function returns a null pointer.
        

        So I am not sure if I would need to do smth else extra or this approach does not work for registering an instance of my class.

        JKSHJ 1 Reply Last reply
        0
        • M Munhz

          @JKSH I am not sure that I follow you. My understanding was that when I use @QmlElement/QmlSingleton I was making the types available for QML to instantiate. In my case, I am creating an instance of my class on the python side that I am registering after, so I can inject some dependencies into it before the QML engine gets it.

          Are you saying that if I just use both decorators in my class, I can still instantiate it before loading the engine and then my QML code can use the instance I created on the python side? I actually did a quick test just changing that and it fails with:

          <Unknown File>: qmlRegisterSingletonType(): "AppController" is not available because the callback function returns a null pointer.
          

          So I am not sure if I would need to do smth else extra or this approach does not work for registering an instance of my class.

          JKSHJ Offline
          JKSHJ Offline
          JKSH
          Moderators
          wrote last edited by JKSH
          #4

          @Munhz said in Do I need to add qmldir for python objects exposed as singleton instances?:

          My understanding was that when I use @QmlElement/QmlSingleton I was making the types available for QML to instantiate.

          Yes, @QmlElement allows your type to be instantiated in QML. @QmlSingleton is quite flexible: The QML engine could automatically instantiate your singleton, or you can make the engine use your existing instance by implementing a static create() method (see below).

          In addition to QML instantiation, these decorators automatically generate the qmldir + *.qmltypes files. These files are read by qmllint and the QML Language Server (qmlls) to understand your Python types.

          In my case, I am creating an instance of my class on the python side that I am registering after, so I can inject some dependencies into it before the QML engine gets it.

          Are you saying that if I just use both decorators in my class, I can still instantiate it before loading the engine and then my QML code can use the instance I created on the python side?

          If you define a static create() method (see https://doc.qt.io/qtforpython-6/PySide6/QtQml/QmlSingleton.html), the QML engine calls that method instead of automatically instantiating your type.

          You can instantiate your object in Python, do your injections, then initialize the QML engine. The engine will call create() at this point, so let create() return your existing object (you can ignore the "engine" parameter of the method if you only have one engine).

          The Python docs are a bit sparse; see the C++ docs to get an idea on how to use create(): https://doc.qt.io/qt-6/qml-singleton.html#defining-singletons-in-c

          So I am not sure if I would need to do smth else extra or this approach does not work for registering an instance of my class.

          The newer @QmlElement and its friends are replacing the older qmlRegister*() functions. If you want to continue using qmlRegister*(), you'll need to manually write a qmldir file and *.qmltypes file to keep qmllint/qmlls happy. Use some auto-generated ones as a template.

          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

          M 1 Reply Last reply
          2
          • JKSHJ JKSH

            @Munhz said in Do I need to add qmldir for python objects exposed as singleton instances?:

            My understanding was that when I use @QmlElement/QmlSingleton I was making the types available for QML to instantiate.

            Yes, @QmlElement allows your type to be instantiated in QML. @QmlSingleton is quite flexible: The QML engine could automatically instantiate your singleton, or you can make the engine use your existing instance by implementing a static create() method (see below).

            In addition to QML instantiation, these decorators automatically generate the qmldir + *.qmltypes files. These files are read by qmllint and the QML Language Server (qmlls) to understand your Python types.

            In my case, I am creating an instance of my class on the python side that I am registering after, so I can inject some dependencies into it before the QML engine gets it.

            Are you saying that if I just use both decorators in my class, I can still instantiate it before loading the engine and then my QML code can use the instance I created on the python side?

            If you define a static create() method (see https://doc.qt.io/qtforpython-6/PySide6/QtQml/QmlSingleton.html), the QML engine calls that method instead of automatically instantiating your type.

            You can instantiate your object in Python, do your injections, then initialize the QML engine. The engine will call create() at this point, so let create() return your existing object (you can ignore the "engine" parameter of the method if you only have one engine).

            The Python docs are a bit sparse; see the C++ docs to get an idea on how to use create(): https://doc.qt.io/qt-6/qml-singleton.html#defining-singletons-in-c

            So I am not sure if I would need to do smth else extra or this approach does not work for registering an instance of my class.

            The newer @QmlElement and its friends are replacing the older qmlRegister*() functions. If you want to continue using qmlRegister*(), you'll need to manually write a qmldir file and *.qmltypes file to keep qmllint/qmlls happy. Use some auto-generated ones as a template.

            M Offline
            M Offline
            Munhz
            wrote last edited by
            #5

            @JKSH I am trying to go through your answer step by step going from the simplest case and adding complexity. I am trying to use the decorators as you mentioned but I still cant get the qmllint or the language server to recognize my python types. The code works but in my qml file I will get a warning that the module can not be imported.

            @JKSH said in Do I need to add qmldir for python objects exposed as singleton instances?:

            In addition to QML instantiation, these decorators automatically generate the qmldir + *.qmltypes files. These files are read by qmllint and the QML Language Server (qmlls) to understand your Python types.

            I am not sure how adding a decorator to my class can generate these files so the language server can recognize the types. I feel like I am missing something here related to the qt tools provided for python but I cant see what. Going through the documentation I have tried to use pyside6-project build but nothing really happens even if I dont get any errors. I tried using pyside6-project qmllint and get the same warnings. My qml file and the .py file where the @QmlElement decorated class lives have been added to the pyproject.toml. Still not *.qmltypes are generated in this process. Information about these tools seems scarce so I am wondering if I am missing something.

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved