diff --git a/src/plugins/qmlprojectmanager/qmlprojectexporter/boilerplate.qrc b/src/plugins/qmlprojectmanager/qmlprojectexporter/boilerplate.qrc
index 4960324ab74..50e9909a17c 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectexporter/boilerplate.qrc
+++ b/src/plugins/qmlprojectmanager/qmlprojectexporter/boilerplate.qrc
@@ -11,5 +11,8 @@
templates/import_qml_components_h.tpl
templates/qtquickcontrols2_conf.tpl
templates/cmakelists_txt_shared.tpl
+ templates/python_generator_main.tpl
+ templates/python_generator_settings.tpl
+ templates/python_pyproject_toml.tpl
diff --git a/src/plugins/qmlprojectmanager/qmlprojectexporter/exporter.cpp b/src/plugins/qmlprojectmanager/qmlprojectexporter/exporter.cpp
index e228b53703a..40de901c4fe 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectexporter/exporter.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectexporter/exporter.cpp
@@ -30,6 +30,7 @@ void Exporter::updateProject(QmlProject *project)
void Exporter::updateProjectItem(QmlProjectItem *item, bool updateEnabled)
{
connect(item, &QmlProjectItem::filesChanged, m_cmakeGen, &CMakeGenerator::update);
+ connect(item, &QmlProjectItem::filesChanged, m_pythonGen, &PythonGenerator::update);
connect(item, &QmlProjectItem::fileModified, m_cmakeGen, &CMakeGenerator::updateModifiedFile);
if (updateEnabled) {
diff --git a/src/plugins/qmlprojectmanager/qmlprojectexporter/pythongenerator.cpp b/src/plugins/qmlprojectmanager/qmlprojectexporter/pythongenerator.cpp
index 11ae25fd2ce..636f47fa7d9 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectexporter/pythongenerator.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectexporter/pythongenerator.cpp
@@ -3,41 +3,14 @@
#include "pythongenerator.h"
#include "cmakewriter.h"
+#include "resourcegenerator.h"
#include "projectexplorer/projectmanager.h"
#include "qmlprojectmanager/qmlproject.h"
#include
-namespace QmlProjectManager {
-
-namespace QmlProjectExporter {
-
-const char *PYTHON_MAIN_FILE_TEMPLATE = R"(
-import os
-import sys
-from pathlib import Path
-
-from PySide6.QtGui import QGuiApplication
-from PySide6.QtQml import QQmlApplicationEngine
-
-from autogen.settings import url, import_paths
-
-if __name__ == '__main__':
- app = QGuiApplication(sys.argv)
- engine = QQmlApplicationEngine()
-
- app_dir = Path(__file__).parent.parent
-
- engine.addImportPath(os.fspath(app_dir))
- for path in import_paths:
- engine.addImportPath(os.fspath(app_dir / path))
-
- engine.load(os.fspath(app_dir/url))
- if not engine.rootObjects():
- sys.exit(-1)
- sys.exit(app.exec())
-)";
+namespace QmlProjectManager::QmlProjectExporter {
void PythonGenerator::createMenuAction(QObject *parent)
{
@@ -66,9 +39,8 @@ PythonGenerator::PythonGenerator(QmlBuildSystem *bs)
void PythonGenerator::updateMenuAction()
{
- FileGenerator::updateMenuAction(
- "QmlProject.EnablePythonGenerator",
- [this]() { return buildSystem()->enablePythonGeneration(); });
+ FileGenerator::updateMenuAction("QmlProject.EnablePythonGenerator",
+ [this]() { return buildSystem()->enablePythonGeneration(); });
}
void PythonGenerator::updateProject(QmlProject *project)
@@ -77,38 +49,47 @@ void PythonGenerator::updateProject(QmlProject *project)
return;
Utils::FilePath projectPath = project->rootProjectDirectory();
- Utils::FilePath pythonPath = projectPath.pathAppended("Python");
- if (!pythonPath.exists())
- pythonPath.createDir();
+ Utils::FilePath pythonFolderPath = projectPath.pathAppended("Python");
+ if (!pythonFolderPath.exists())
+ pythonFolderPath.createDir();
- Utils::FilePath mainFile = pythonPath.pathAppended("main.py");
- if (!mainFile.exists()) {
- const QString mainContent = QString::fromUtf8(PYTHON_MAIN_FILE_TEMPLATE);
- CMakeWriter::writeFile(mainFile, mainContent);
+ Utils::FilePath mainFilePath = pythonFolderPath.pathAppended("main.py");
+ if (!mainFilePath.exists()) {
+ const QString mainFileTemplate = CMakeWriter::readTemplate(
+ ":/templates/python_generator_main");
+ CMakeWriter::writeFile(mainFilePath, mainFileTemplate);
}
- Utils::FilePath autogenPath = pythonPath.pathAppended("autogen");
- if (!autogenPath.exists())
- autogenPath.createDir();
+ Utils::FilePath pyprojectFilePath = pythonFolderPath.pathAppended("pyproject.toml");
+ if (!pyprojectFilePath.exists()) {
+ const QString pyprojectFileTemplate = CMakeWriter::readTemplate(
+ ":/templates/python_pyproject_toml");
+ const QString pyprojectFileContent = pyprojectFileTemplate.arg(project->displayName());
+ CMakeWriter::writeFile(pyprojectFilePath, pyprojectFileContent);
+ }
- Utils::FilePath settingsPath = autogenPath.pathAppended("settings.py");
- CMakeWriter::writeFile(settingsPath, settingsFileContent());
+ Utils::FilePath autogenFolderPath = pythonFolderPath.pathAppended("autogen");
+ if (!autogenFolderPath.exists())
+ autogenFolderPath.createDir();
+
+ Utils::FilePath settingsFilePath = autogenFolderPath.pathAppended("settings.py");
+ const QString settingsFileTemplate = CMakeWriter::readTemplate(
+ ":/templates/python_generator_settings");
+ const QString settingsFileContent = settingsFileTemplate.arg(buildSystem()->mainFile());
+ CMakeWriter::writeFile(settingsFilePath, settingsFileContent);
+
+ // Python code uses the Qt resources collection file (.qrc)
+ ResourceGenerator::createQrc(project);
}
-QString PythonGenerator::settingsFileContent() const
-{
- QTC_ASSERT(buildSystem(), return {});
+/*!
+ Regenerates the .qrc resources file
+*/
+void PythonGenerator::update(const QSet &added, const QSet &removed) {
+ Q_UNUSED(added);
+ Q_UNUSED(removed);
+ ResourceGenerator::createQrc(qmlProject());
+ // Generated Python code does not need to be updated
+};
- QString content("\n");
- content.append("url = \"" + buildSystem()->mainFile() + "\"\n");
-
- content.append("import_paths = [\n");
- for (const QString &path : buildSystem()->importPaths())
- content.append("\t\"" + path + "\",\n");
- content.append("]\n");
-
- return content;
-}
-
-} // namespace QmlProjectExporter.
-} // namespace QmlProjectManager.
+} // namespace QmlProjectExporter::QmlProjectManager.
diff --git a/src/plugins/qmlprojectmanager/qmlprojectexporter/pythongenerator.h b/src/plugins/qmlprojectmanager/qmlprojectexporter/pythongenerator.h
index 7c0a5810df5..34f8c2be38d 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectexporter/pythongenerator.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectexporter/pythongenerator.h
@@ -21,11 +21,10 @@ public:
static void createMenuAction(QObject *parent);
PythonGenerator(QmlBuildSystem *bs);
+
+ void update(const QSet &added, const QSet &removed);
void updateMenuAction() override;
void updateProject(QmlProject *project) override;
-
-private:
- QString settingsFileContent() const;
};
} // namespace QmlProjectExporter.
diff --git a/src/plugins/qmlprojectmanager/qmlprojectexporter/templates/python_generator_main.tpl b/src/plugins/qmlprojectmanager/qmlprojectexporter/templates/python_generator_main.tpl
new file mode 100644
index 00000000000..c768aa799bf
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qmlprojectexporter/templates/python_generator_main.tpl
@@ -0,0 +1,26 @@
+import sys
+
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import QQmlApplicationEngine
+
+from autogen.settings import setup_qt_environment
+
+# Import here the Python files that define QML elements
+
+
+def main():
+ app = QGuiApplication(sys.argv)
+ engine = QQmlApplicationEngine()
+
+ setup_qt_environment(engine)
+
+ if not engine.rootObjects():
+ sys.exit(-1)
+
+ ex = app.exec()
+ del engine
+ return ex
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/src/plugins/qmlprojectmanager/qmlprojectexporter/templates/python_generator_settings.tpl b/src/plugins/qmlprojectmanager/qmlprojectexporter/templates/python_generator_settings.tpl
new file mode 100644
index 00000000000..435ee55aac4
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qmlprojectexporter/templates/python_generator_settings.tpl
@@ -0,0 +1,36 @@
+# This file is automatically generated by Qt Design Studio.
+import os
+import sys
+from pathlib import Path
+
+from PySide6.QtQml import QQmlApplicationEngine
+
+project_root = Path(__file__).parent.parent.parent
+
+
+def setup_qt_environment(qml_engine: QQmlApplicationEngine):
+ """
+ Load the QML application. Import the compiled resources when the application is deployed.
+ """
+ qml_app_url = "%1"
+
+ if "__compiled__" in globals():
+ # Application has been deployed using pyside6-deploy
+ try:
+ import autogen.resources # noqa: F401
+ except ImportError:
+ resource_file = Path(__file__).parent / "resources.py"
+ print(
+ f"Error: No compiled resources found in {resource_file.absolute()}\n"
+ f"Please compile the resources using pyside6-rcc or pyside6-project build",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ qml_engine.addImportPath(":/")
+ qml_engine.load(f":/{qml_app_url}")
+ return
+
+ qml_engine.addImportPath(str(project_root.absolute()))
+ os.environ["QT_QUICK_CONTROLS_CONF"] = str(project_root / "qtquickcontrols2.conf")
+ qml_engine.load(str(project_root / qml_app_url))
diff --git a/src/plugins/qmlprojectmanager/qmlprojectexporter/templates/python_pyproject_toml.tpl b/src/plugins/qmlprojectmanager/qmlprojectexporter/templates/python_pyproject_toml.tpl
new file mode 100644
index 00000000000..21c00189295
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/qmlprojectexporter/templates/python_pyproject_toml.tpl
@@ -0,0 +1,5 @@
+[project]
+name = "%1"
+
+[tool.pyside6-project]
+files = ["main.py", "autogen/settings.py"]