diff --git a/src/plugins/qmldesigner/boilerplate.qrc b/src/plugins/qmldesigner/boilerplate.qrc
index 2680ec0da9c..3e2106beaa0 100644
--- a/src/plugins/qmldesigner/boilerplate.qrc
+++ b/src/plugins/qmldesigner/boilerplate.qrc
@@ -1,5 +1,10 @@
qmlprojectmaincpp.tpl
+ qmlprojectmaincppheader.tpl
+ qmlprojectmodules.tpl
+ qmlprojectmaincmakelists.tpl
+ qmlprojectmodulecmakelists.tpl
+ qmlprojectmainqml.tpl
diff --git a/src/plugins/qmldesigner/generatecmakelists.cpp b/src/plugins/qmldesigner/generatecmakelists.cpp
index feeaa2fe19e..24faa267397 100644
--- a/src/plugins/qmldesigner/generatecmakelists.cpp
+++ b/src/plugins/qmldesigner/generatecmakelists.cpp
@@ -78,7 +78,7 @@ void onGenerateCmakeLists()
{
queuedFiles.clear();
FilePath rootDir = ProjectExplorer::SessionManager::startupProject()->projectDirectory();
- GenerateCmakeLists::generateMainCmake(rootDir);
+ GenerateCmakeLists::generateCmakes(rootDir);
GenerateEntryPoints::generateMainCpp(rootDir);
GenerateEntryPoints::generateMainQml(rootDir);
if (showConfirmationDialog(rootDir))
@@ -139,138 +139,125 @@ bool writeFile(const GeneratableFile &file)
return true;
}
+QString readTemplate(const QString &templatePath)
+{
+ QFile templatefile(templatePath);
+ templatefile.open(QIODevice::ReadOnly);
+ QTextStream stream(&templatefile);
+ QString content = stream.readAll();
+ templatefile.close();
+
+ return content;
+}
+
}
namespace GenerateCmakeLists {
+QStringList moduleNames;
+
const QDir::Filters FILES_ONLY = QDir::Files;
const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
const char CMAKEFILENAME[] = "CMakeLists.txt";
const char QMLDIRFILENAME[] = "qmldir";
+const char MODULEFILENAME[] = "qmlmodules";
-QStringList processDirectory(const FilePath &dir)
+bool generateCmakes(const FilePath &rootDir)
{
- QStringList moduleNames;
+ moduleNames.clear();
- FilePaths files = dir.dirEntries(FILES_ONLY);
- for (FilePath &file : files) {
- if (!file.fileName().compare(CMAKEFILENAME))
- files.removeAll(file);
- }
+ FilePath contentDir = rootDir.pathAppended("content");
+ FilePath importDir = rootDir.pathAppended("imports");
- if (files.isEmpty()) {
- generateSubdirCmake(dir);
- FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
- for (FilePath &subDir : subDirs) {
- QStringList subDirModules = processDirectory(subDir);
- moduleNames.append(subDirModules);
- }
- }
- else {
- QString moduleName = generateModuleCmake(dir);
- if (!moduleName.isEmpty()) {
- moduleNames.append(moduleName);
- }
- }
+ generateModuleCmake(contentDir);
+ generateImportCmake(importDir);
+ generateMainCmake(rootDir);
- return moduleNames;
+ return true;
}
-const char MAINFILE_REQUIRED_VERSION[] = "cmake_minimum_required(VERSION 3.18)\n\n";
-const char MAINFILE_PROJECT[] = "project(%1 LANGUAGES CXX)\n\n";
-const char MAINFILE_CMAKE_OPTIONS[] = "set(CMAKE_INCLUDE_CURRENT_DIR ON)\nset(CMAKE_AUTOMOC ON)\n\n";
-const char MAINFILE_PACKAGES[] = "find_package(Qt6 COMPONENTS Gui Qml Quick)\n";
-const char MAINFILE_LIBRARIES[] = "set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml)\n\n";
-const char MAINFILE_CPP[] = "add_executable(%1 main.cpp)\n\n";
-const char MAINFILE_MAINMODULE[] = "qt6_add_qml_module(%1\n\tURI \"Main\"\n\tVERSION 1.0\n\tNO_PLUGIN\n\tQML_FILES main.qml\n)\n\n";
-const char MAINFILE_LINK_LIBRARIES[] = "target_link_libraries(%1 PRIVATE\n\tQt${QT_VERSION_MAJOR}::Core\n\tQt${QT_VERSION_MAJOR}::Gui\n\tQt${QT_VERSION_MAJOR}::Quick\n\tQt${QT_VERSION_MAJOR}::Qml\n)\n\n";
-
-const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
+const char MAIN_CMAKEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincmakelists.tpl";
+const char QMLMODULES_FILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodules.tpl";
void generateMainCmake(const FilePath &rootDir)
{
//TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all.
QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName();
+ QString appName = projectName + "App";
- FilePaths subDirs = rootDir.dirEntries(DIRS_ONLY);
+ QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH).arg(appName);
+ queueCmakeFile(rootDir, cmakeFileContent);
+ QString modulesAsPlugins;
+ for (const QString &moduleName : moduleNames)
+ modulesAsPlugins.append(" " + moduleName + "plugin\n");
+
+ QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH).arg(appName).arg(modulesAsPlugins);
+ GenerateCmake::queueFile(rootDir.pathAppended(MODULEFILENAME), moduleFileContent);
+}
+
+const char DO_NOT_EDIT_FILE_COMMENT[] = "### This file is automatically generated by Qt Design Studio.\n### Do not change\n\n";
+const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
+
+void generateImportCmake(const FilePath &dir)
+{
QString fileContent;
- fileContent.append(MAINFILE_REQUIRED_VERSION);
- fileContent.append(QString(MAINFILE_PROJECT).arg(projectName));
- fileContent.append(MAINFILE_CMAKE_OPTIONS);
- fileContent.append(MAINFILE_PACKAGES);
- fileContent.append(QString(MAINFILE_CPP).arg(projectName));
- fileContent.append(QString(MAINFILE_MAINMODULE).arg(projectName));
- fileContent.append(MAINFILE_LIBRARIES);
+ fileContent.append(DO_NOT_EDIT_FILE_COMMENT);
+
+ FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
for (FilePath &subDir : subDirs) {
- QStringList subDirModules = processDirectory(subDir);
- if (!subDirModules.isEmpty())
- fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
+ fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
+ generateModuleCmake(subDir);
}
- fileContent.append("\n");
- fileContent.append(QString(MAINFILE_LINK_LIBRARIES).arg(projectName));
-
- createCmakeFile(rootDir, fileContent);
+ queueCmakeFile(dir, fileContent);
}
const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE";
-const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n\tPROPERTIES\n\t\t%2 %3\n)\n\n";
-const char MODULEFILE_CREATE_MODULE[] = "qt6_add_qml_module(%1\n\tURI \"%1\"\n\tVERSION 1.0\n%2)\n\n";
+const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n";
+const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl";
-
-QString generateModuleCmake(const FilePath &dir)
+void generateModuleCmake(const FilePath &dir)
{
- QString fileContent;
+ QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH);
const QStringList qmldirFilesOnly(QMLDIRFILENAME);
+ QString singletonContent;
FilePaths qmldirFileList = dir.dirEntries(qmldirFilesOnly, FILES_ONLY);
if (!qmldirFileList.isEmpty()) {
QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
for (QString &singleton : singletons) {
- fileContent.append(QString(MODULEFILE_PROPERTY_SET).arg(singleton).arg(MODULEFILE_PROPERTY_SINGLETON).arg("true"));
+ singletonContent.append(QString(MODULEFILE_PROPERTY_SET).arg(singleton).arg(MODULEFILE_PROPERTY_SINGLETON).arg("true"));
}
}
QStringList qmlFileList = getDirectoryTreeQmls(dir);
QString qmlFiles;
for (QString &qmlFile : qmlFileList)
- qmlFiles.append(QString("\t\t%1\n").arg(qmlFile));
+ qmlFiles.append(QString(" %1\n").arg(qmlFile));
QStringList resourceFileList = getDirectoryTreeResources(dir);
QString resourceFiles;
for (QString &resourceFile : resourceFileList)
- resourceFiles.append(QString("\t\t%1\n").arg(resourceFile));
+ resourceFiles.append(QString(" %1\n").arg(resourceFile));
QString moduleContent;
if (!qmlFiles.isEmpty()) {
- moduleContent.append(QString("\tQML_FILES\n%1").arg(qmlFiles));
+ moduleContent.append(QString(" QML_FILES\n%1").arg(qmlFiles));
}
if (!resourceFiles.isEmpty()) {
- moduleContent.append(QString("\tRESOURCES\n%1").arg(resourceFiles));
+ moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles));
}
QString moduleName = dir.fileName();
- fileContent.append(QString(MODULEFILE_CREATE_MODULE).arg(moduleName).arg(moduleContent));
+ moduleNames.append(moduleName);
- createCmakeFile(dir, fileContent);
-
- return moduleName;
-}
-
-void generateSubdirCmake(const FilePath &dir)
-{
QString fileContent;
- FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
-
- for (FilePath &subDir : subDirs) {
- fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
- }
-
- createCmakeFile(dir, fileContent);
+ fileContent.append(fileTemplate.arg(singletonContent).arg(moduleName).arg(moduleContent));
+ queueCmakeFile(dir, fileContent);
}
QStringList getSingletonsFromQmldirFile(const FilePath &filePath)
@@ -347,7 +334,7 @@ QStringList getDirectoryTreeResources(const FilePath &dir)
return resourceFileList;
}
-void createCmakeFile(const FilePath &dir, const QString &content)
+void queueCmakeFile(const FilePath &dir, const QString &content)
{
FilePath filePath = dir.pathAppended(CMAKEFILENAME);
GenerateCmake::queueFile(filePath, content);
@@ -370,35 +357,42 @@ bool generateEntryPointFiles(const FilePath &dir)
return cppOk && qmlOk;
}
-const char MAIN_CPPFILE_CONTENT[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
+const char MAIN_CPPFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
+const char MAIN_CPPFILE_DIR[] = "src";
const char MAIN_CPPFILE_NAME[] = "main.cpp";
+const char MAIN_CPPFILE_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl";
+const char MAIN_CPPFILE_HEADER_NAME[] = "import_qml_plugins.h";
+const char MAIN_CPPFILE_HEADER_PLUGIN_LINE[] = "Q_IMPORT_QML_PLUGIN(%1)\n";
bool generateMainCpp(const FilePath &dir)
{
- QFile templatefile(MAIN_CPPFILE_CONTENT);
- templatefile.open(QIODevice::ReadOnly);
- QTextStream stream(&templatefile);
- QString content = stream.readAll();
- templatefile.close();
+ FilePath srcDir = dir.pathAppended(MAIN_CPPFILE_DIR);
- FilePath filePath = dir.pathAppended(MAIN_CPPFILE_NAME);
- return GenerateCmake::queueFile(filePath, content);
+ QString cppContent = GenerateCmake::readTemplate(MAIN_CPPFILE_TEMPLATE_PATH);
+ FilePath cppFilePath = srcDir.pathAppended(MAIN_CPPFILE_NAME);
+ bool cppOk = GenerateCmake::queueFile(cppFilePath, cppContent);
+
+ QString modulesAsPlugins;
+ for (const QString &moduleName : GenerateCmakeLists::moduleNames)
+ modulesAsPlugins.append(
+ QString(MAIN_CPPFILE_HEADER_PLUGIN_LINE).arg(moduleName + "plugin"));
+
+ QString headerContent = GenerateCmake::readTemplate(MAIN_CPPFILE_HEADER_TEMPLATE_PATH)
+ .arg(modulesAsPlugins);
+ FilePath headerFilePath = srcDir.pathAppended(MAIN_CPPFILE_HEADER_NAME);
+ bool headerOk = GenerateCmake::queueFile(headerFilePath, headerContent);
+
+ return cppOk && headerOk;
}
-const char MAIN_QMLFILE_CONTENT[] = "import %1Qml\n\n%2 {\n}\n";
+const char MAIN_QMLFILE_PATH[] = ":/boilerplatetemplates/qmlprojectmainqml.tpl";
const char MAIN_QMLFILE_NAME[] = "main.qml";
bool generateMainQml(const FilePath &dir)
{
+ QString content = GenerateCmake::readTemplate(MAIN_QMLFILE_PATH);
FilePath filePath = dir.pathAppended(MAIN_QMLFILE_NAME);
- QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName();
- ProjectExplorer::RunConfiguration *runConfiguration = ProjectExplorer::SessionManager::startupRunConfiguration();
- QString mainClass;
-
- if (const auto aspect = runConfiguration->aspect())
- mainClass = FilePath::fromString(aspect->mainScript()).baseName();
-
- return GenerateCmake::queueFile(filePath, QString(MAIN_QMLFILE_CONTENT).arg(projectName).arg(mainClass));
+ return GenerateCmake::queueFile(filePath, content);
}
}
diff --git a/src/plugins/qmldesigner/generatecmakelists.h b/src/plugins/qmldesigner/generatecmakelists.h
index d1603a1860b..b9f225e9465 100644
--- a/src/plugins/qmldesigner/generatecmakelists.h
+++ b/src/plugins/qmldesigner/generatecmakelists.h
@@ -45,16 +45,17 @@ bool showConfirmationDialog(const Utils::FilePath &rootDir);
bool queueFile(const Utils::FilePath &filePath, const QString &fileContent);
bool writeFile(const GeneratableFile &file);
bool writeQueuedFiles();
+QString readTemplate(const QString &templatePath);
}
namespace GenerateCmakeLists {
+bool generateCmakes(const Utils::FilePath &rootDir);
void generateMainCmake(const Utils::FilePath &rootDir);
-void generateSubdirCmake(const Utils::FilePath &dir);
-QString generateModuleCmake(const Utils::FilePath &dir);
-QStringList processDirectory(const Utils::FilePath &dir);
+void generateImportCmake(const Utils::FilePath &dir);
+void generateModuleCmake(const Utils::FilePath &dir);
QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
-void createCmakeFile(const Utils::FilePath &filePath, const QString &content);
+void queueCmakeFile(const Utils::FilePath &filePath, const QString &content);
bool isFileBlacklisted(const QString &fileName);
}
namespace GenerateEntryPoints {
diff --git a/src/plugins/qmldesigner/qmlprojectmaincmakelists.tpl b/src/plugins/qmldesigner/qmlprojectmaincmakelists.tpl
new file mode 100644
index 00000000000..926f7b43be9
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlprojectmaincmakelists.tpl
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 3.18)
+
+project(%1 LANGUAGES CXX)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(CMAKE_AUTOMOC ON)
+
+find_package(Qt6 COMPONENTS Gui Qml Quick)
+add_executable(%1 src/main.cpp)
+
+target_link_libraries(%1 PRIVATE
+ Qt${QT_VERSION_MAJOR}::Core
+ Qt${QT_VERSION_MAJOR}::Gui
+ Qt${QT_VERSION_MAJOR}::Quick
+ Qt${QT_VERSION_MAJOR}::Qml
+)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/qmlmodules)
+
diff --git a/src/plugins/qmldesigner/qmlprojectmaincppheader.tpl b/src/plugins/qmldesigner/qmlprojectmaincppheader.tpl
new file mode 100644
index 00000000000..60cef09a82c
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlprojectmaincppheader.tpl
@@ -0,0 +1,8 @@
+/*
+ * This file is automatically generated by Qt Design Studio.
+ * Do not change.
+*/
+
+#include
+
+%1
diff --git a/src/plugins/qmldesigner/qmlprojectmainqml.tpl b/src/plugins/qmldesigner/qmlprojectmainqml.tpl
new file mode 100644
index 00000000000..fa8f6d1cc18
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlprojectmainqml.tpl
@@ -0,0 +1,6 @@
+import QtQuick
+import content
+
+App {
+}
+
diff --git a/src/plugins/qmldesigner/qmlprojectmodulecmakelists.tpl b/src/plugins/qmldesigner/qmlprojectmodulecmakelists.tpl
new file mode 100644
index 00000000000..46132d8c1a4
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlprojectmodulecmakelists.tpl
@@ -0,0 +1,11 @@
+### This file is automatically generated by Qt Design Studio.
+### Do not change
+
+%1
+
+qt_add_library(%2 STATIC)
+qt6_add_qml_module(%2
+ URI "%2"
+ VERSION 1.0
+%3
+)
diff --git a/src/plugins/qmldesigner/qmlprojectmodules.tpl b/src/plugins/qmldesigner/qmlprojectmodules.tpl
new file mode 100644
index 00000000000..2cae6017cc3
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlprojectmodules.tpl
@@ -0,0 +1,16 @@
+### This file is automatically generated by Qt Design Studio.
+### Do not change
+
+qt6_add_qml_module(%1
+ URI "Main"
+ VERSION 1.0
+ NO_PLUGIN
+ QML_FILES main.qml
+)
+
+add_subdirectory(content)
+add_subdirectory(imports)
+
+target_link_libraries(%1 PRIVATE
+%2
+)