Do I need to add qmldir for python objects exposed as singleton instances?
-
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]qmllintThat 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.
-
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]qmllintThat 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.
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
importthe file that contains@QmlElementand the related decorators/variables before you initialize your QML engine. -
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
importthe file that contains@QmlElementand the related decorators/variables before you initialize your QML engine.@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.
-
@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.
@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,
@QmlElementallows your type to be instantiated in QML.@QmlSingletonis quite flexible: The QML engine could automatically instantiate your singleton, or you can make the engine use your existing instance by implementing a staticcreate()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 letcreate()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-cSo 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
@QmlElementand its friends are replacing the olderqmlRegister*()functions. If you want to continue usingqmlRegister*(), 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. -
@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,
@QmlElementallows your type to be instantiated in QML.@QmlSingletonis quite flexible: The QML engine could automatically instantiate your singleton, or you can make the engine use your existing instance by implementing a staticcreate()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 letcreate()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-cSo 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
@QmlElementand its friends are replacing the olderqmlRegister*()functions. If you want to continue usingqmlRegister*(), 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.@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.