aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmlprojectmanager
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qmlprojectmanager')
-rw-r--r--src/plugins/qmlprojectmanager/.clang-format50
-rw-r--r--src/plugins/qmlprojectmanager/CMakeLists.txt10
-rw-r--r--src/plugins/qmlprojectmanager/QmlProjectManager.json.in2
-rw-r--r--src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp7
-rw-r--r--src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.cpp7
-rw-r--r--src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.h2
-rw-r--r--src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp111
-rw-r--r--src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h16
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc24
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp45
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h31
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp620
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h75
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp168
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h51
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp174
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h51
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp422
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h77
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp180
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h47
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriter.cpp258
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriter.h101
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.cpp180
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.h25
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.cpp185
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.h25
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp668
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h80
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h42
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectappmainqml.tpl14
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectenvheader.tpl11
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincppheader.tpl8
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmainqml.tpl6
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl12
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl16
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/cmakelists_txt_shared.tpl16
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/cmakemodule_v1.tpl (renamed from src/plugins/qmlprojectmanager/cmakegen/gencmakemodule.tpl)3
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v0.tpl (renamed from src/plugins/qmlprojectmanager/cmakegen/gencmakeroot.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v1.tpl (renamed from src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincmakelists.tpl)28
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/environment_h.tpl24
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/import_qml_components_h.tpl (renamed from src/plugins/qmlprojectmanager/cmakegen/gencmakeheadercomponents.tpl)1
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/insight.tpl19
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v0.tpl (renamed from src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v1.tpl31
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/qmlcomponents.tpl36
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/qtquickcontrols2_conf.tpl7
-rw-r--r--src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp2
-rw-r--r--src/plugins/qmlprojectmanager/qmlmainfileaspect.h2
-rw-r--r--src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp4
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectconstants.h1
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp4
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager.qbs10
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectplugin.cpp35
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp6
55 files changed, 1444 insertions, 2586 deletions
diff --git a/src/plugins/qmlprojectmanager/.clang-format b/src/plugins/qmlprojectmanager/.clang-format
new file mode 100644
index 0000000000..366f82f76f
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/.clang-format
@@ -0,0 +1,50 @@
+Language: Cpp
+AccessModifierOffset: -4
+AlignEscapedNewlines: DontAlign
+AllowShortFunctionsOnASingleLine: Inline
+AlwaysBreakTemplateDeclarations: true # use with clang 19
+BinPackArguments: false
+BinPackParameters: false
+BraceWrapping:
+ AfterClass: true
+ AfterFunction: true
+ AfterStruct: true
+ SplitEmptyFunction: false
+ SplitEmptyRecord: false
+ SplitEmptyNamespace: false
+BreakBeforeBinaryOperators: All
+BreakBeforeBraces: Custom
+BreakConstructorInitializers: BeforeComma
+BreakInheritanceList: AfterComma
+# BreakTemplateDeclarations: Yes # use with clang 19
+ColumnLimit: 100
+IncludeCategories:
+ - Regex: 'Q.*'
+ Priority: 8
+ CaseSensitive: true
+IndentPPDirectives: AfterHash
+IndentWidth: 4
+KeepEmptyLinesAtTheStartOfBlocks: false
+# Do not add QT_BEGIN_NAMESPACE/QT_END_NAMESPACE as this will indent lines in between.
+ObjCBlockIndentWidth: 4
+PPIndentWidth: 2
+PackConstructorInitializers: Never
+PenaltyBreakAssignment: 500
+PenaltyBreakBeforeFirstCallParameter: 150
+PenaltyBreakComment: 500
+PenaltyBreakFirstLessLess: 400
+PenaltyBreakString: 600
+PenaltyExcessCharacter: 7
+PenaltyReturnTypeOnItsOwnLine: 300
+QualifierAlignment: Custom
+QualifierOrder: ['friend', 'inline', 'static', 'constexpr', 'const', 'type']
+ReferenceAlignment: Right
+ReflowComments: false
+SeparateDefinitionBlocks: Always
+SortUsingDeclarations: Lexicographic
+SpaceAfterCStyleCast: true
+SpaceAfterTemplateKeyword: false
+SpaceBeforeParens: ControlStatementsExceptControlMacros
+SpacesInContainerLiterals: false
+StatementAttributeLikeMacros: [emit]
+TabWidth: 4
diff --git a/src/plugins/qmlprojectmanager/CMakeLists.txt b/src/plugins/qmlprojectmanager/CMakeLists.txt
index ab96a5f7df..68bb545011 100644
--- a/src/plugins/qmlprojectmanager/CMakeLists.txt
+++ b/src/plugins/qmlprojectmanager/CMakeLists.txt
@@ -42,14 +42,10 @@ extend_qtc_plugin(QmlProjectManager
PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/cmakegen
SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/cmakegen
SOURCES
- checkablefiletreeitem.cpp checkablefiletreeitem.h
- cmakegeneratordialog.cpp cmakegeneratordialog.h
- cmakegeneratordialogtreemodel.cpp cmakegeneratordialogtreemodel.h
- cmakeprojectconverter.cpp cmakeprojectconverter.h
- cmakeprojectconverterdialog.cpp cmakeprojectconverterdialog.h
- generatecmakelists.cpp generatecmakelists.h
- generatecmakelistsconstants.h
cmakegenerator.cpp cmakegenerator.h
+ cmakewriter.cpp cmakewriter.h
+ cmakewriterv0.cpp cmakewriterv0.h
+ cmakewriterv1.cpp cmakewriterv1.h
boilerplate.qrc
)
diff --git a/src/plugins/qmlprojectmanager/QmlProjectManager.json.in b/src/plugins/qmlprojectmanager/QmlProjectManager.json.in
index 5df33015f4..18388275f3 100644
--- a/src/plugins/qmlprojectmanager/QmlProjectManager.json.in
+++ b/src/plugins/qmlprojectmanager/QmlProjectManager.json.in
@@ -14,7 +14,7 @@
],
"Category" : "Qt Quick",
"Description" : "Qt Quick support",
- "Url" : "http://www.qt.io",
+ "Url" : "https://www.qt.io",
${IDE_PLUGIN_DEPENDENCIES},
"Mimetypes" : [
diff --git a/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp b/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp
index 95cc859af5..82ba1fc2e4 100644
--- a/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp
+++ b/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp
@@ -14,7 +14,12 @@ const static QStringList imageFilesFilter{QStringLiteral("*.jpeg"),
QStringLiteral("*.png"),
QStringLiteral("*.svg"),
QStringLiteral("*.hdr"),
- QStringLiteral("*.ktx")};
+ QStringLiteral("*.ktx"),
+ QStringLiteral("*.bmp"),
+ QStringLiteral("*.ttf"),
+ QStringLiteral("*.tiff"),
+ QStringLiteral("*.webp"),
+ QStringLiteral("*.gif")};
QString jsonValueToString(const QJsonValue &val, int indentationLevel, bool indented);
diff --git a/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.cpp b/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.cpp
index eb6e6de177..5229d486ce 100644
--- a/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.cpp
+++ b/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.cpp
@@ -79,7 +79,7 @@ void QmlProjectItem::setupFileFilters()
connect(fileFilterItem.get(),
&FileFilterItem::filesChanged,
this,
- &QmlProjectItem::qmlFilesChanged);
+ &QmlProjectItem::filesChanged);
#endif
m_content.push_back(std::move(fileFilterItem));
};
@@ -105,10 +105,7 @@ void QmlProjectItem::setupFileFilters()
fileFilterItem->setDefaultDirectory(m_projectFile.parentDir().toString());
fileFilterItem->setDirectory(groupDir.toString());
#ifndef TESTS_ENABLED_QMLPROJECTITEM
- connect(fileFilterItem.get(),
- &FileFilterItem::filesChanged,
- this,
- &QmlProjectItem::qmlFilesChanged);
+ connect(fileFilterItem.get(), &FileFilterItem::filesChanged, this, &QmlProjectItem::filesChanged);
#endif
m_content.push_back(std::move(fileFilterItem));
};
diff --git a/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.h b/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.h
index 7d57ad2e60..5d0b520f14 100644
--- a/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.h
+++ b/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.h
@@ -92,7 +92,7 @@ public:
void setEnableCMakeGeneration(bool enable);
signals:
- void qmlFilesChanged(const QSet<QString> &, const QSet<QString> &);
+ void filesChanged(const QSet<QString> &, const QSet<QString> &);
private:
typedef QSharedPointer<QmlProjectItem> ShrdPtrQPI;
diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp
index a0b8263900..97b540ad7e 100644
--- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp
+++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp
@@ -6,8 +6,9 @@
#include "../qmlprojectconstants.h"
#include "../qmlprojectmanagertr.h"
#include "../qmlproject.h"
+#include "projectitem/qmlprojectitem.h"
+#include "projectnode/qmlprojectnodes.h"
-#include <QtCore5Compat/qtextcodec.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <coreplugin/actionmanager/actioncontainer.h>
@@ -30,18 +31,18 @@
#include <projectexplorer/kitaspects.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/projectmanager.h>
#include <projectexplorer/target.h>
-#include "projectexplorer/projectmanager.h"
-#include "projectitem/qmlprojectitem.h"
-#include "projectnode/qmlprojectnodes.h"
-
-#include "utils/algorithm.h"
-#include "utils/qtcassert.h"
+#include <utils/algorithm.h>
+#include <utils/filepath.h>
+#include <utils/filesystemwatcher.h>
+#include <utils/qtcassert.h>
-#include "texteditor/textdocument.h"
+#include <texteditor/textdocument.h>
#include <QAction>
+#include <QtCore5Compat/qtextcodec.h>
using namespace ProjectExplorer;
namespace QmlProjectManager {
@@ -93,6 +94,7 @@ QmlBuildSystem::QmlBuildSystem(Target *target)
connect(target->project(), &Project::projectFileIsDirty, this, [this] {
refresh(RefreshOptions::Project);
m_cmakeGen->initialize(qmlProject());
+ m_cmakeGen->updateMenuAction();
updateMcuBuildStep(project()->activeTarget(), qtForMCUs());
});
@@ -140,8 +142,6 @@ void QmlBuildSystem::registerMenuButtons()
//wip:
bool QmlBuildSystem::updateProjectFile()
{
- qDebug() << "debug#1-mainfilepath" << mainFilePath();
-
QFile file(mainFilePath().fileName().append("project-test"));
if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
qCritical() << "Cannot open Qml Project file for editing!";
@@ -219,17 +219,56 @@ void QmlBuildSystem::refresh(RefreshOptions options)
void QmlBuildSystem::initProjectItem()
{
m_projectItem.reset(new QmlProjectItem{projectFilePath()});
- connect(m_projectItem.get(),
- &QmlProjectItem::qmlFilesChanged,
- this,
- &QmlBuildSystem::refreshFiles);
- connect(m_projectItem.get(),
- &QmlProjectItem::qmlFilesChanged,
+ connect(m_projectItem.data(), &QmlProjectItem::filesChanged, this, &QmlBuildSystem::refreshFiles);
+ connect(m_projectItem.data(),
+ &QmlProjectItem::filesChanged,
m_cmakeGen,
&GenerateCmake::CMakeGenerator::update);
m_cmakeGen->setEnabled(m_projectItem->enableCMakeGeneration());
+
+ initMcuProjectItems();
+}
+
+void QmlBuildSystem::initMcuProjectItems()
+{
+ m_mcuProjectItems.clear();
+ m_mcuProjectFilesWatcher.clear();
+
+ Utils::FilePath projectDir = projectFilePath().parentDir();
+ // traverse the project dir and find all other mcu projects (.qmlproject files) in the project tree
+ // and add them to the m_mcuProjectItems vector
+ QDirIterator it(projectDir.toFSPathString(), QDir::Files, QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ it.next();
+ if (it.fileInfo().suffix() == "qmlproject" && it.filePath() != projectFilePath().toString()) {
+ auto qmlProjectItem = QSharedPointer<QmlProjectItem>(
+ new QmlProjectItem{Utils::FilePath::fromString(it.filePath())});
+
+ m_mcuProjectItems.append(qmlProjectItem);
+ connect(qmlProjectItem.data(),
+ &QmlProjectItem::filesChanged,
+ this,
+ &QmlBuildSystem::refreshFiles);
+ connect(qmlProjectItem.data(),
+ &QmlProjectItem::filesChanged,
+ m_cmakeGen,
+ &GenerateCmake::CMakeGenerator::update);
+
+ m_mcuProjectFilesWatcher.addFile(it.filePath(),
+ Utils::FileSystemWatcher::WatchModifiedDate);
+
+ connect(&m_mcuProjectFilesWatcher,
+ &Utils::FileSystemWatcher::fileChanged,
+ this,
+ [this](const QString &file) {
+ Q_UNUSED(file)
+ initMcuProjectItems();
+ refresh(RefreshOptions::Files);
+ });
+ }
+ }
}
void QmlBuildSystem::parseProjectFiles()
@@ -238,7 +277,6 @@ void QmlBuildSystem::parseProjectFiles()
modelManager->updateSourceFiles(m_projectItem->files(), true);
}
-
const QString mainFileName = m_projectItem->mainFile();
if (!mainFileName.isEmpty()) {
Utils::FilePath mainFilePath = canonicalProjectDir().resolvePath(mainFileName);
@@ -264,6 +302,16 @@ void QmlBuildSystem::generateProjectTree()
: FileNode::fileTypeForFileName(file);
newRoot->addNestedNode(std::make_unique<FileNode>(file, fileType));
}
+
+ for (const auto &mcuProjectItem : m_mcuProjectItems) {
+ for (const auto &file : mcuProjectItem->files()) {
+ // newRoot->addNestedNode(std::make_unique<FileNode>(file, FileType::Project));
+ const FileType fileType = (file == projectFilePath())
+ ? FileType::Project
+ : FileNode::fileTypeForFileName(file);
+ newRoot->addNestedNode(std::make_unique<FileNode>(file, fileType));
+ }
+ }
newRoot->addNestedNode(std::make_unique<FileNode>(projectFilePath(), FileType::Project));
setRootProjectNode(std::move(newRoot));
@@ -501,6 +549,17 @@ void QmlBuildSystem::setPrimaryLanguage(QString language)
m_projectItem->setPrimaryLanguage(language);
}
+bool QmlBuildSystem::enableCMakeGeneration() const
+{
+ return m_projectItem->enableCMakeGeneration();
+}
+
+void QmlBuildSystem::setEnableCMakeGeneration(bool enable)
+{
+ if (enable != enableCMakeGeneration())
+ m_projectItem->setEnableCMakeGeneration(enable);
+}
+
void QmlBuildSystem::refreshFiles(const QSet<QString> & /*added*/, const QSet<QString> &removed)
{
if (m_blockFilesUpdate) {
@@ -522,7 +581,7 @@ void QmlBuildSystem::refreshFiles(const QSet<QString> & /*added*/, const QSet<QS
QVariant QmlBuildSystem::additionalData(Utils::Id id) const
{
if (id == Constants::customFileSelectorsData)
- return customFileSelectors();
+ return fileSelectors();
if (id == Constants::supportedLanguagesData)
return supportedLanguages();
if (id == Constants::primaryLanguageData)
@@ -535,8 +594,6 @@ QVariant QmlBuildSystem::additionalData(Utils::Id id) const
return qt6Project();
if (id == Constants::mainFilePath)
return mainFilePath().toString();
- if (id == Constants::customImportPaths)
- return customImportPaths();
if (id == Constants::canonicalProjectDir)
return canonicalProjectDir().toString();
return {};
@@ -620,12 +677,7 @@ Utils::EnvironmentItems QmlBuildSystem::environment() const
return m_projectItem->environment();
}
-QStringList QmlBuildSystem::customImportPaths() const
-{
- return m_projectItem->importPaths();
-}
-
-QStringList QmlBuildSystem::customFileSelectors() const
+QStringList QmlBuildSystem::fileSelectors() const
{
return m_projectItem->fileSelectors();
}
@@ -670,7 +722,7 @@ QStringList QmlBuildSystem::importPaths() const
return m_projectItem->importPaths();
}
-QStringList QmlBuildSystem::absoluteImportPaths()
+QStringList QmlBuildSystem::absoluteImportPaths() const
{
return Utils::transform<QStringList>(m_projectItem->importPaths(), [&](const QString &importPath) {
Utils::FilePath filePath = Utils::FilePath::fromString(importPath);
@@ -680,11 +732,6 @@ QStringList QmlBuildSystem::absoluteImportPaths()
});
}
-Utils::FilePaths QmlBuildSystem::files() const
-{
- return m_projectItem->files();
-}
-
QString QmlBuildSystem::versionQt() const
{
return m_projectItem->versionQt();
diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h
index 524af5cd1b..d91f60cdd1 100644
--- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h
+++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h
@@ -6,7 +6,9 @@
#pragma once
#include "../qmlprojectmanager_global.h"
+
#include <projectexplorer/buildsystem.h>
+#include <utils/filesystemwatcher.h>
#include "qmlprojectmanager/cmakegen/cmakegenerator.h"
@@ -72,9 +74,8 @@ public:
Utils::EnvironmentItems environment() const;
QStringList importPaths() const;
- QStringList absoluteImportPaths();
- QStringList customImportPaths() const;
- QStringList customFileSelectors() const;
+ QStringList absoluteImportPaths() const;
+ QStringList fileSelectors() const;
bool multilanguageSupport() const;
QStringList supportedLanguages() const;
@@ -83,12 +84,14 @@ public:
QString primaryLanguage() const;
void setPrimaryLanguage(QString language);
+ bool enableCMakeGeneration() const;
+ void setEnableCMakeGeneration(bool enable);
+
bool forceFreeType() const;
bool widgetApp() const;
QStringList shaderToolArgs() const;
QStringList shaderToolFiles() const;
- Utils::FilePaths files() const;
QString versionQt() const;
QString versionQtQuick() const;
@@ -114,10 +117,15 @@ private:
const Utils::FilePath &mainFilePath,
const QString &oldFile);
+ // this is the main project item
QSharedPointer<QmlProjectItem> m_projectItem;
+ // these are the mcu project items which can be found in the project tree
+ QList<QSharedPointer<QmlProjectItem>> m_mcuProjectItems;
+ Utils::FileSystemWatcher m_mcuProjectFilesWatcher;
bool m_blockFilesUpdate = false;
void initProjectItem();
+ void initMcuProjectItems();
void parseProjectFiles();
void generateProjectTree();
diff --git a/src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc b/src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc
index 10fab59838..4960324ab7 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc
+++ b/src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc
@@ -1,15 +1,15 @@
<RCC>
- <qresource prefix="/boilerplatetemplates">
- <file>gencmakeroot.tpl</file>
- <file>gencmakemodule.tpl</file>
- <file>gencmakeheadercomponents.tpl</file>
- <file>qmlprojectmaincpp.tpl</file>
- <file>qmlprojectmaincppheader.tpl</file>
- <file>qmlprojectenvheader.tpl</file>
- <file>qmlprojectmodules.tpl</file>
- <file>qmlprojectmaincmakelists.tpl</file>
- <file>qmlprojectmodulecmakelists.tpl</file>
- <file>qmlprojectmainqml.tpl</file>
- <file>qmlprojectappmainqml.tpl</file>
+ <qresource prefix="/templates">
+ <file alias="cmakeroot_v0">templates/cmakeroot_v0.tpl</file>
+ <file alias="cmakeroot_v1">templates/cmakeroot_v1.tpl</file>
+ <file alias="main_cpp_v0">templates/main_cpp_v0.tpl</file>
+ <file alias="main_cpp_v1">templates/main_cpp_v1.tpl</file>
+ <file alias="cmakemodule_v1">templates/cmakemodule_v1.tpl</file>
+ <file alias="insight">templates/insight.tpl</file>
+ <file alias="qmlcomponents">templates/qmlcomponents.tpl</file>
+ <file alias="environment_h">templates/environment_h.tpl</file>
+ <file alias="import_qml_components_h">templates/import_qml_components_h.tpl</file>
+ <file alias="qtquickcontrols_conf">templates/qtquickcontrols2_conf.tpl</file>
+ <file alias="cmake_shared">templates/cmakelists_txt_shared.tpl</file>
</qresource>
</RCC>
diff --git a/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp b/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp
deleted file mode 100644
index 9eb45d9150..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "checkablefiletreeitem.h"
-
-using namespace Utils;
-
-namespace QmlProjectManager {
-
-CheckableFileTreeItem::CheckableFileTreeItem(const FilePath &filePath)
- :QStandardItem(filePath.toString())
-{
- Qt::ItemFlags itemFlags = flags();
- if (!isDir())
- itemFlags |= Qt::ItemIsUserCheckable;
- itemFlags &= ~(Qt::ItemIsEditable | Qt::ItemIsSelectable);
- setFlags(itemFlags);
-}
-
-const FilePath CheckableFileTreeItem::toFilePath() const
-{
- return FilePath::fromString(text());
-}
-
-bool CheckableFileTreeItem::isFile() const
-{
- return FilePath::fromString(text()).isFile();
-}
-
-bool CheckableFileTreeItem::isDir() const
-{
- return FilePath::fromString(text()).isDir();
-}
-
-void CheckableFileTreeItem::setChecked(bool checked)
-{
- this->checked = checked;
-}
-
-bool CheckableFileTreeItem::isChecked() const
-{
- return this->checked;
-}
-
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h b/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h
deleted file mode 100644
index c3c5145301..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#ifndef CHECKABLEFILETREEITEM_H
-#define CHECKABLEFILETREEITEM_H
-
-#include <utils/fileutils.h>
-
-#include <QStandardItem>
-
-namespace QmlProjectManager {
-
-class CheckableFileTreeItem : public QStandardItem
-{
-public:
- explicit CheckableFileTreeItem(const Utils::FilePath &text = Utils::FilePath());
-
- const Utils::FilePath toFilePath() const;
- bool isFile() const;
- bool isDir() const;
-
- bool isChecked() const;
- void setChecked(bool checked);
-
-private:
- bool checked;
-};
-
-} //QmlProjectManager
-
-#endif // CHECKABLEFILETREEITEM_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp
index 736ac04ec6..9ae576ec35 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp
@@ -2,12 +2,23 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cmakegenerator.h"
-#include "generatecmakelistsconstants.h"
+
+#include "qmlprojectmanager/qmlproject.h"
+#include "qmlprojectmanager/qmlprojectconstants.h"
+#include "qmlprojectmanager/qmlprojectmanagertr.h"
#include "projectexplorer/projectmanager.h"
#include "projectexplorer/projectnodes.h"
-#include "qmlprojectmanager/qmlproject.h"
+#include "projectexplorer/taskhub.h"
+
+#include "utils/filenamevalidatinglineedit.h"
+#include "coreplugin/actionmanager/actionmanager.h"
+#include "coreplugin/actionmanager/actioncontainer.h"
+
+#include <QDirIterator>
+#include <QFileInfo>
+#include <QMenu>
#include <QRegularExpression>
#include <set>
@@ -16,37 +27,109 @@ namespace QmlProjectManager {
namespace GenerateCmake {
-const char TEMPLATE_CMAKELISTS_ROOT[] = ":/boilerplatetemplates/gencmakeroot.tpl";
-const char TEMPLATE_CMAKELISTS_MODULE[] = ":/boilerplatetemplates/gencmakemodule.tpl";
+void CMakeGenerator::createMenuAction(QObject *parent)
+{
+ Core::ActionContainer *fileMenu = Core::ActionManager::actionContainer(
+ Core::Constants::M_FILE);
+ Core::ActionContainer *exportMenu = Core::ActionManager::createMenu(
+ QmlProjectManager::Constants::EXPORT_MENU);
-const char TEMPLATE_SOURCE_MAIN[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
-const char TEMPLATE_HEADER_IMPORT_COMPS[] = ":/boilerplatetemplates/gencmakeheadercomponents.tpl";
-const char TEMPLATE_HEADER_IMPORT_PLUGINS[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl";
-const char TEMPLATE_HEADER_ENVIRONMENT[] = ":/boilerplatetemplates/qmlprojectenvheader.tpl";
+ exportMenu->menu()->setTitle(Tr::tr("Export Project"));
+ exportMenu->appendGroup(QmlProjectManager::Constants::G_EXPORT_GENERATE);
+ fileMenu->addMenu(exportMenu, Core::Constants::G_FILE_EXPORT);
-const char DO_NOT_EDIT_FILE_COMMENT[]
- = "### This file is automatically generated by Qt Design Studio.\n"
- "### Do not change\n\n";
+ auto action = new QAction(Tr::tr("Enable Automatic CMake Generation"), parent);
+ action->setEnabled(false);
+ action->setCheckable(true);
-const char TEMPLATE_BIG_RESOURCES[] = R"(
-qt6_add_resources(%1 %2
- BIG_RESOURCES
- PREFIX "%3"
- VERSION 1.0
- FILES %4
-))";
+ Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.EnableCMakeGeneration");
+ exportMenu->addAction(cmd, QmlProjectManager::Constants::G_EXPORT_GENERATE);
-const char TEMPLATE_LINK_LIBRARIES[] = R"(
-target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
-%3
-))";
+ QObject::connect(
+ ProjectExplorer::ProjectManager::instance(),
+ &ProjectExplorer::ProjectManager::startupProjectChanged,
+ [action]() {
+ if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem()) {
+ action->setEnabled(!buildSystem->qtForMCUs());
+ action->setChecked(buildSystem->enableCMakeGeneration());
+ }
+ }
+ );
+
+ QObject::connect(action, &QAction::toggled, [](bool checked) {
+ if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem())
+ buildSystem->setEnableCMakeGeneration(checked);
+ });
+}
+
+void CMakeGenerator::logIssue(ProjectExplorer::Task::TaskType type, const QString &text, const Utils::FilePath &file)
+{
+ ProjectExplorer::BuildSystemTask task(type, text, file);
+ ProjectExplorer::TaskHub::addTask(task);
+ ProjectExplorer::TaskHub::requestPopup();
+}
+
+void CMakeGenerator::updateMenuAction()
+{
+ QTC_ASSERT(buildSystem(), return);
+
+ Core::Command *cmd = Core::ActionManager::command("QmlProject.EnableCMakeGeneration");
+ if (!cmd)
+ return;
+
+ QAction *action = cmd->action();
+ if (!action)
+ return;
+
+ bool enabled = buildSystem()->enableCMakeGeneration();
+ if (enabled != action->isChecked())
+ action->setChecked(enabled);
+}
CMakeGenerator::CMakeGenerator(QmlBuildSystem *bs, QObject *parent)
: QObject(parent)
- , m_root(std::make_shared<Node>())
, m_buildSystem(bs)
+ , m_root(std::make_shared<Node>())
{}
+const QmlProject *CMakeGenerator::qmlProject() const
+{
+ if (m_buildSystem)
+ return m_buildSystem->qmlProject();
+ return nullptr;
+}
+
+const QmlBuildSystem *CMakeGenerator::buildSystem() const
+{
+ return m_buildSystem;
+}
+
+bool CMakeGenerator::findFile(const Utils::FilePath& file) const
+{
+ return findFile(m_root, file);
+}
+
+bool CMakeGenerator::isRootNode(const NodePtr &node) const
+{
+ return node->name == "Main";
+}
+
+bool CMakeGenerator::hasChildModule(const NodePtr &node) const
+{
+ for (const NodePtr &child : node->subdirs) {
+ if (child->type == Node::Type::Module)
+ return true;
+ if (hasChildModule(child))
+ return true;
+ }
+ return false;
+}
+
+QString CMakeGenerator::projectName() const
+{
+ return m_projectName;
+}
+
void CMakeGenerator::setEnabled(bool enabled)
{
m_enabled = enabled;
@@ -57,11 +140,11 @@ void CMakeGenerator::initialize(QmlProject *project)
if (!m_enabled)
return;
- m_srcs.clear();
m_moduleNames.clear();
+ m_writer = CMakeWriter::create(this);
m_root = std::make_shared<Node>();
- m_root->module = true;
+ m_root->type = Node::Type::App;
m_root->uri = QString("Main");
m_root->name = QString("Main");
m_root->dir = project->rootProjectDirectory();
@@ -73,7 +156,9 @@ void CMakeGenerator::initialize(QmlProject *project)
parseSourceTree();
createCMakeFiles(m_root);
- createEntryPoints(m_root);
+ createSourceFiles();
+
+ compareWithFileSystem(m_root);
}
void CMakeGenerator::update(const QSet<QString> &added, const QSet<QString> &removed)
@@ -81,304 +166,117 @@ void CMakeGenerator::update(const QSet<QString> &added, const QSet<QString> &rem
if (!m_enabled)
return;
+ QTC_ASSERT(m_writer, return);
+
std::set<NodePtr> dirtyModules;
for (const QString &add : added) {
const Utils::FilePath path = Utils::FilePath::fromString(add);
- if (auto node = findOrCreateNode(m_root, path)) {
+ if (ignore(path.parentDir()))
+ continue;
+
+ if (auto node = findOrCreateNode(m_root, path.parentDir())) {
insertFile(node, path);
if (auto module = findModuleFor(node))
dirtyModules.insert(module);
} else {
- qDebug() << "CmakeGen: Failed to find Folder node " << path;
+ QString text("Failed to find Folder for file");
+ logIssue(ProjectExplorer::Task::Error, text, path);
}
}
for (const QString &remove : removed) {
const Utils::FilePath path = Utils::FilePath::fromString(remove);
- if (auto node = findNode(m_root, path)) {
+ if (auto node = findNode(m_root, path.parentDir())) {
removeFile(node, path);
if (auto module = findModuleFor(node))
dirtyModules.insert(module);
}
}
- for (auto module : dirtyModules)
- createModuleCMakeFile(module);
-}
-
-std::vector<Utils::FilePath> CMakeGenerator::files(const NodePtr &node,
- const FileGetter &getter) const
-{
- std::vector<Utils::FilePath> out = getter(node);
- for (const CMakeGenerator::NodePtr &child : node->subdirs) {
- if (child->module)
- continue;
-
- auto childFiles = files(child, getter);
- out.insert(out.end(), childFiles.begin(), childFiles.end());
- }
- return out;
-}
-
-std::vector<Utils::FilePath> CMakeGenerator::qmlFiles(const NodePtr &node) const
-{
- return files(node, [](const NodePtr &n) { return n->files; });
-}
-
-std::vector<Utils::FilePath> CMakeGenerator::singletons(const NodePtr &node) const
-{
- return files(node, [](const NodePtr &n) { return n->singletons; });
-}
-
-std::vector<Utils::FilePath> CMakeGenerator::resources(const NodePtr &node) const
-{
- return files(node, [](const NodePtr &n) { return n->resources; });
+ createCMakeFiles(m_root);
+ createSourceFiles();
}
-std::vector<Utils::FilePath> CMakeGenerator::sources(const NodePtr &node) const
+bool CMakeGenerator::isQml(const Utils::FilePath &path) const
{
- return files(node, [](const NodePtr &n) { return n->sources; });
+ const QString suffix = path.suffix();
+ return suffix == "qml" || suffix == "ui.qml";
}
-void CMakeGenerator::createCMakeFiles(const NodePtr &node) const
-{
- if (isRootNode(node))
- createMainCMakeFile(node);
-
- if (node->module || hasChildModule(node))
- createModuleCMakeFile(node);
-
- for (const NodePtr &n : node->subdirs)
- createCMakeFiles(n);
-}
-
-void CMakeGenerator::createMainCMakeFile(const NodePtr &node) const
+bool CMakeGenerator::isResource(const Utils::FilePath &path) const
{
- const QString appName = m_projectName + "App";
-
- const QString qtcontrolsConfFile = makeEnvironmentVariable(Constants::ENV_VARIABLE_CONTROLCONF);
-
- QString fileSection = "";
- if (!qtcontrolsConfFile.isEmpty())
- fileSection = QString(" FILES\n %1").arg(qtcontrolsConfFile);
-
- const QString fileTemplate = readTemplate(TEMPLATE_CMAKELISTS_ROOT);
- const QString fileContent = fileTemplate.arg(appName, m_srcs.join(" "), fileSection);
-
- const Utils::FilePath file = node->dir.pathAppended("CMakeLists.txt");
- writeFile(file, fileContent);
+ static const QStringList suffixes = {
+ "json", "mesh", "dae", "qad", "hints", "png", "hdr", "ttf", "jpg",
+ "jpeg", "js", "qsb", "frag", "frag.qsb", "vert", "vert.qsb", "svg",
+ "ktx", "bmp", "gif", "webp", "tiff"};
+ return suffixes.contains(path.suffix(), Qt::CaseInsensitive);
}
-void CMakeGenerator::createModuleCMakeFile(const NodePtr &node) const
+bool CMakeGenerator::ignore(const Utils::FilePath &path) const
{
- Utils::FilePath writeToFile = node->dir.pathAppended("CMakeLists.txt");
-
- if (!node->module && hasChildModule(node)) {
- QString content(DO_NOT_EDIT_FILE_COMMENT);
- content.append(makeSubdirectoriesBlock(node));
- writeFile(writeToFile, content);
- return;
- }
-
- QString templatePrefix;
- templatePrefix.append(makeSubdirectoriesBlock(node));
- templatePrefix.append(makeSingletonBlock(node));
-
- auto [resources, bigResources] = makeResourcesBlocks(node);
- QString moduleContent;
- moduleContent.append(makeQmlFilesBlock(node));
- moduleContent.append(resources);
-
- QString templatePostfix;
- templatePostfix.append(bigResources);
-
- if (isRootNode(node)) {
- writeToFile = node->dir.pathAppended("qmlModules");
- QString pluginNames;
- for (const QString &moduleName : m_moduleNames)
- pluginNames.append(" " + moduleName + "plugin\n");
-
- templatePostfix += QString::fromUtf8(TEMPLATE_LINK_LIBRARIES, -1).arg(pluginNames);
- }
-
- const QString fileTemplate = readTemplate(TEMPLATE_CMAKELISTS_MODULE);
- const QString fileContent
- = fileTemplate.arg(node->name, node->uri, templatePrefix, moduleContent, templatePostfix);
+ if (path.isFile()) {
+ static const QStringList suffixes = { "hints" };
+ return suffixes.contains(path.suffix(), Qt::CaseInsensitive);
+ } else if (path.isDir()) {
+ if (!m_root->dir.exists())
+ return true;
- writeFile(writeToFile, fileContent);
-}
+ static const QStringList fileNames = { "CMakeCache.txt", "build.ninja" };
-void CMakeGenerator::createEntryPoints(const NodePtr &node) const
-{
- createMainCppFile(node);
-}
-
-void CMakeGenerator::createMainCppFile(const NodePtr &node) const
-{
- const Utils::FilePath srcDir = node->dir.pathAppended(Constants::DIRNAME_CPP);
- if (!srcDir.exists()) {
- srcDir.createDir();
-
- const Utils::FilePath componentsHeaderPath = srcDir.pathAppended(
- "import_qml_components_plugins.h");
-
- const QString componentsHeaderContent = readTemplate(TEMPLATE_HEADER_IMPORT_COMPS);
- writeFile(componentsHeaderPath, componentsHeaderContent);
-
- const Utils::FilePath cppFilePath = srcDir.pathAppended("main.cpp");
- const QString cppContent = readTemplate(TEMPLATE_SOURCE_MAIN);
- writeFile(cppFilePath, cppContent);
-
- const Utils::FilePath envHeaderPath = srcDir.pathAppended("app_environment.h");
- if (m_buildSystem) {
- QString environment;
- const QString qtcontrolsConfFile = makeEnvironmentVariable(
- Constants::ENV_VARIABLE_CONTROLCONF);
- for (Utils::EnvironmentItem &envItem : m_buildSystem->environment()) {
- QString key = envItem.name;
- QString value = envItem.value;
- if (value == qtcontrolsConfFile)
- value.prepend(":/");
- environment.append(QString(" qputenv(\"%1\", \"%2\");\n").arg(key).arg(value));
+ Utils::FilePath dir = path;
+ while (dir.isChildOf(m_root->dir)) {
+ for (const QString& fileName : fileNames) {
+ Utils::FilePath checkFile = dir.pathAppended(fileName);
+ if (checkFile.exists())
+ return true;
}
- const QString envHeaderContent
- = readTemplate(TEMPLATE_HEADER_ENVIRONMENT).arg(environment);
- writeFile(envHeaderPath, envHeaderContent);
+ dir = dir.parentDir();
}
}
-
- QString moduleContent;
- for (const QString &module : m_moduleNames)
- moduleContent.append(QString("Q_IMPORT_QML_PLUGIN(%1)\n").arg(module + "Plugin"));
-
- const QString headerContent = readTemplate(TEMPLATE_HEADER_IMPORT_PLUGINS).arg(moduleContent);
- const Utils::FilePath headerFilePath = srcDir.pathAppended("import_qml_plugins.h");
- writeFile(headerFilePath, headerContent);
-}
-
-void CMakeGenerator::writeFile(const Utils::FilePath &path, const QString &content) const
-{
- QFile fileHandle(path.toString());
- fileHandle.open(QIODevice::WriteOnly);
- QTextStream stream(&fileHandle);
- stream << content;
- fileHandle.close();
-}
-
-QString CMakeGenerator::makeRelative(const NodePtr &node, const Utils::FilePath &path) const
-{
- const QString dir = node->dir.toString();
- return "\"" + Utils::FilePath::calcRelativePath(path.toString(), dir) + "\"";
-}
-
-QString CMakeGenerator::makeEnvironmentVariable(const QString &key) const
-{
- QString value;
- if (m_buildSystem) {
- auto envItems = m_buildSystem->environment();
- auto confEnv = std::find_if(envItems.begin(),
- envItems.end(),
- [key](Utils::EnvironmentItem &item) { return item.name == key; });
- if (confEnv != envItems.end())
- value = confEnv->value;
- }
- return value;
-}
-
-QString CMakeGenerator::makeSingletonBlock(const NodePtr &node) const
-{
- const QString setProperties(
- "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n");
-
- QString str;
- for (const Utils::FilePath &path : node->singletons)
- str.append(setProperties.arg(path.fileName()).arg("QT_QML_SINGLETON_TYPE").arg("true"));
- return str;
-}
-
-QString CMakeGenerator::makeSubdirectoriesBlock(const NodePtr &node) const
-{
- QString str;
- for (const NodePtr &n : node->subdirs) {
- if (n->module || hasChildModule(n))
- str.append(QString("add_subdirectory(%1)\n").arg(n->dir.fileName()));
- }
- return str;
+ return false;
}
-QString CMakeGenerator::makeQmlFilesBlock(const NodePtr &node) const
+void CMakeGenerator::createCMakeFiles(const NodePtr &node) const
{
- QString qmlFileContent;
- for (const Utils::FilePath &path : qmlFiles(node))
- qmlFileContent.append(QString(" %1\n").arg(makeRelative(node, path)));
+ QTC_ASSERT(m_writer, return);
- if (isRootNode(node) && qmlFileContent.isEmpty())
- qmlFileContent.append(QString(" %1\n").arg("\"main.qml\""));
+ if (isRootNode(node))
+ m_writer->writeRootCMakeFile(node);
- QString str;
- if (!qmlFileContent.isEmpty())
- str.append(QString(" QML_FILES\n%1").arg(qmlFileContent));
+ if (node->type == Node::Type::Module || (hasChildModule(node)))
+ m_writer->writeModuleCMakeFile(node, m_root);
- return str;
+ for (const NodePtr &n : node->subdirs)
+ createCMakeFiles(n);
}
-std::tuple<QString, QString> CMakeGenerator::makeResourcesBlocks(const NodePtr &node) const
+void CMakeGenerator::createSourceFiles() const
{
- QString resourcesOut;
- QString bigResourcesOut;
-
- QString resourceFiles;
- std::vector<QString> bigResources;
- for (const Utils::FilePath &path : resources(node)) {
- if (path.fileSize() > 5000000) {
- bigResources.push_back(makeRelative(node, path));
- continue;
- }
- resourceFiles.append(QString(" %1\n").arg(makeRelative(node, path)));
- }
+ QTC_ASSERT(m_writer, return);
- if (!resourceFiles.isEmpty())
- resourcesOut.append(QString(" RESOURCES\n%1").arg(resourceFiles));
-
- QString templatePostfix;
- if (!bigResources.empty()) {
- QString resourceContent;
- for (const QString &res : bigResources)
- resourceContent.append(QString("\n %1").arg(res));
-
- const QString prefixPath = QString(node->uri).replace('.', '/');
- const QString prefix = "/qt/qml/" + prefixPath;
- const QString resourceName = node->name + "BigResource";
-
- bigResourcesOut = QString::fromUtf8(TEMPLATE_BIG_RESOURCES, -1)
- .arg(node->name, resourceName, prefix, resourceContent);
+ NodePtr sourceNode = {};
+ for (const NodePtr &child : m_root->subdirs) {
+ if (child->name == m_writer->sourceDirName())
+ sourceNode = child;
}
- return {resourcesOut, bigResourcesOut};
-}
-
-QString CMakeGenerator::readTemplate(const QString &templatePath) const
-{
- QFile templatefile(templatePath);
- templatefile.open(QIODevice::ReadOnly);
- QTextStream stream(&templatefile);
- QString content = stream.readAll();
- templatefile.close();
- return content;
+ if (sourceNode)
+ m_writer->writeSourceFiles(sourceNode, m_root);
}
void CMakeGenerator::readQmlDir(const Utils::FilePath &filePath, NodePtr &node) const
{
- node->module = true;
+ node->type = Node::Type::Module;
QFile f(filePath.toString());
f.open(QIODevice::ReadOnly);
QTextStream stream(&f);
Utils::FilePath dir = filePath.parentDir();
+ static const QRegularExpression whitespaceRegex("\\s+");
while (!stream.atEnd()) {
const QString line = stream.readLine();
- const QStringList tokenizedLine = line.split(QRegularExpression("\\s+"));
+ const QStringList tokenizedLine = line.split(whitespaceRegex);
const QString maybeFileName = tokenizedLine.last();
if (tokenizedLine.first().compare("module", Qt::CaseInsensitive) == 0) {
node->uri = tokenizedLine.last();
@@ -392,11 +290,11 @@ void CMakeGenerator::readQmlDir(const Utils::FilePath &filePath, NodePtr &node)
f.close();
}
-CMakeGenerator::NodePtr CMakeGenerator::findModuleFor(const NodePtr &node) const
+NodePtr CMakeGenerator::findModuleFor(const NodePtr &node) const
{
NodePtr current = node;
while (current->parent) {
- if (current->module)
+ if (current->type == Node::Type::Module)
return current;
current = current->parent;
@@ -404,11 +302,10 @@ CMakeGenerator::NodePtr CMakeGenerator::findModuleFor(const NodePtr &node) const
return nullptr;
}
-CMakeGenerator::NodePtr CMakeGenerator::findNode(NodePtr &node, const Utils::FilePath &path) const
+NodePtr CMakeGenerator::findNode(NodePtr &node, const Utils::FilePath &path) const
{
- const Utils::FilePath parentDir = path.parentDir();
for (NodePtr &child : node->subdirs) {
- if (child->dir == parentDir)
+ if (child->dir == path)
return child;
if (path.isChildOf(child->dir))
return findNode(child, path);
@@ -416,8 +313,7 @@ CMakeGenerator::NodePtr CMakeGenerator::findNode(NodePtr &node, const Utils::Fil
return nullptr;
}
-CMakeGenerator::NodePtr CMakeGenerator::findOrCreateNode(NodePtr &node,
- const Utils::FilePath &path) const
+NodePtr CMakeGenerator::findOrCreateNode(NodePtr &node, const Utils::FilePath &path) const
{
if (auto found = findNode(node, path))
return found;
@@ -425,31 +321,73 @@ CMakeGenerator::NodePtr CMakeGenerator::findOrCreateNode(NodePtr &node,
if (!path.isChildOf(node->dir))
return nullptr;
- const Utils::FilePath parentDir = path.parentDir();
- const Utils::FilePath relative = parentDir.relativeChildPath(node->dir);
- const QChar separator = relative.pathComponentSeparator();
- const QList<QStringView> components = relative.pathView().split(separator);
+ auto findSubDir = [](NodePtr &node, const Utils::FilePath &path) -> NodePtr {
+ for (NodePtr child : node->subdirs) {
+ if (child->dir == path)
+ return child;
+ }
+ return nullptr;
+ };
- NodePtr last = node;
+ const Utils::FilePath relative = path.relativeChildPath(node->dir);
+ const QList<QStringView> components = relative.pathView().split('/');
+
+ NodePtr lastNode = node;
for (const auto &comp : components) {
+
+ Utils::FilePath subPath = lastNode->dir.pathAppended(comp.toString());
+ if (NodePtr sub = findSubDir(lastNode, subPath)) {
+ lastNode = sub;
+ continue;
+ }
NodePtr newNode = std::make_shared<Node>();
- newNode->parent = last;
+ newNode->parent = lastNode;
newNode->name = comp.toString();
- newNode->dir = last->dir.pathAppended(comp.toString());
- last->subdirs.push_back(newNode);
- last = newNode;
+ newNode->dir = subPath;
+ lastNode->subdirs.push_back(newNode);
+ lastNode = newNode;
+ }
+ return lastNode;
+}
+
+bool findFileWithGetter(const Utils::FilePath &file, const NodePtr &node, const FileGetter &getter)
+{
+ for (const auto &f : getter(node)) {
+ if (f == file)
+ return true;
}
- return last;
+ for (const auto &subdir : node->subdirs) {
+ if (findFileWithGetter(file, subdir, getter))
+ return true;
+ }
+ return false;
+}
+
+bool CMakeGenerator::findFile(const NodePtr &node, const Utils::FilePath &file) const
+{
+ if (isResource(file)) {
+ return findFileWithGetter(file, node, [](const NodePtr &n) { return n->resources; });
+ } else if (isQml(file)) {
+ if (findFileWithGetter(file, node, [](const NodePtr &n) { return n->files; }))
+ return true;
+ else if (findFileWithGetter(file, node, [](const NodePtr &n) { return n->singletons; }))
+ return true;
+ }
+ return false;
}
void CMakeGenerator::insertFile(NodePtr &node, const Utils::FilePath &path) const
{
+ QString error;
+ if (!Utils::FileNameValidatingLineEdit::validateFileName(path.fileName(), false, &error))
+ logIssue(ProjectExplorer::Task::Error, error, path);
+
if (path.fileName() == "qmldir") {
readQmlDir(path, node);
- } else if (path.suffix() == "qml" || path.suffix() == "ui.qml") {
- node->files.push_back(path);
} else if (path.suffix() == "cpp") {
node->sources.push_back(path);
+ } else if (isQml(path)) {
+ node->files.push_back(path);
} else if (isResource(path)) {
node->resources.push_back(path);
}
@@ -458,12 +396,12 @@ void CMakeGenerator::insertFile(NodePtr &node, const Utils::FilePath &path) cons
void CMakeGenerator::removeFile(NodePtr &node, const Utils::FilePath &path) const
{
if (path.fileName() == "qmldir") {
- node->module = false;
+ node->type = Node::Type::Folder;
node->singletons.clear();
node->uri = "";
node->name = path.parentDir().fileName();
- } else if (path.suffix() == "qml") {
+ } else if (isQml(path)) {
auto iter = std::find(node->files.begin(), node->files.end(), path);
if (iter != node->files.end())
node->files.erase(iter);
@@ -474,33 +412,9 @@ void CMakeGenerator::removeFile(NodePtr &node, const Utils::FilePath &path) cons
}
}
-bool CMakeGenerator::isRootNode(const NodePtr &node) const
-{
- return node->name == "Main";
-}
-
-bool CMakeGenerator::hasChildModule(const NodePtr &node) const
-{
- for (const NodePtr &child : node->subdirs) {
- if (child->module)
- return true;
- if (hasChildModule(child))
- return true;
- }
- return false;
-}
-
-bool CMakeGenerator::isResource(const Utils::FilePath &path) const
-{
- static const QStringList suffixes = {
- "json", "mesh", "dae", "qad", "hints", "png", "hdr", "ttf", "jpg", "JPG",
- "js", "qsb", "frag", "frag.qsb", "vert", "vert.qsb", "svg", "ktx"};
- return suffixes.contains(path.suffix());
-}
-
void CMakeGenerator::printModules(const NodePtr &node) const
{
- if (node->module)
+ if (node->type == Node::Type::Module)
qDebug() << "Module: " << node->name;
for (const auto &child : node->subdirs)
@@ -516,7 +430,27 @@ void CMakeGenerator::printNodeTree(const NodePtr &generatorNode, size_t indent)
return str;
};
+ QString typeString;
+ switch (generatorNode->type)
+ {
+ case Node::Type::App:
+ typeString = "Node::Type::App";
+ break;
+ case Node::Type::Folder:
+ typeString = "Node::Type::Folder";
+ break;
+ case Node::Type::Module:
+ typeString = "Node::Type::Module";
+ break;
+ case Node::Type::Library:
+ typeString = "Node::Type::Library";
+ break;
+ default:
+ typeString = "Node::Type::Undefined";
+ }
+
qDebug() << addIndent(indent) << "GeneratorNode: " << generatorNode->name;
+ qDebug() << addIndent(indent) << "type: " << typeString;
qDebug() << addIndent(indent) << "directory: " << generatorNode->dir;
qDebug() << addIndent(indent) << "files: " << generatorNode->files;
qDebug() << addIndent(indent) << "singletons: " << generatorNode->singletons;
@@ -532,7 +466,10 @@ void CMakeGenerator::parseNodeTree(NodePtr &generatorNode,
{
for (const auto *childNode : folderNode->nodes()) {
if (const auto *subFolderNode = childNode->asFolderNode()) {
- CMakeGenerator::NodePtr childGeneratorNode = std::make_shared<Node>();
+ if (ignore(subFolderNode->filePath()))
+ continue;
+
+ NodePtr childGeneratorNode = std::make_shared<Node>();
childGeneratorNode->parent = generatorNode;
childGeneratorNode->dir = subFolderNode->filePath();
childGeneratorNode->name = subFolderNode->displayName();
@@ -544,25 +481,58 @@ void CMakeGenerator::parseNodeTree(NodePtr &generatorNode,
}
}
- if (generatorNode->name == "content")
- generatorNode->module = true;
+ if (m_writer)
+ m_writer->transformNode(generatorNode);
- if (generatorNode->module)
+ if (generatorNode->type == Node::Type::Module)
m_moduleNames.push_back(generatorNode->name);
}
void CMakeGenerator::parseSourceTree()
{
- m_srcs.clear();
- const QString srcDir = m_root->dir.pathAppended(Constants::DIRNAME_CPP).path();
- QDirIterator it(srcDir, QStringList({"*.cpp"}), QDir::Files, QDirIterator::Subdirectories);
+ QTC_ASSERT(m_writer, return);
+
+ const Utils::FilePath srcDir = m_root->dir.pathAppended(m_writer->sourceDirName());
+ QDirIterator it(srcDir.path(), {"*.cpp"}, QDir::Files, QDirIterator::Subdirectories);
+
+ NodePtr srcNode = std::make_shared<Node>();
+ srcNode->parent = m_root;
+ srcNode->type = Node::Type::App;
+ srcNode->dir = srcDir;
+ srcNode->uri = srcDir.baseName();
+ srcNode->name = srcNode->uri;
+
while (it.hasNext()) {
- QString relative = Utils::FilePath::calcRelativePath(it.next(), m_root->dir.path());
- m_srcs.push_back(relative);
+ auto next = it.next();
+ srcNode->sources.push_back(Utils::FilePath::fromString(next));
+ }
+
+ if (srcNode->sources.empty())
+ srcNode->sources.push_back(srcDir.pathAppended("main.cpp"));
+
+ if (m_writer)
+ m_writer->transformNode(srcNode);
+
+ m_root->subdirs.push_back(srcNode);
+}
+
+void CMakeGenerator::compareWithFileSystem(const NodePtr &node) const
+{
+ std::vector<Utils::FilePath> files;
+ QDirIterator iter(node->dir.path(), QDir::Files, QDirIterator::Subdirectories);
+
+ while (iter.hasNext()) {
+ auto next = Utils::FilePath::fromString(iter.next());
+ if (ignore(next.parentDir()))
+ continue;
+
+ if (isResource(next) && !findFile(next) && !ignore(next))
+ files.push_back(next);
}
- if (m_srcs.empty())
- m_srcs.push_back("src/main.cpp");
+ const QString text("File is not part of the project");
+ for (const auto &file : files)
+ logIssue(ProjectExplorer::Task::Warning, text, file);
}
} // namespace GenerateCmake
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h
index f89257ac5d..3af3405879 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h
@@ -2,7 +2,10 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
+#include "cmakewriter.h"
+
#include "utils/filepath.h"
+#include "projectexplorer/task.h"
#include <QObject>
@@ -22,81 +25,57 @@ class CMakeGenerator : public QObject
Q_OBJECT
public:
+ static void createMenuAction(QObject *parent);
+ static void logIssue(ProjectExplorer::Task::TaskType type, const QString &text, const Utils::FilePath &file);
+
CMakeGenerator(QmlBuildSystem *bs, QObject *parent = nullptr);
- void setEnabled(bool enabled);
+ QString projectName() const;
- void initialize(QmlProject *project);
+ const QmlProject *qmlProject() const;
+ const QmlBuildSystem *buildSystem() const;
+ bool findFile(const Utils::FilePath &file) const;
+ bool isRootNode(const NodePtr &node) const;
+ bool hasChildModule(const NodePtr &node) const;
+
+ void setEnabled(bool enabled);
+ void initialize(QmlProject *project);
void update(const QSet<QString> &added, const QSet<QString> &removed);
+ void updateMenuAction();
private:
- struct Node
- {
- std::shared_ptr<Node> parent = nullptr;
- bool module = false;
-
- QString uri;
- QString name;
- Utils::FilePath dir;
-
- std::vector<std::shared_ptr<Node>> subdirs;
- std::vector<Utils::FilePath> files;
- std::vector<Utils::FilePath> singletons;
- std::vector<Utils::FilePath> resources;
- std::vector<Utils::FilePath> sources;
- };
-
- using NodePtr = std::shared_ptr<Node>;
- using FileGetter = std::function<std::vector<Utils::FilePath>(const NodePtr &)>;
-
- std::vector<Utils::FilePath> files(const NodePtr &node, const FileGetter &getter) const;
- std::vector<Utils::FilePath> qmlFiles(const NodePtr &node) const;
- std::vector<Utils::FilePath> singletons(const NodePtr &node) const;
- std::vector<Utils::FilePath> resources(const NodePtr &node) const;
- std::vector<Utils::FilePath> sources(const NodePtr &node) const;
+ bool isQml(const Utils::FilePath &path) const;
+ bool isResource(const Utils::FilePath &path) const;
+ bool ignore(const Utils::FilePath &path) const;
void createCMakeFiles(const NodePtr &node) const;
- void createMainCMakeFile(const NodePtr &node) const;
- void createModuleCMakeFile(const NodePtr &node) const;
-
- void createEntryPoints(const NodePtr &node) const;
- void createMainCppFile(const NodePtr &node) const;
- void writeFile(const Utils::FilePath &path, const QString &content) const;
+ void createSourceFiles() const;
- QString makeRelative(const NodePtr &node, const Utils::FilePath &path) const;
- QString makeEnvironmentVariable(const QString &key) const;
- QString makeSingletonBlock(const NodePtr &node) const;
- QString makeSubdirectoriesBlock(const NodePtr &node) const;
- QString makeQmlFilesBlock(const NodePtr &node) const;
- std::tuple<QString, QString> makeResourcesBlocks(const NodePtr &node) const;
-
- QString readTemplate(const QString &templatePath) const;
void readQmlDir(const Utils::FilePath &filePath, NodePtr &node) const;
-
NodePtr findModuleFor(const NodePtr &node) const;
NodePtr findNode(NodePtr &node, const Utils::FilePath &path) const;
NodePtr findOrCreateNode(NodePtr &node, const Utils::FilePath &path) const;
+ bool findFile(const NodePtr &node, const Utils::FilePath &file) const;
void insertFile(NodePtr &node, const Utils::FilePath &path) const;
void removeFile(NodePtr &node, const Utils::FilePath &path) const;
- bool isRootNode(const NodePtr &node) const;
- bool hasChildModule(const NodePtr &node) const;
- bool isResource(const Utils::FilePath &path) const;
-
void printModules(const NodePtr &generatorNode) const;
void printNodeTree(const NodePtr &generatorNode, size_t indent = 0) const;
void parseNodeTree(NodePtr &generatorNode, const ProjectExplorer::FolderNode *folderNode);
void parseSourceTree();
+ void compareWithFileSystem(const NodePtr &node) const;
+
bool m_enabled = false;
+ QmlBuildSystem *m_buildSystem = nullptr;
+ CMakeWriter::Ptr m_writer = {};
+
QString m_projectName = {};
NodePtr m_root = {};
- QStringList m_srcs = {};
- std::vector<QString> m_moduleNames = {};
- QmlBuildSystem *m_buildSystem = nullptr;
+ QStringList m_moduleNames = {};
};
} // namespace GenerateCmake
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp
deleted file mode 100644
index aa733b68af..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "cmakegeneratordialog.h"
-#include "../qmlprojectmanagertr.h"
-#include "cmakegeneratordialogtreemodel.h"
-
-#include <utils/utilsicons.h>
-#include <utils/detailswidget.h>
-
-#include <QDialogButtonBox>
-#include <QPushButton>
-#include <QLayout>
-#include <QLabel>
-
-#include <QSplitter>
-
-using namespace Utils;
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-CmakeGeneratorDialog::CmakeGeneratorDialog(const FilePath &rootDir,
- const FilePaths &files,
- const FilePaths invalidFiles)
- : QDialog(), m_rootDir(rootDir), m_files(files), m_invalidFiles(invalidFiles)
-{
- setWindowTitle(Tr::tr("Select Files to Generate"));
-
- QLabel *mainLabel = new QLabel(Tr::tr("Start CMakeFiles.txt generation"), this);
- mainLabel->setMargin(30);
-
- QVBoxLayout *dialogLayout = new QVBoxLayout(this);
- dialogLayout->addWidget(mainLabel);
- dialogLayout->addWidget(createDetailsWidget());
- dialogLayout->addWidget(createButtons());
- setLayout(dialogLayout);
-
- setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- setMaximumHeight(layout()->totalSizeHint().height());
-
- refreshNotificationText();
-}
-
-QTreeView* CmakeGeneratorDialog::createFileTree()
-{
- m_model = new CMakeGeneratorDialogTreeModel(m_rootDir, m_files, this);
-
- QTreeView *tree = new QTreeView(this);
- tree->setModel(m_model);
- tree->expandAll();
- tree->setHeaderHidden(true);
-
- return tree;
-}
-
-QWidget* CmakeGeneratorDialog::createDetailsWidget()
-{
- QTreeView* tree = createFileTree();
-
- m_notifications = new QTextEdit(this);
- m_warningIcon = Utils::Icons::WARNING.pixmap();
-
- QSplitter *advancedInnerWidget = new QSplitter(this);
- advancedInnerWidget->addWidget(tree);
- advancedInnerWidget->addWidget(m_notifications);
- advancedInnerWidget->setStretchFactor(0, 2);
- advancedInnerWidget->setStretchFactor(1, 1);
- advancedInnerWidget->setOrientation(Qt::Vertical);
- advancedInnerWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::MinimumExpanding);
-
- DetailsWidget *advancedWidget = new DetailsWidget(this);
- advancedWidget->setMinimumWidth(600);
- advancedWidget->setWidget(advancedInnerWidget);
- advancedWidget->setSummaryText(Tr::tr("Advanced Options"));
- connect(advancedWidget, &DetailsWidget::expanded, this, &CmakeGeneratorDialog::advancedVisibilityChanged);
-
- return advancedWidget;
-}
-
-QWidget* CmakeGeneratorDialog::createButtons()
-{
- QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
- auto *okButton = buttons->button(QDialogButtonBox::Ok);
- okButton->setDefault(true);
-
- connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
- connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
- connect(m_model, &CMakeGeneratorDialogTreeModel::checkedStateChanged, this, &CmakeGeneratorDialog::refreshNotificationText);
-
- return buttons;
-}
-
-FilePaths CmakeGeneratorDialog::getFilePaths()
-{
- FilePaths paths;
-
- QList<CheckableFileTreeItem*> items = m_model->checkedItems();
- for (CheckableFileTreeItem *item: items) {
- paths.append(FilePath::fromString(item->text()));
- }
-
- return paths;
-}
-
-const QString FILE_CREATE_NOTIFICATION = Tr::tr("File %1 will be created.\n");
-const QString FILE_OVERWRITE_NOTIFICATION = Tr::tr("File %1 will be overwritten.\n");
-const QString FILE_INVALID_NOTIFICATION = Tr::tr(
- "File %1 contains invalid characters and will be skipped.\n");
-
-void CmakeGeneratorDialog::refreshNotificationText()
-{
- QTextDocument *document = m_notifications->document();
- document->clear();
- document->addResource(QTextDocument::ImageResource, QUrl("cmakegendialog://warningicon"), m_warningIcon);
-
- QTextCursor cursor = m_notifications->textCursor();
- QTextImageFormat iformat;
- iformat.setName("cmakegendialog://warningicon");
-
- QList<CheckableFileTreeItem*> nodes = m_model->items();
-
- for (const auto &file : m_invalidFiles) {
- cursor.insertImage(iformat);
- cursor.insertText(QString(FILE_INVALID_NOTIFICATION).arg(file.displayName()));
- }
-
- for (CheckableFileTreeItem *node : nodes) {
- if (!m_files.contains(node->toFilePath()))
- continue;
-
- if (!node->toFilePath().exists() && node->isChecked()) {
- QString relativePath = QString(node->toFilePath().toString()).remove(m_rootDir.toString()+'/');
- cursor.insertText(QString(FILE_CREATE_NOTIFICATION).arg(relativePath));
- }
- }
-
- if (!document->toPlainText().isEmpty())
- cursor.insertBlock();
-
- for (CheckableFileTreeItem *node : nodes) {
- if (!m_files.contains(node->toFilePath()))
- continue;
-
- if (node->toFilePath().exists() && node->isChecked()) {
- QString relativePath = node->toFilePath().relativePathFrom(m_rootDir).toString();
- cursor.insertImage(iformat);
- cursor.insertText(QString(FILE_OVERWRITE_NOTIFICATION).arg(relativePath));
- }
- }
-}
-
-void CmakeGeneratorDialog::advancedVisibilityChanged(bool visible)
-{
- if (visible) {
- setMaximumHeight(QWIDGETSIZE_MAX);
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- }
- else {
- setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- int height = layout()->totalSizeHint().height();
- setMaximumHeight(height);
- resize(width(), height);
- }
-}
-
-} //GenerateCmake
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h
deleted file mode 100644
index fb15ec4de7..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-
-#ifndef CMAKEGENERATORDIALOG_H
-#define CMAKEGENERATORDIALOG_H
-
-#include "cmakegeneratordialogtreemodel.h"
-
-#include <utils/fileutils.h>
-
-#include <QDialog>
-#include <QTextEdit>
-#include <QTreeView>
-#include <QLabel>
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-class CmakeGeneratorDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- CmakeGeneratorDialog(const Utils::FilePath &rootDir,
- const Utils::FilePaths &files,
- const Utils::FilePaths invalidFiles);
- Utils::FilePaths getFilePaths();
-
-public slots:
- void refreshNotificationText();
- void advancedVisibilityChanged(bool visible);
-
-private:
- QTreeView* createFileTree();
- QWidget* createDetailsWidget();
- QWidget* createButtons();
-
-private:
- CMakeGeneratorDialogTreeModel *m_model;
- QTextEdit *m_notifications;
- QVariant m_warningIcon;
- Utils::FilePath m_rootDir;
- Utils::FilePaths m_files;
- Utils::FilePaths m_invalidFiles;
-};
-
-} //GenerateCmake
-} //QmlProjectManager
-
-#endif // CMAKEGENERATORDIALOG_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp
deleted file mode 100644
index 525230bdfd..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "cmakegeneratordialogtreemodel.h"
-#include "generatecmakelistsconstants.h"
-#include "checkablefiletreeitem.h"
-#include "../qmlprojectmanagertr.h"
-
-#include <utils/utilsicons.h>
-
-using namespace Utils;
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-CMakeGeneratorDialogTreeModel::CMakeGeneratorDialogTreeModel(const FilePath &rootDir,
- const FilePaths &files, QObject *parent)
- :QStandardItemModel(parent),
- rootDir(rootDir),
- m_icons(new QFileIconProvider())
-{
- createNodes(files, invisibleRootItem());
-}
-
-CMakeGeneratorDialogTreeModel::~CMakeGeneratorDialogTreeModel()
-{
- delete m_icons;
-}
-
-QVariant CMakeGeneratorDialogTreeModel::data(const QModelIndex &index, int role) const
-{
- if (index.isValid()) {
- const CheckableFileTreeItem *node = constNodeForIndex(index);
- if (role == Qt::CheckStateRole) {
- if (!node->isDir())
- return node->isChecked() ? Qt::Checked : Qt::Unchecked;
- return {};
- }
- else if (role == Qt::DisplayRole) {
- FilePath fullPath = node->toFilePath();
- return QVariant(fullPath.fileName());
- }
- else if (role == Qt::DecorationRole) {
- if (node->isFile())
- return Utils::Icons::WARNING.icon();
- if (node->isDir())
- return m_icons->icon(QFileIconProvider::Folder);
- else
- return Utils::Icons::NEWFILE.icon();
- }
- else if (role == Qt::ToolTipRole) {
- if (node->isFile())
- return Tr::tr("This file already exists and will be overwritten.");
- if (!node->toFilePath().exists())
- return Tr::tr("This file or folder will be created.");
- }
- }
-
- return QStandardItemModel::data(index, role);
-}
-
-bool CMakeGeneratorDialogTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- if (index.isValid()) {
- CheckableFileTreeItem *node = nodeForIndex(index);
- if (role == Qt::CheckStateRole) {
- node->setChecked(value.value<bool>());
- emit checkedStateChanged(node);
- return true;
- }
- }
-
- return QStandardItemModel::setData(index, value, role);;
-}
-
-const QList<CheckableFileTreeItem*> CMakeGeneratorDialogTreeModel::items() const
-{
- QList<QStandardItem*> standardItems = findItems(".*", Qt::MatchRegularExpression | Qt::MatchRecursive);
- QList<CheckableFileTreeItem*> checkableItems;
- for (QStandardItem *item : standardItems)
- checkableItems.append(static_cast<CheckableFileTreeItem*>(item));
-
- return checkableItems;
-}
-
-const QList<CheckableFileTreeItem*> CMakeGeneratorDialogTreeModel::checkedItems() const
-{
- QList<CheckableFileTreeItem*> allItems = items();
-
- QList<CheckableFileTreeItem*> checkedItems;
- for (CheckableFileTreeItem *item : allItems) {
- if (item->isChecked())
- checkedItems.append(item);
- }
-
- return checkedItems;
-}
-
-bool CMakeGeneratorDialogTreeModel::checkedByDefault(const Utils::FilePath &file) const
-{
- if (file.exists()) {
- QString relativePath = file.relativeChildPath(rootDir).toString();
- if (relativePath.compare(QmlProjectManager::GenerateCmake::Constants::FILENAME_CMAKELISTS) == 0)
- return false;
- if (relativePath.endsWith(QmlProjectManager::GenerateCmake::Constants::FILENAME_CMAKELISTS)
- && relativePath.length() > QString(QmlProjectManager::GenerateCmake::Constants::FILENAME_CMAKELISTS).length())
- return true;
- if (relativePath.compare(QmlProjectManager::GenerateCmake::Constants::FILENAME_MODULES) == 0)
- return true;
- if (relativePath.compare(
- FilePath::fromString(QmlProjectManager::GenerateCmake::Constants::DIRNAME_CPP)
- .pathAppended(QmlProjectManager::GenerateCmake::Constants::FILENAME_MAINCPP_HEADER)
- .toString())
- == 0)
- return true;
- }
-
- return !file.exists();
-}
-
-void CMakeGeneratorDialogTreeModel::createNodes(const FilePaths &candidates, QStandardItem *parent)
-{
- if (!parent)
- return;
-
- CheckableFileTreeItem *checkParent = dynamic_cast<CheckableFileTreeItem*>(parent);
- FilePath thisDir = (parent == invisibleRootItem()) ? rootDir : checkParent->toFilePath();
-
- for (const FilePath &file : candidates) {
- if (file.parentDir() == thisDir) {
- CheckableFileTreeItem *fileNode = new CheckableFileTreeItem(file);
- fileNode->setChecked(checkedByDefault(file));
- if (!file.exists())
- fileNode->setChecked(true);
- parent->appendRow(fileNode);
- }
- }
-
- FilePaths directSubDirs;
- for (const FilePath &file : candidates) {
- FilePath dir = file.parentDir();
- if (dir.parentDir() == thisDir && !directSubDirs.contains(dir))
- directSubDirs.append(dir);
- }
-
- for (const FilePath &subDir : directSubDirs) {
- CheckableFileTreeItem *dirNode = new CheckableFileTreeItem(subDir);
- parent->appendRow(dirNode);
-
- FilePaths subDirCandidates;
- for (const FilePath &file : candidates)
- if (file.isChildOf(subDir))
- subDirCandidates.append(file);
-
- createNodes(subDirCandidates, dirNode);
- }
-}
-
-const CheckableFileTreeItem* CMakeGeneratorDialogTreeModel::constNodeForIndex(const QModelIndex &index) const
-{
- const QStandardItem *parent = static_cast<const QStandardItem*>(index.internalPointer());
- const QStandardItem *item = parent->child(index.row(), index.column());
- return static_cast<const CheckableFileTreeItem*>(item);
-}
-
-CheckableFileTreeItem* CMakeGeneratorDialogTreeModel::nodeForIndex(const QModelIndex &index)
-{
- QStandardItem *parent = static_cast<QStandardItem*>(index.internalPointer());
- QStandardItem *item = parent->child(index.row(), index.column());
- return static_cast<CheckableFileTreeItem*>(item);
-}
-
-} //GenerateCmake
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h
deleted file mode 100644
index 3fb79c2b96..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#ifndef CMAKEGENERATORDIALOGTREEMODEL_H
-#define CMAKEGENERATORDIALOGTREEMODEL_H
-
-#include "checkablefiletreeitem.h"
-
-#include <QFileIconProvider>
-#include <QStandardItemModel>
-
-#include <utils/fileutils.h>
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-class CMakeGeneratorDialogTreeModel : public QStandardItemModel
-{
- Q_OBJECT
-
-public:
- CMakeGeneratorDialogTreeModel(const Utils::FilePath &rootDir,
- const Utils::FilePaths &files, QObject *parent = nullptr);
- ~CMakeGeneratorDialogTreeModel();
-
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
-
- const QList<CheckableFileTreeItem*> items() const;
- const QList<CheckableFileTreeItem*> checkedItems() const;
- const CheckableFileTreeItem* constNodeForIndex(const QModelIndex &index) const;
- CheckableFileTreeItem* nodeForIndex(const QModelIndex &index);
-
-signals:
- void checkedStateChanged(CheckableFileTreeItem *item);
-
-protected:
- bool checkedByDefault(const Utils::FilePath &file) const;
- Utils::FilePath rootDir;
-
-private:
- void createNodes(const Utils::FilePaths &candidates, QStandardItem *parent);
-
- QFileIconProvider* m_icons;
-};
-
-} //GenerateCmake
-} //QmlProjectManager
-
-
-#endif // CMAKEGENERATORDIALOGTREEMODEL_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp
deleted file mode 100644
index f6bf1a4975..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp
+++ /dev/null
@@ -1,422 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "cmakeprojectconverter.h"
-#include "cmakeprojectconverterdialog.h"
-#include "generatecmakelists.h"
-#include "generatecmakelistsconstants.h"
-#include "../qmlprojectmanagertr.h"
-
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/actionmanager/actioncontainer.h>
-#include <coreplugin/icore.h>
-
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/projectmanager.h>
-#include <projectexplorer/target.h>
-
-#include <qmlprojectmanager/qmlprojectconstants.h>
-
-#include <QAction>
-#include <QMessageBox>
-#include <QRegularExpression>
-
-using namespace Utils;
-using namespace QmlProjectManager::GenerateCmake::Constants;
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-const QString MENU_ITEM_CONVERT = Tr::tr("Export as Latest Project Format...");
-const QString ERROR_TITLE = Tr::tr("Creating Project");
-const QString SUCCESS_TITLE = Tr::tr("Creating Project");
-const QString ERROR_TEXT = Tr::tr("Creating project failed.\n%1");
-const QString SUCCESS_TEXT = Tr::tr("Creating project succeeded.");
-
-void CmakeProjectConverter::generateMenuEntry(QObject *parent)
-{
- Core::ActionContainer *exportMenu = Core::ActionManager::actionContainer(
- QmlProjectManager::Constants::EXPORT_MENU);
- auto action = new QAction(MENU_ITEM_CONVERT, parent);
- QObject::connect(action, &QAction::triggered, CmakeProjectConverter::onConvertProject);
- Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.ConvertToCmakeProject");
- exportMenu->addAction(cmd, QmlProjectManager::Constants::G_EXPORT_CONVERT);
-
- action->setEnabled(isProjectConvertable(ProjectExplorer::ProjectManager::startupProject()));
- QObject::connect(ProjectExplorer::ProjectManager::instance(),
- &ProjectExplorer::ProjectManager::startupProjectChanged,
- [action]() {
- auto currentBuildSystem = QmlBuildSystem::getStartupBuildSystem();
- bool isMCU = currentBuildSystem ? currentBuildSystem->qtForMCUs() : false;
-
- action->setEnabled(isMCU
- && isProjectConvertable(
- ProjectExplorer::ProjectManager::startupProject()));
- });
-}
-
-bool CmakeProjectConverter::isProjectConvertable(const ProjectExplorer::Project *project)
-{
- if (!project)
- return false;
-
- return !isProjectCurrentFormat(project);
-}
-
-const QStringList sanityCheckFiles({FILENAME_CMAKELISTS,
- FILENAME_MODULES,
- FILENAME_MAINQML,
- QString(DIRNAME_CONTENT)+'/'+FILENAME_CMAKELISTS,
- QString(DIRNAME_IMPORT)+'/'+FILENAME_CMAKELISTS,
- QString(DIRNAME_CPP)+'/'+FILENAME_MAINCPP,
- QString(DIRNAME_CPP)+'/'+FILENAME_ENV_HEADER,
- QString(DIRNAME_CPP)+'/'+FILENAME_MAINCPP_HEADER
- });
-
-bool CmakeProjectConverter::isProjectCurrentFormat(const ProjectExplorer::Project *project)
-{
- const QmlProjectManager::QmlProject *qmlprj = qobject_cast<const QmlProjectManager::QmlProject*>(project);
-
- if (!qmlprj)
- return false;
-
- FilePath rootDir = qmlprj->rootProjectDirectory();
- for (const QString &file : sanityCheckFiles)
- if (!rootDir.pathAppended(file).exists())
- return false;
-
- return true;
-}
-
-void CmakeProjectConverter::onConvertProject()
-{
- ProjectExplorer::Project *project = ProjectExplorer::ProjectManager::startupProject();
- const QmlProjectManager::QmlProject *qmlProject =
- qobject_cast<const QmlProjectManager::QmlProject*>(project);
- if (qmlProject) {
- CmakeProjectConverterDialog dialog(qmlProject);
- if (dialog.exec()) {
- FilePath newProjectPath = dialog.newPath();
- CmakeProjectConverter converter;
- converter.convertProject(qmlProject, newProjectPath);
- }
- }
-}
-
-bool CmakeProjectConverter::convertProject(const QmlProjectManager::QmlProject *project,
- const FilePath &targetDir)
-{
- m_converterObjects.clear();
- m_projectDir = project->projectDirectory();
- m_newProjectDir = targetDir;
- m_project = project;
-
- m_rootDirFiles = QStringList(FILENAME_FILTER_QMLPROJECT);
- const QString confFile = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
- if (!confFile.isEmpty())
- m_rootDirFiles.append(confFile);
-
- bool retVal = prepareAndExecute();
-
- if (retVal) {
- QMessageBox::information(Core::ICore::dialogParent(), SUCCESS_TITLE, SUCCESS_TEXT);
- ProjectExplorer::OpenProjectResult result
- = ProjectExplorer::ProjectExplorerPlugin::openProject(newProjectFile());
- if (!result)
- ProjectExplorer::ProjectExplorerPlugin::showOpenProjectError(result);
- }
- else {
- QMessageBox::critical(Core::ICore::dialogParent(), ERROR_TITLE, ERROR_TEXT.arg(m_errorText));
- }
-
- return retVal;
-}
-
-bool CmakeProjectConverter::prepareAndExecute()
-{
- GenerateCmake::CmakeFileGenerator cmakeGenerator;
-
- if (!performSanityCheck())
- return false;
- if (!prepareBaseDirectoryStructure())
- return false;
- if (!prepareCopy())
- return false;
- if (!createPreparedProject())
- return false;
- if (!cmakeGenerator.prepare(m_newProjectDir, false))
- return false;
- if (!cmakeGenerator.execute())
- return false;
- if (!modifyNewFiles())
- return false;
-
- return true;
-}
-
-bool CmakeProjectConverter::isFileBlacklisted(const Utils::FilePath &file) const
-{
- if (!file.fileName().compare(FILENAME_CMAKELISTS))
- return true;
- if (!file.suffix().compare(FILENAME_SUFFIX_QMLPROJECT))
- return true;
- if (!file.suffix().compare(FILENAME_SUFFIX_USER))
- return true;
- if (m_rootDirFiles.contains(file.fileName()))
- return true;
-
- return false;
-}
-
-bool CmakeProjectConverter::isDirBlacklisted(const Utils::FilePath &dir) const
-{
- if (!dir.isDir())
- return true;
-
- return false;
-}
-
-const QString ERROR_CANNOT_WRITE_DIR = Tr::tr("Unable to write to directory\n%1.");
-
-bool CmakeProjectConverter::performSanityCheck()
-{
- if (!m_newProjectDir.parentDir().isWritableDir()) {
- m_errorText = ERROR_CANNOT_WRITE_DIR.arg(m_newProjectDir.parentDir().toString());
- return false;
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareBaseDirectoryStructure()
-{
- addDirectory(m_newProjectDir);
- addDirectory(contentDir());
- addDirectory(sourceDir());
- addDirectory(importDir());
- addDirectory(assetDir());
- addDirectory(assetImportDir());
- addFile(contentDir().pathAppended(FILENAME_APPMAINQML));
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareCopy()
-{
- FilePaths rootFiles = m_projectDir.dirEntries({m_rootDirFiles, QDir::Files});
- for (const FilePath &file : rootFiles) {
- addFile(file, m_newProjectDir.pathAppended(file.fileName()));
- }
-
- prepareCopyDirFiles(m_projectDir, contentDir());
-
- FilePaths subDirs = m_projectDir.dirEntries(QDir::Dirs|QDir::NoDotAndDotDot);
- for (FilePath &subDir : subDirs) {
- if (subDir.fileName() == DIRNAME_IMPORT) {
- prepareCopyDirTree(subDir, importDir());
- }
- else if (subDir.fileName() == DIRNAME_CPP) {
- prepareCopyDirTree(subDir, sourceDir());
- }
- else if (subDir.fileName() == DIRNAME_ASSET) {
- prepareCopyDirTree(subDir, assetDir());
- }
- else if (subDir.fileName() == DIRNAME_ASSETIMPORT) {
- prepareCopyDirTree(subDir, assetImportDir());
- }
- else {
- prepareCopyDirTree(subDir, contentDir().pathAppended(subDir.fileName()));
- }
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareCopyDirFiles(const FilePath &dir, const FilePath &targetDir)
-{
- FilePaths dirFiles = dir.dirEntries(QDir::Files);
- for (FilePath file : dirFiles) {
- if (!isFileBlacklisted(file))
- addFile(file, targetDir.pathAppended(file.fileName()));
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareCopyDirTree(const FilePath &dir, const FilePath &targetDir)
-{
- prepareCopyDirFiles(dir, targetDir);
- FilePaths subDirs = dir.dirEntries(QDir::Dirs|QDir::NoDotAndDotDot);
- for (FilePath &subDir : subDirs) {
- if (isDirBlacklisted(subDir))
- continue;
- addDirectory(targetDir.pathAppended(subDir.fileName()));
- prepareCopyDirFiles(subDir, targetDir.pathAppended(subDir.fileName()));
- prepareCopyDirTree(subDir, targetDir.pathAppended(subDir.fileName()));
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::addDirectory(const Utils::FilePath &target)
-{
- return addObject(ProjectConverterObjectType::Directory, FilePath(), target);
-}
-
-bool CmakeProjectConverter::addFile(const Utils::FilePath &target)
-{
- return addFile(FilePath(), target);
-}
-
-bool CmakeProjectConverter::addFile(const Utils::FilePath &original, const Utils::FilePath &target)
-{
- addDirectory(target.parentDir());
- return addObject(ProjectConverterObjectType::File, original, target);
-}
-
-bool CmakeProjectConverter::addObject(ProjectConverterObjectType type,
- const Utils::FilePath &original, const Utils::FilePath &target)
-{
- if (target.isChildOf(m_projectDir))
- return false;
-
- if (!target.isChildOf(m_newProjectDir) &&
- ((type == ProjectConverterObjectType::Directory) && (target != m_newProjectDir))) {
- return false;
- }
-
- for (ProjectConverterObject &o : m_converterObjects) {
- if (o.target == target)
- return false;
- }
-
- ProjectConverterObject object;
- object.type = type;
- object.target = target;
- object.original = original;
-
- m_converterObjects.append(object);
-
- return true;
-}
-
-bool CmakeProjectConverter::createPreparedProject()
-{
- for (ProjectConverterObject &pco : m_converterObjects) {
- if (pco.type == ProjectConverterObjectType::Directory) {
- pco.target.createDir();
- }
- else if (pco.type == ProjectConverterObjectType::File) {
- if (pco.original.isEmpty()) {
- QFile newFile(pco.target.toString());
- newFile.open(QIODevice::WriteOnly);
- newFile.close();
- }
- else {
- pco.original.copyFile(pco.target);
- }
- }
- }
-
- return true;
-}
-
-const FilePath CmakeProjectConverter::contentDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_CONTENT);
-}
-
-const FilePath CmakeProjectConverter::sourceDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_CPP);
-}
-
-const FilePath CmakeProjectConverter::importDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_IMPORT);
-}
-
-const FilePath CmakeProjectConverter::assetDir() const
-{
- return contentDir().pathAppended(DIRNAME_ASSET);
-}
-
-const FilePath CmakeProjectConverter::assetImportDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_ASSETIMPORT);
-}
-
-const FilePath CmakeProjectConverter::newProjectFile() const
-{
- return m_newProjectDir.pathAppended(m_project->projectFilePath().fileName());
-}
-
-const FilePath CmakeProjectConverter::projectMainFile() const
-{
- auto *target = m_project->activeTarget();
- if (target && target->buildSystem()) {
- auto buildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
- if (buildSystem) {
- return buildSystem->mainFilePath();
- }
- }
- return {};
-}
-
-const QString CmakeProjectConverter::projectMainClass() const
-{
- return projectMainFile().baseName();
-}
-
-bool CmakeProjectConverter::modifyNewFiles()
-{
- return modifyAppMainQml() && modifyProjectFile();
-}
-
-const char APPMAIN_QMLFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectappmainqml.tpl";
-
-bool CmakeProjectConverter::modifyAppMainQml()
-{
- QString appMainQmlPath = contentDir().pathAppended(FILENAME_APPMAINQML).toString();
- QFile appMainQml(appMainQmlPath);
- appMainQml.open(QIODevice::ReadWrite);
- if (!appMainQml.isOpen())
- return false;
-
- QString templateContent = GenerateCmake::readTemplate(APPMAIN_QMLFILE_TEMPLATE_PATH);
- QString appMainQmlContent = templateContent.arg(projectMainClass());
-
- appMainQml.reset();
- appMainQml.write(appMainQmlContent.toUtf8());
- appMainQml.close();
-
- return true;
-}
-
-bool CmakeProjectConverter::modifyProjectFile()
-{
- QString projectFileName = m_project->projectFilePath().fileName();
- FilePath projectFilePath = m_newProjectDir.pathAppended(projectFileName);
- QFile projectFile(projectFilePath.toString());
- projectFile.open(QIODevice::ReadOnly);
- if (!projectFile.isOpen())
- return false;
- QString projectFileContent = QString::fromUtf8(projectFile.readAll());
- projectFile.close();
-
- const QRegularExpression mainFilePattern("^\\s*mainFile:\\s*\".*\"", QRegularExpression::MultilineOption);
- const QString mainFileString(" mainFile: \"content/App.qml\"");
-
- projectFileContent.replace(mainFilePattern, mainFileString);
-
- projectFile.open(QIODevice::WriteOnly|QIODevice::Truncate);
- if (!projectFile.isOpen())
- return false;
- projectFile.write(projectFileContent.toUtf8());
- projectFile.close();
-
- return true;
-}
-
-} //GenerateCmake
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h
deleted file mode 100644
index 415123db70..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#ifndef CMAKEPROJECTCONVERTER_H
-#define CMAKEPROJECTCONVERTER_H
-
-#include <utils/fileutils.h>
-#include <qmlprojectmanager/qmlproject.h>
-
-namespace QmlProjectManager {
-
-namespace GenerateCmake {
-
-enum ProjectConverterObjectType {
- File,
- Directory
-};
-
-struct ProjectConverterObject {
- ProjectConverterObjectType type;
- Utils::FilePath target;
- Utils::FilePath original;
-};
-
-class CmakeProjectConverter {
-
-public:
- bool convertProject(const QmlProjectManager::QmlProject *project,
- const Utils::FilePath &targetDir);
- static void generateMenuEntry(QObject *parent);
- static void onConvertProject();
- static bool isProjectConvertable(const ProjectExplorer::Project *project);
- static bool isProjectCurrentFormat(const ProjectExplorer::Project *project);
-
-private:
- bool prepareAndExecute();
- bool isFileBlacklisted(const Utils::FilePath &file) const;
- bool isDirBlacklisted(const Utils::FilePath &dir) const;
- bool performSanityCheck();
- bool prepareBaseDirectoryStructure();
- bool prepareCopyDirFiles(const Utils::FilePath &dir, const Utils::FilePath &targetDir);
- bool prepareCopyDirTree(const Utils::FilePath &dir, const Utils::FilePath &targetDir);
- bool prepareCopy();
- bool addDirectory(const Utils::FilePath &target);
- bool addFile(const Utils::FilePath &target);
- bool addFile(const Utils::FilePath &original, const Utils::FilePath &target);
- bool addObject(ProjectConverterObjectType type,
- const Utils::FilePath &original, const Utils::FilePath &target);
- bool createPreparedProject();
-
- const Utils::FilePath contentDir() const;
- const Utils::FilePath sourceDir() const;
- const Utils::FilePath importDir() const;
- const Utils::FilePath assetDir() const;
- const Utils::FilePath assetImportDir() const;
- const Utils::FilePath newProjectFile() const;
-
- const QString environmentVariable(const QString &key) const;
- const Utils::FilePath projectMainFile() const;
- const QString projectMainClass() const;
- bool modifyNewFiles();
- bool modifyAppMainQml();
- bool modifyProjectFile();
-
-private:
- QList<ProjectConverterObject> m_converterObjects;
- QStringList m_rootDirFiles;
- Utils::FilePath m_projectDir;
- Utils::FilePath m_newProjectDir;
- const QmlProjectManager::QmlProject *m_project;
- QString m_errorText;
-};
-
-} //GenerateCmake
-} //QmlProjectManager
-
-#endif // CMAKEPROJECTCONVERTER_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp
deleted file mode 100644
index 1d67a92b39..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "cmakeprojectconverterdialog.h"
-#include "../qmlprojectmanagertr.h"
-
-#include <coreplugin/documentmanager.h>
-
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QFormLayout>
-#include <QGroupBox>
-#include <QLabel>
-#include <QPushButton>
-#include <QRegularExpression>
-
-using namespace Utils;
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-const QRegularExpression projectNameRegexp("^(?!(import))(?!(QtQml))(?!(QtQuick))(?:[A-Z][a-zA-Z0-9-_]*)$");
-
-static bool projectNameValidationFunction(FancyLineEdit *editor, QString *)
-{
- return editor->text().count(projectNameRegexp);
-}
-
-static bool dirValidationFunction(FancyLineEdit *editor, QString *)
-{
- return FilePath::fromString(editor->text()).isWritableDir();
-}
-
-const QString EXPLANATION_TEXT = Tr::tr("This process creates a copy of the existing project. The new project's folder structure is adjusted for CMake build process and necessary related new files are generated.\n\nThe new project can be opened in Qt Creator using the main CMakeLists.txt file.");
-const QString PROJECT_NAME_LABEL = Tr::tr("Name:");
-const QString PARENT_DIR_LABEL = Tr::tr("Create in:");
-
-CmakeProjectConverterDialog::CmakeProjectConverterDialog(const QmlProjectManager::QmlProject *oldProject)
- : QDialog()
-{
- const FilePath defaultDir = Core::DocumentManager::projectsDirectory();
- const QString defaultName = uniqueProjectName(defaultDir, oldProject->displayName());
-
- QLabel *mainLabel = new QLabel(EXPLANATION_TEXT, this);
- mainLabel->setWordWrap(true);
-
- mainLabel->setMargin(20);
- mainLabel->setMinimumWidth(600);
-
- m_errorLabel = new InfoLabel();
- m_errorLabel->setType(InfoLabel::InfoType::None);
-
- m_nameEditor = new FancyLineEdit();
- m_nameEditor->setValidationFunction(projectNameValidationFunction);
- m_nameEditor->setText(defaultName);
-
- m_dirSelector = new PathChooser();
- m_dirSelector->setExpectedKind(PathChooser::Directory);
- m_dirSelector->setValidationFunction(dirValidationFunction);
- m_dirSelector->setFilePath(defaultDir);
-
- QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
- m_okButton = buttons->button(QDialogButtonBox::Ok);
- m_okButton->setDefault(true);
-
- connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
- connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
- connect(m_nameEditor, &FancyLineEdit::textChanged, this, &CmakeProjectConverterDialog::pathValidChanged);
- connect(m_dirSelector->lineEdit(), &FancyLineEdit::textChanged, this, &CmakeProjectConverterDialog::pathValidChanged);
-
- QGroupBox *form = new QGroupBox();
- QFormLayout *formLayout = new QFormLayout(form);
- formLayout->addRow(PROJECT_NAME_LABEL, m_nameEditor);
- formLayout->addRow(PARENT_DIR_LABEL, m_dirSelector);
-
- QVBoxLayout *dialogLayout = new QVBoxLayout(this);
- dialogLayout->addWidget(mainLabel);
- dialogLayout->addWidget(form);
- dialogLayout->addWidget(m_errorLabel);
- dialogLayout->addWidget(buttons);
-
- pathValidChanged();
-}
-
-void CmakeProjectConverterDialog::pathValidChanged()
-{
- bool valid = isValid();
-
- if (valid)
- m_newProjectDir = m_dirSelector->filePath().pathAppended(m_nameEditor->text());
- else
- m_newProjectDir = FilePath();
-
- const QString error = errorText();
- m_errorLabel->setType(error.isEmpty() ? InfoLabel::None : InfoLabel::Warning);
- m_errorLabel->setText(error);
- m_okButton->setEnabled(valid);
-}
-
-const FilePath CmakeProjectConverterDialog::newPath() const
-{
- return m_newProjectDir;
-}
-
-const QStringList blackListedStarts = {"import","QtQml","QtQuick"};
-
-const QString CmakeProjectConverterDialog::startsWithBlacklisted(const QString &text) const
-{
- for (const QString &badWord : blackListedStarts) {
- if (text.startsWith(badWord))
- return badWord;
- }
-
- return {};
-}
-
-const QString ERROR_TEXT_NAME_EMPTY = Tr::tr("Name is empty.");
-const QString ERROR_TEXT_NAME_BAD_START = Tr::tr("Name must not start with \"%1\".");
-const QString ERROR_TEXT_NAME_LOWERCASE_START = Tr::tr("Name must begin with a capital letter");
-const QString ERROR_TEXT_NAME_BAD_CHARACTERS = Tr::tr("Name must contain only letters, numbers or characters - _.");
-
-const QString ERROR_DIR_NOT_DIR = Tr::tr("Target is not a directory.");
-const QString ERROR_DIR_NOT_WRITABLE = Tr::tr("Cannot write to target directory.");
-const QString ERROR_DIR_EXISTS = Tr::tr("Project directory already exists.");
-
-const QString CmakeProjectConverterDialog::errorText() const
-{
- QString text;
-
- if (!m_nameEditor->isValid()) {
- QString name = m_nameEditor->text();
-
- if (name.isEmpty())
- return ERROR_TEXT_NAME_EMPTY;
-
- const QString badStart = startsWithBlacklisted(text);
- if (!badStart.isEmpty())
- return ERROR_TEXT_NAME_BAD_START.arg(badStart);
-
- if (name[0].isLower())
- return ERROR_TEXT_NAME_LOWERCASE_START;
-
- return ERROR_TEXT_NAME_BAD_CHARACTERS;
-
- }
-
- if (!m_dirSelector->isValid()) {
- FilePath path = m_dirSelector->filePath();
- if (!path.isDir())
- return ERROR_DIR_NOT_DIR;
- if (!path.isWritableDir())
- return ERROR_DIR_NOT_WRITABLE;
- }
-
- if (m_dirSelector->filePath().pathAppended(m_nameEditor->text()).exists())
- return ERROR_DIR_EXISTS;
-
- return text;
-}
-
-const QString CmakeProjectConverterDialog::uniqueProjectName(const FilePath &dir, const QString &oldName) const
-{
- for (unsigned i = 0; ; ++i) {
- QString name = oldName;
- if (i)
- name += QString::number(i);
- if (!dir.pathAppended(name).exists())
- return name;
- }
- return oldName;
-}
-
-bool CmakeProjectConverterDialog::isValid()
-{
- FilePath newPath = m_dirSelector->filePath().pathAppended(m_nameEditor->text());
- return m_dirSelector->isValid() && m_nameEditor->isValid() && !newPath.exists();
-}
-
-} //GenerateCmake
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h
deleted file mode 100644
index 071eec481a..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-
-#ifndef CMAKEPROJECTCONVERTERDIALOG_H
-#define CMAKEPROJECTCONVERTERDIALOG_H
-
-#include <qmlprojectmanager/qmlproject.h>
-#include <utils/fancylineedit.h>
-#include <utils/filepath.h>
-#include <utils/infolabel.h>
-#include <utils/pathchooser.h>
-
-#include <QDialog>
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-class CmakeProjectConverterDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- CmakeProjectConverterDialog(const QmlProjectManager::QmlProject *oldProject);
- const Utils::FilePath newPath() const;
-
-public slots:
- void pathValidChanged();
-
-private:
- const QString startsWithBlacklisted(const QString &text) const;
- const QString errorText() const;
- const QString uniqueProjectName(const Utils::FilePath &dir, const QString &oldName) const;
- bool isValid();
-
-private:
- Utils::FilePath m_newProjectDir;
- Utils::FancyLineEdit *m_nameEditor;
- Utils::PathChooser *m_dirSelector;
- Utils::InfoLabel *m_errorLabel;
- QPushButton *m_okButton;
-};
-
-} //GenerateCmake
-} //QmlProjectManager
-
-#endif // CMAKEPROJECTCONVERTERDIALOG_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.cpp
new file mode 100644
index 0000000000..0b1d0c4c60
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.cpp
@@ -0,0 +1,258 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#include "cmakewriter.h"
+#include "cmakegenerator.h"
+#include "cmakewriterv0.h"
+#include "cmakewriterv1.h"
+
+#include "qmlprojectmanager/qmlproject.h"
+#include "qmlprojectmanager/buildsystem/qmlbuildsystem.h"
+
+#include "utils/namevalueitem.h"
+
+#include <QFile>
+#include <QTextStream>
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+const char TEMPLATE_BIG_RESOURCES[] = R"(
+qt6_add_resources(%1 %2
+ BIG_RESOURCES
+ PREFIX "%3"
+ VERSION 1.0
+ FILES %4
+))";
+
+CMakeWriter::Ptr CMakeWriter::create(CMakeGenerator *parent)
+{
+ const QmlProject *project = parent->qmlProject();
+ QTC_ASSERT(project, return {});
+
+ const QmlBuildSystem *buildSystem = parent->buildSystem();
+ QTC_ASSERT(buildSystem, return {});
+
+ const QString versionString = buildSystem->versionDesignStudio();
+ bool ok = false;
+ if (float version = versionString.toFloat(&ok); ok && version > 4.4)
+ return std::make_unique<CMakeWriterV1>(parent);
+
+ return std::make_unique<CMakeWriterV0>(parent);
+}
+
+QString CMakeWriter::readTemplate(const QString &templatePath)
+{
+ QFile templatefile(templatePath);
+ templatefile.open(QIODevice::ReadOnly);
+ QTextStream stream(&templatefile);
+ QString content = stream.readAll();
+ templatefile.close();
+ return content;
+}
+
+CMakeWriter::CMakeWriter(CMakeGenerator *parent)
+ : m_parent(parent)
+{}
+
+const CMakeGenerator *CMakeWriter::parent() const
+{
+ return m_parent;
+}
+
+bool CMakeWriter::isPlugin(const NodePtr &node) const
+{
+ if (node->type == Node::Type::Module)
+ return true;
+ return false;
+}
+
+QString CMakeWriter::sourceDirName() const
+{
+ return "src";
+}
+
+void CMakeWriter::transformNode(NodePtr &) const
+{}
+
+std::vector<Utils::FilePath> CMakeWriter::files(const NodePtr &node, const FileGetter &getter) const
+{
+ std::vector<Utils::FilePath> out = getter(node);
+ for (const NodePtr &child : node->subdirs) {
+ if (child->type == Node::Type::Module)
+ continue;
+
+ auto childFiles = files(child, getter);
+ out.insert(out.end(), childFiles.begin(), childFiles.end());
+ }
+ return out;
+}
+
+std::vector<Utils::FilePath> CMakeWriter::qmlFiles(const NodePtr &node) const
+{
+ return files(node, [](const NodePtr &n) { return n->files; });
+}
+
+std::vector<Utils::FilePath> CMakeWriter::singletons(const NodePtr &node) const
+{
+ return files(node, [](const NodePtr &n) { return n->singletons; });
+}
+
+std::vector<Utils::FilePath> CMakeWriter::resources(const NodePtr &node) const
+{
+ return files(node, [](const NodePtr &n) { return n->resources; });
+}
+
+std::vector<Utils::FilePath> CMakeWriter::sources(const NodePtr &node) const
+{
+ return files(node, [](const NodePtr &n) { return n->sources; });
+}
+
+std::vector<QString> CMakeWriter::plugins(const NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return {});
+ std::vector<QString> out;
+ collectPlugins(node, out);
+ return out;
+}
+
+QString CMakeWriter::getEnvironmentVariable(const QString &key) const
+{
+ QTC_ASSERT(parent(), return {});
+
+ QString value;
+ if (m_parent->buildSystem()) {
+ auto envItems = m_parent->buildSystem()->environment();
+ auto confEnv = std::find_if(
+ envItems.begin(), envItems.end(), [key](const Utils::EnvironmentItem &item) {
+ return item.name == key;
+ });
+ if (confEnv != envItems.end())
+ value = confEnv->value;
+ }
+ return value;
+}
+
+QString CMakeWriter::makeRelative(const NodePtr &node, const Utils::FilePath &path) const
+{
+ const QString dir = node->dir.toString();
+ return "\"" + Utils::FilePath::calcRelativePath(path.toString(), dir) + "\"";
+}
+
+QString CMakeWriter::makeQmlFilesBlock(const NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return {});
+
+ QString qmlFileContent;
+ for (const Utils::FilePath &path : qmlFiles(node))
+ qmlFileContent.append(QString("\t\t%1\n").arg(makeRelative(node, path)));
+
+ QString str;
+ if (!qmlFileContent.isEmpty())
+ str.append(QString("\tQML_FILES\n%1").arg(qmlFileContent));
+
+ return str;
+}
+
+QString CMakeWriter::makeSingletonBlock(const NodePtr &node) const
+{
+ QString str;
+ const QString setProperties("set_source_files_properties(%1\n\tPROPERTIES\n\t\t%2 %3\n)\n\n");
+ for (const Utils::FilePath &path : node->singletons)
+ str.append(setProperties.arg(path.fileName()).arg("QT_QML_SINGLETON_TYPE").arg("true"));
+ return str;
+}
+
+QString CMakeWriter::makeSubdirectoriesBlock(const NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return {});
+
+ QString str;
+ for (const NodePtr &n : node->subdirs) {
+ if (n->type == Node::Type::Module || n->type == Node::Type::Library
+ || n->type == Node::Type::App || parent()->hasChildModule(n))
+ str.append(QString("add_subdirectory(%1)\n").arg(n->dir.fileName()));
+ }
+ return str;
+}
+
+QString CMakeWriter::makeSetEnvironmentFn() const
+{
+ QTC_ASSERT(parent(), return {});
+ QTC_ASSERT(parent()->buildSystem(), return {});
+
+ const QmlBuildSystem *buildSystem = parent()->buildSystem();
+ const QString configFile = getEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
+
+ QString out("inline void set_qt_environment() {\n");
+ for (Utils::EnvironmentItem &envItem : buildSystem->environment()) {
+ QString key = envItem.name;
+ QString value = envItem.value;
+ if (value == configFile)
+ value.prepend(":/");
+ out.append(QString("\tqputenv(\"%1\", \"%2\");\n").arg(key).arg(value));
+ }
+ out.append("}");
+
+ return out;
+}
+
+std::tuple<QString, QString> CMakeWriter::makeResourcesBlocks(const NodePtr &node) const
+{
+ QString resourcesOut;
+ QString bigResourcesOut;
+
+ QString resourceFiles;
+ std::vector<QString> bigResources;
+ for (const Utils::FilePath &path : resources(node)) {
+ if (path.fileSize() > 5000000) {
+ bigResources.push_back(makeRelative(node, path));
+ continue;
+ }
+ resourceFiles.append(QString("\t\t%1\n").arg(makeRelative(node, path)));
+ }
+
+ if (!resourceFiles.isEmpty())
+ resourcesOut.append(QString("\tRESOURCES\n%1").arg(resourceFiles));
+
+ QString templatePostfix;
+ if (!bigResources.empty()) {
+ QString resourceContent;
+ for (const QString &res : bigResources)
+ resourceContent.append(QString("\n %1").arg(res));
+
+ const QString prefixPath = QString(node->uri).replace('.', '/');
+ const QString prefix = "/qt/qml/" + prefixPath;
+ const QString resourceName = node->name + "BigResource";
+
+ bigResourcesOut = QString::fromUtf8(TEMPLATE_BIG_RESOURCES, -1)
+ .arg(node->name, resourceName, prefix, resourceContent);
+ }
+
+ return {resourcesOut, bigResourcesOut};
+}
+
+void CMakeWriter::writeFile(const Utils::FilePath &path, const QString &content) const
+{
+ QFile fileHandle(path.toString());
+ if (fileHandle.open(QIODevice::WriteOnly)) {
+ QTextStream stream(&fileHandle);
+ stream << content;
+ } else {
+ QString text("Failed to write");
+ CMakeGenerator::logIssue(ProjectExplorer::Task::Error, text, path);
+ }
+ fileHandle.close();
+}
+
+void CMakeWriter::collectPlugins(const NodePtr &node, std::vector<QString> &out) const
+{
+ if (isPlugin(node))
+ out.push_back(node->name);
+ for (const auto &child : node->subdirs)
+ collectPlugins(child, out);
+}
+
+} // End namespace GenerateCmake.
+
+} // End namespace QmlProjectManager.
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.h b/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.h
new file mode 100644
index 0000000000..8766df0dcd
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.h
@@ -0,0 +1,101 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#pragma once
+
+#include "utils/filepath.h"
+
+#include <QString>
+
+namespace QmlProjectManager {
+
+class QmlProject;
+class QmlBuildSystem;
+
+namespace GenerateCmake {
+
+struct Node
+{
+ enum class Type {
+ App,
+ Module,
+ Library,
+ Folder,
+ };
+
+ std::shared_ptr<Node> parent = nullptr;
+ Type type = Type::Folder;
+
+ QString uri;
+ QString name;
+ Utils::FilePath dir;
+
+ std::vector<std::shared_ptr<Node>> subdirs;
+ std::vector<Utils::FilePath> files;
+ std::vector<Utils::FilePath> singletons;
+ std::vector<Utils::FilePath> resources;
+ std::vector<Utils::FilePath> sources;
+};
+
+using NodePtr = std::shared_ptr<Node>;
+using FileGetter = std::function<std::vector<Utils::FilePath>(const NodePtr &)>;
+
+class CMakeGenerator;
+
+const char ENV_VARIABLE_CONTROLCONF[] =
+ "QT_QUICK_CONTROLS_CONF";
+
+const char DO_NOT_EDIT_FILE[] =
+ "### This file is automatically generated by Qt Design Studio.\n"
+ "### Do not change\n\n";
+
+const char TEMPLATE_LINK_LIBRARIES[] =
+ "target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE\n"
+ "%3"
+ ")";
+
+class CMakeWriter
+{
+public:
+ using Ptr = std::shared_ptr<CMakeWriter>;
+
+ static Ptr create(CMakeGenerator *parent);
+ static QString readTemplate(const QString &templatePath);
+
+ CMakeWriter(CMakeGenerator *parent);
+ const CMakeGenerator *parent() const;
+
+ virtual bool isPlugin(const NodePtr &node) const;
+ virtual QString sourceDirName() const;
+ virtual void transformNode(NodePtr &) const;
+
+ virtual void writeRootCMakeFile(const NodePtr &node) const = 0;
+ virtual void writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const = 0;
+ virtual void writeSourceFiles(const NodePtr &node, const NodePtr &root) const = 0;
+
+protected:
+ std::vector<Utils::FilePath> files(const NodePtr &node, const FileGetter &getter) const;
+ std::vector<Utils::FilePath> qmlFiles(const NodePtr &node) const;
+ std::vector<Utils::FilePath> singletons(const NodePtr &node) const;
+ std::vector<Utils::FilePath> resources(const NodePtr &node) const;
+ std::vector<Utils::FilePath> sources(const NodePtr &node) const;
+ std::vector<QString> plugins(const NodePtr &node) const;
+
+ QString getEnvironmentVariable(const QString &key) const;
+
+ QString makeRelative(const NodePtr &node, const Utils::FilePath &path) const;
+ QString makeQmlFilesBlock(const NodePtr &node) const;
+ QString makeSingletonBlock(const NodePtr &node) const;
+ QString makeSubdirectoriesBlock(const NodePtr &node) const;
+ QString makeSetEnvironmentFn() const;
+ std::tuple<QString, QString> makeResourcesBlocks(const NodePtr &node) const;
+
+ void writeFile(const Utils::FilePath &path, const QString &content) const;
+
+private:
+ void collectPlugins(const NodePtr &node, std::vector<QString> &out) const;
+ const CMakeGenerator *m_parent = nullptr;
+};
+
+} // End namespace GenerateCmake.
+
+} // End namespace QmlProjectManager.
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.cpp
new file mode 100644
index 0000000000..5cb17d1e1b
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.cpp
@@ -0,0 +1,180 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#include "cmakewriterv0.h"
+#include "cmakegenerator.h"
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+const char TEMPLATE_ADD_QML_MODULE[] = R"(
+qt6_add_qml_module(%1
+ URI "%2"
+ VERSION 1.0
+ RESOURCE_PREFIX "/qt/qml"
+%3))";
+
+CMakeWriterV0::CMakeWriterV0(CMakeGenerator *parent)
+ : CMakeWriter(parent)
+{}
+
+bool CMakeWriterV0::isPlugin(const NodePtr &node) const
+{
+ if (node->type == Node::Type::App)
+ return !node->files.empty() || !node->singletons.empty() || !node->resources.empty();
+
+ return CMakeWriter::isPlugin(node);
+}
+
+void CMakeWriterV0::transformNode(NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return);
+
+ if (node->name == "src") {
+ node->type = Node::Type::Folder;
+ } else if (node->name == "content") {
+ node->type = Node::Type::Module;
+ } else if (node->type == Node::Type::App) {
+ Utils::FilePath path = node->dir.pathAppended("main.qml");
+ if (!path.exists()) {
+ QString text("Expected File not found.");
+ CMakeGenerator::logIssue(ProjectExplorer::Task::Error, text, path);
+ return;
+ }
+ if (!parent()->findFile(path))
+ node->files.push_back(path);
+ }
+}
+
+void CMakeWriterV0::writeRootCMakeFile(const NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return);
+
+ const Utils::FilePath quickControlsPath = node->dir.pathAppended("qtquickcontrols2.conf");
+ if (!quickControlsPath.exists()) {
+ const QString quickControlsTemplate = readTemplate(":/templates/qtquickcontrols_conf");
+ writeFile(quickControlsPath, quickControlsTemplate);
+ }
+
+ const Utils::FilePath insightPath = node->dir.pathAppended("insight");
+ if (!insightPath.exists()) {
+ const QString insightTemplate = readTemplate(":/templates/insight");
+ writeFile(insightPath, insightTemplate);
+ }
+
+ const Utils::FilePath componentPath = node->dir.pathAppended("qmlcomponents");
+ if (!componentPath.exists()) {
+ const QString compTemplate = readTemplate(":/templates/qmlcomponents");
+ writeFile(componentPath, compTemplate);
+ }
+
+ const QString appName = parent()->projectName() + "App";
+ const QString qtcontrolsConfFile = getEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
+
+ QString fileSection = "";
+ if (!qtcontrolsConfFile.isEmpty())
+ fileSection = QString("\tFILES\n\t\t%1").arg(qtcontrolsConfFile);
+
+ QStringList srcs;
+ for (const Utils::FilePath &path : sources(node))
+ srcs.push_back(makeRelative(node, path));
+
+ const QString fileTemplate = readTemplate(":/templates/cmakeroot_v0");
+ const QString fileContent = fileTemplate.arg(appName, srcs.join(" "), fileSection);
+
+ const Utils::FilePath cmakeFile = node->dir.pathAppended("CMakeLists.txt");
+ writeFile(cmakeFile, fileContent);
+}
+
+void CMakeWriterV0::writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const
+{
+ QTC_ASSERT(parent(), return);
+
+ Utils::FilePath writeToFile = node->dir.pathAppended("CMakeLists.txt");
+
+ QString content(DO_NOT_EDIT_FILE);
+ if (node->type == Node::Type::Folder && parent()->hasChildModule(node)) {
+ content.append(makeSubdirectoriesBlock(node));
+ writeFile(writeToFile, content);
+ return;
+ }
+
+ content.append(makeSubdirectoriesBlock(node));
+ content.append("\n");
+ content.append(makeSingletonBlock(node));
+
+ QString qmlModulesContent;
+ qmlModulesContent.append(makeQmlFilesBlock(node));
+
+ auto [resources, bigResources] = makeResourcesBlocks(node);
+ qmlModulesContent.append(resources);
+
+ if (!qmlModulesContent.isEmpty()) {
+ const QString addLibraryTemplate("qt_add_library(%1 STATIC)");
+ const QString addModuleTemplate(TEMPLATE_ADD_QML_MODULE);
+
+ content.append(addLibraryTemplate.arg(node->name));
+ content.append(addModuleTemplate.arg(node->name, node->uri, qmlModulesContent));
+ content.append("\n\n");
+ }
+
+ content.append(bigResources);
+
+ if (node->type == Node::Type::App) {
+ writeToFile = node->dir.pathAppended("qmlModules");
+ QString pluginNames;
+ for (const QString &moduleName : plugins(root))
+ pluginNames.append("\t" + moduleName + "plugin\n");
+
+ if (!pluginNames.isEmpty())
+ content += QString::fromUtf8(TEMPLATE_LINK_LIBRARIES, -1).arg(pluginNames);
+ }
+
+ writeFile(writeToFile, content);
+}
+
+void CMakeWriterV0::writeSourceFiles(const NodePtr &node, const NodePtr &root) const
+{
+ QTC_ASSERT(parent(), return);
+
+ const Utils::FilePath srcDir = node->dir;
+ if (!srcDir.exists()) {
+ srcDir.createDir();
+
+ const Utils::FilePath componentsHeaderPath = srcDir.pathAppended(
+ "import_qml_components_plugins.h");
+ const QString componentsHeaderContent = readTemplate(
+ ":/templates/import_qml_components_h");
+ writeFile(componentsHeaderPath, componentsHeaderContent);
+
+ const Utils::FilePath cppFilePath = srcDir.pathAppended("main.cpp");
+ const QString cppContent = readTemplate(":/templates/main_cpp_v0");
+ writeFile(cppFilePath, cppContent);
+ }
+
+ QString fileHeader(
+ "/*\n"
+ " * This file is automatically generated by Qt Design Studio.\n"
+ " * Do not change\n"
+ "*/\n\n");
+
+ const Utils::FilePath envHeaderPath = srcDir.pathAppended("app_environment.h");
+ QString envHeaderContent(fileHeader);
+ envHeaderContent.append("#include <QGuiApplication>\n\n");
+ envHeaderContent.append(makeSetEnvironmentFn());
+ writeFile(envHeaderPath, envHeaderContent);
+
+ QString importPluginsContent;
+ for (const QString &module : plugins(root))
+ importPluginsContent.append(QString("Q_IMPORT_QML_PLUGIN(%1)\n").arg(module + "Plugin"));
+
+ QString importPluginsHeader(fileHeader);
+ importPluginsHeader.append("#include <QtQml/qqmlextensionplugin.h>\n\n");
+ importPluginsHeader.append(importPluginsContent);
+
+ const Utils::FilePath headerFilePath = srcDir.pathAppended("import_qml_plugins.h");
+ writeFile(headerFilePath, importPluginsHeader);
+}
+
+} // namespace GenerateCmake
+} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.h b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.h
new file mode 100644
index 0000000000..a1cd16d0fc
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.h
@@ -0,0 +1,25 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#pragma once
+
+#include "cmakewriter.h"
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+class CMakeWriterV0 final : public CMakeWriter
+{
+public:
+ CMakeWriterV0(CMakeGenerator *parent);
+
+ bool isPlugin(const NodePtr &node) const override;
+ void transformNode(NodePtr &node) const override;
+
+ void writeRootCMakeFile(const NodePtr &node) const override;
+ void writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const override;
+ void writeSourceFiles(const NodePtr &node, const NodePtr &root) const override;
+};
+
+} // namespace GenerateCmake
+} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.cpp
new file mode 100644
index 0000000000..6d2d93a76b
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.cpp
@@ -0,0 +1,185 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#include "cmakewriterv1.h"
+#include "cmakegenerator.h"
+
+#include "qmlprojectmanager/buildsystem/qmlbuildsystem.h"
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+const char TEMPLATE_SRC_CMAKELISTS[] = R"(
+target_sources(${CMAKE_PROJECT_NAME} PUBLIC
+%2)
+
+target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
+ Qt${QT_VERSION_MAJOR}::Core
+ Qt${QT_VERSION_MAJOR}::Gui
+ Qt${QT_VERSION_MAJOR}::Quick
+ Qt${QT_VERSION_MAJOR}::Qml))";
+
+CMakeWriterV1::CMakeWriterV1(CMakeGenerator *parent)
+ : CMakeWriter(parent)
+{}
+
+QString CMakeWriterV1::sourceDirName() const
+{
+ return "App";
+}
+
+void CMakeWriterV1::transformNode(NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return);
+
+ QString contentDir = parent()->projectName() + "Content";
+ if (node->name == contentDir)
+ node->type = Node::Type::Module;
+}
+
+void CMakeWriterV1::writeRootCMakeFile(const NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return);
+
+ const Utils::FilePath cmakeFolderPath = node->dir.pathAppended("cmake");
+ if (!cmakeFolderPath.exists())
+ cmakeFolderPath.createDir();
+
+ const Utils::FilePath insightPath = cmakeFolderPath.pathAppended("insight.cmake");
+ if (!insightPath.exists()) {
+ const QString insightTemplate = readTemplate(":/templates/insight");
+ writeFile(insightPath, insightTemplate);
+ }
+
+ const Utils::FilePath componentPath = cmakeFolderPath.pathAppended("qmlcomponents.cmake");
+ if (!componentPath.exists()) {
+ const QString compTemplate = readTemplate(":/templates/qmlcomponents");
+ writeFile(componentPath, compTemplate);
+ }
+
+ const Utils::FilePath sharedFile = node->dir.pathAppended("CMakeLists.txt.shared");
+ if (!sharedFile.exists()) {
+ const QString sharedTemplate = readTemplate(":/templates/cmake_shared");
+ writeFile(sharedFile, sharedTemplate);
+ }
+
+ const Utils::FilePath file = node->dir.pathAppended("CMakeLists.txt");
+ if (!file.exists()) {
+ const QString appName = parent()->projectName() + "App";
+
+ QString fileSection = "";
+ const QString configFile = getEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
+ if (!configFile.isEmpty())
+ fileSection = QString("\t\t%1").arg(configFile);
+
+ const QString fileTemplate = readTemplate(":/templates/cmakeroot_v1");
+ const QString fileContent = fileTemplate.arg(appName, fileSection);
+ writeFile(file, fileContent);
+ }
+}
+
+void CMakeWriterV1::writeModuleCMakeFile(const NodePtr &node, const NodePtr &) const
+{
+ QTC_ASSERT(parent(), return);
+
+ if (node->type == Node::Type::App) {
+ const Utils::FilePath userFile = node->dir.pathAppended("qds.cmake");
+ QString userFileContent(DO_NOT_EDIT_FILE);
+ userFileContent.append(makeSubdirectoriesBlock(node));
+ userFileContent.append("\n");
+
+ QString pluginNames;
+ std::vector<QString> plugs = plugins(node);
+ for (size_t i = 0; i < plugs.size(); ++i) {
+ pluginNames.append("\t" + plugs[i] + "plugin");
+ if (i != plugs.size() - 1)
+ pluginNames.append("\n");
+ }
+
+ QString linkLibrariesTemplate(
+ "target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE\n"
+ "%1)");
+
+ userFileContent.append(linkLibrariesTemplate.arg(pluginNames));
+ writeFile(userFile, userFileContent);
+ return;
+ }
+
+ Utils::FilePath writeToFile = node->dir.pathAppended("CMakeLists.txt");
+ if (node->type == Node::Type::Folder && parent()->hasChildModule(node)) {
+ QString content(DO_NOT_EDIT_FILE);
+ content.append(makeSubdirectoriesBlock(node));
+ writeFile(writeToFile, content);
+ return;
+ }
+
+ QString prefix;
+ prefix.append(makeSubdirectoriesBlock(node));
+ prefix.append(makeSingletonBlock(node));
+
+ auto [resources, bigResources] = makeResourcesBlocks(node);
+ QString moduleContent;
+ moduleContent.append(makeQmlFilesBlock(node));
+ moduleContent.append(resources);
+
+ QString postfix;
+ postfix.append(bigResources);
+
+ const QString fileTemplate = readTemplate(":/templates/cmakemodule_v1");
+ const QString fileContent = fileTemplate
+ .arg(node->name, node->uri, prefix, moduleContent, postfix);
+ writeFile(writeToFile, fileContent);
+}
+
+void CMakeWriterV1::writeSourceFiles(const NodePtr &node, const NodePtr &root) const
+{
+ QTC_ASSERT(parent(), return);
+ QTC_ASSERT(parent()->buildSystem(), return);
+
+ const QmlBuildSystem *buildSystem = parent()->buildSystem();
+
+ const Utils::FilePath srcDir = node->dir;
+ if (!srcDir.exists())
+ srcDir.createDir();
+
+ const Utils::FilePath autogenDir = srcDir.pathAppended("autogen");
+ if (!autogenDir.exists())
+ autogenDir.createDir();
+
+ const Utils::FilePath mainCppPath = srcDir.pathAppended("main.cpp");
+ if (!mainCppPath.exists()) {
+ const QString cppContent = readTemplate(":/templates/main_cpp_v1");
+ writeFile(mainCppPath, cppContent);
+ }
+
+ const Utils::FilePath cmakePath = srcDir.pathAppended("CMakeLists.txt");
+ if (!cmakePath.exists()) {
+ std::vector<Utils::FilePath> sourcePaths = sources(node);
+ if (sourcePaths.empty())
+ sourcePaths.push_back(mainCppPath);
+
+ QString srcs = {};
+ for (const Utils::FilePath &src : sourcePaths)
+ srcs.append("\t" + makeRelative(node, src) + "\n");
+
+ QString fileTemplate = QString::fromUtf8(TEMPLATE_SRC_CMAKELISTS, -1).arg(srcs);
+ writeFile(cmakePath, fileTemplate);
+ }
+
+ const Utils::FilePath headerPath = autogenDir.pathAppended("environment.h");
+
+ QString environmentPrefix;
+ for (const QString &module : plugins(root))
+ environmentPrefix.append(QString("Q_IMPORT_QML_PLUGIN(%1)\n").arg(module + "Plugin"));
+
+ const QString mainFile("const char mainQmlFile[] = \"qrc:/qt/qml/%1\";");
+ environmentPrefix.append("\n");
+ environmentPrefix.append(mainFile.arg(buildSystem->mainFile()));
+
+ const QString environmentPostfix = makeSetEnvironmentFn();
+ const QString headerTemplate = readTemplate(":/templates/environment_h");
+ writeFile(headerPath, headerTemplate.arg(environmentPrefix, environmentPostfix));
+}
+
+} // namespace GenerateCmake
+} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.h b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.h
new file mode 100644
index 0000000000..2a6a05b07b
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.h
@@ -0,0 +1,25 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#pragma once
+
+#include "cmakewriter.h"
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+class CMakeWriterV1 final : public CMakeWriter
+{
+public:
+ CMakeWriterV1(CMakeGenerator *parent);
+
+ QString sourceDirName() const override;
+ void transformNode(NodePtr &node) const override;
+
+ void writeRootCMakeFile(const NodePtr &node) const override;
+ void writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const override;
+ void writeSourceFiles(const NodePtr &node, const NodePtr &root) const override;
+};
+
+} // namespace GenerateCmake
+} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
deleted file mode 100644
index f46b508c8c..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
+++ /dev/null
@@ -1,668 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "generatecmakelists.h"
-
-#include "generatecmakelistsconstants.h"
-#include "cmakegeneratordialog.h"
-#include "../qmlprojectmanagertr.h"
-
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/actionmanager/actioncontainer.h>
-
-#include <projectexplorer/buildsystem.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/projectmanager.h>
-#include <projectexplorer/target.h>
-
-#include <qmlprojectmanager/buildsystem/qmlbuildsystem.h>
-#include <qmlprojectmanager/qmlmainfileaspect.h>
-#include <qmlprojectmanager/qmlproject.h>
-#include <qmlprojectmanager/qmlprojectconstants.h>
-
-#include <extensionsystem/iplugin.h>
-#include <extensionsystem/pluginmanager.h>
-#include <extensionsystem/pluginspec.h>
-
-#include <utils/fileutils.h>
-
-#include <QAction>
-#include <QMenu>
-#include <QMessageBox>
-#include <QRegularExpression>
-#include <QStringList>
-#include <QTextStream>
-#include <QtConcurrent>
-
-using namespace Utils;
-using namespace QmlProjectManager::GenerateCmake::Constants;
-
-namespace QmlProjectManager {
-
-namespace GenerateCmake {
-
-static bool isQmlDesigner(const ExtensionSystem::PluginSpec *spec)
-{
- if (!spec)
- return false;
-
- return spec->name().contains("QmlDesigner");
-}
-
-static void trackUsage(const QString &id)
-{
- const auto plugins = ExtensionSystem::PluginManager::plugins();
- const auto it = std::find_if(plugins.begin(), plugins.end(), &isQmlDesigner);
- if (it != plugins.end()) {
- QObject *qmlDesignerPlugin = (*it)->plugin();
- QMetaObject::invokeMethod(qmlDesignerPlugin,
- "usageStatisticsNotifier",
- Qt::DirectConnection,
- Q_ARG(QString, id));
- }
-}
-
-bool operator==(const GeneratableFile &left, const GeneratableFile &right)
-{
- return (left.filePath == right.filePath && left.content == right.content);
-}
-
-enum ProjectDirectoryError {
- NoError = 0,
- MissingContentDir = 1<<1,
- MissingImportDir = 1<<2,
- MissingAssetDir = 1<<3,
- MissingAssetImportDir = 1<<4,
- MissingCppDir = 1<<5,
- MissingMainCMake = 1<<6,
- MissingMainQml = 1<<7,
- MissingAppMainQml = 1<<8,
- MissingQmlModules = 1<<9,
- MissingMainCpp = 1<<10,
- MissingMainCppHeader = 1<<11,
- MissingEnvHeader = 1<<12
-};
-
-const QString MENU_ITEM_GENERATE = Tr::tr("Generate CMake Build Files...");
-
-void generateMenuEntry(QObject *parent)
-{
- Core::ActionContainer *menu = Core::ActionManager::actionContainer(Core::Constants::M_FILE);
-
- Core::ActionContainer *exportMenu = Core::ActionManager::createMenu(
- QmlProjectManager::Constants::EXPORT_MENU);
-
- exportMenu->menu()->setTitle(Tr::tr("Export Project"));
- menu->addMenu(exportMenu, Core::Constants::G_FILE_EXPORT);
-
- exportMenu->appendGroup(QmlProjectManager::Constants::G_EXPORT_GENERATE);
- exportMenu->appendGroup(QmlProjectManager::Constants::G_EXPORT_CONVERT);
- exportMenu->addSeparator(QmlProjectManager::Constants::G_EXPORT_CONVERT);
-
- auto action = new QAction(MENU_ITEM_GENERATE, parent);
- QObject::connect(action, &QAction::triggered, GenerateCmake::onGenerateCmakeLists);
- Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.CreateCMakeLists");
- exportMenu->addAction(cmd, QmlProjectManager::Constants::G_EXPORT_GENERATE);
-
- action->setEnabled(false);
- QObject::connect(ProjectExplorer::ProjectManager::instance(),
- &ProjectExplorer::ProjectManager::startupProjectChanged,
- [action]() {
- if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem())
- action->setEnabled(!buildSystem->qtForMCUs());
- });
-}
-
-void onGenerateCmakeLists()
-{
- trackUsage("generateCMakeProjectDialogOpened");
- FilePath rootDir = ProjectExplorer::ProjectManager::startupProject()->projectDirectory();
-
- int projectDirErrors = isProjectCorrectlyFormed(rootDir);
- if (projectDirErrors != NoError) {
- showProjectDirErrorDialog(projectDirErrors);
- if (isErrorFatal(projectDirErrors))
- return;
- }
-
- CmakeFileGenerator cmakeGen;
- cmakeGen.prepare(rootDir);
-
- FilePaths allFiles;
- for (const GeneratableFile &file: cmakeGen.fileQueue().queuedFiles())
- allFiles.append(file.filePath);
-
- CmakeGeneratorDialog dialog(rootDir, allFiles, cmakeGen.invalidFileNames());
- if (dialog.exec()) {
- FilePaths confirmedFiles = dialog.getFilePaths();
- cmakeGen.filterFileQueue(confirmedFiles);
- cmakeGen.execute();
- }
-
- trackUsage("generateCMakeProjectExecuted");
-}
-
-bool isErrorFatal(int error)
-{
- if (error & MissingContentDir ||
- error & MissingImportDir ||
- error & MissingCppDir ||
- error & MissingAppMainQml)
- return true;
-
- return false;
-}
-
-int isProjectCorrectlyFormed(const FilePath &rootDir)
-{
- int errors = NoError;
-
- if (!rootDir.pathAppended(DIRNAME_CONTENT).exists())
- errors |= MissingContentDir;
- if (!rootDir.pathAppended(DIRNAME_CONTENT).pathAppended(FILENAME_APPMAINQML).exists())
- errors |= MissingAppMainQml;
-
- if (!rootDir.pathAppended(DIRNAME_IMPORT).exists())
- errors |= MissingImportDir;
- if (!rootDir.pathAppended(DIRNAME_ASSETIMPORT).exists())
- errors |= MissingAssetImportDir;
-
- if (!rootDir.pathAppended(DIRNAME_CPP).exists())
- errors |= MissingCppDir;
- if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_MAINCPP).exists())
- errors |= MissingMainCpp;
- if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_MAINCPP_HEADER).exists())
- errors |= MissingMainCppHeader;
- if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_ENV_HEADER).exists())
- errors |= MissingEnvHeader;
-
- if (!rootDir.pathAppended(FILENAME_CMAKELISTS).exists())
- errors |= MissingMainCMake;
- if (!rootDir.pathAppended(FILENAME_MODULES).exists())
- errors |= MissingQmlModules;
- if (!rootDir.pathAppended(FILENAME_MAINQML).exists())
- errors |= MissingMainQml;
-
- return errors;
-}
-
-const QString WARNING_MISSING_STRUCTURE_FATAL = Tr::tr("The project is not properly structured for automatically generating CMake files.\n\nAborting process.\n\nThe following files or directories are missing:\n\n%1");
-//const QString WARNING_MISSING_STRUCTURE_NONFATAL = Tr::tr("The project is not properly structured for automatically generating CMake files.\n\nThe following files or directories are missing and may be created:\n\n%1");
-const QString WARNING_TITLE_FATAL = Tr::tr("Cannot Generate CMake Files");
-//const QString WARNING_TITLE_NONFATAL = Tr::tr("Problems with Generating CMake Files");
-
-void showProjectDirErrorDialog(int error)
-{
- bool isFatal = isErrorFatal(error);
-
- if (isFatal) {
- QString fatalList;
-
- if (error & MissingContentDir)
- fatalList.append(QString(DIRNAME_CONTENT) + "\n");
- if (error & MissingAppMainQml)
- fatalList.append(QString(DIRNAME_CONTENT)
- + QDir::separator()
- + QString(FILENAME_APPMAINQML)
- + "\n");
- if (error & MissingCppDir)
- fatalList.append(QString(DIRNAME_CPP) + "\n");
- if (error & MissingImportDir)
- fatalList.append(QString(DIRNAME_IMPORT) + "\n");
-
- QMessageBox::critical(nullptr,
- WARNING_TITLE_FATAL,
- WARNING_MISSING_STRUCTURE_FATAL.arg(fatalList));
- }
-}
-
-bool FileQueue::queueFile(const FilePath &filePath, const QString &fileContent)
-{
- GeneratableFile file;
- file.filePath = filePath;
- file.content = fileContent;
- file.fileExists = filePath.exists();
- m_queuedFiles.append(file);
-
- return true;
-}
-
-const QVector<GeneratableFile> FileQueue::queuedFiles() const
-{
- return m_queuedFiles;
-}
-
-bool FileQueue::writeQueuedFiles()
-{
- for (GeneratableFile &file: m_queuedFiles)
- if (!writeFile(file))
- return false;
-
- return true;
-}
-
-bool FileQueue::writeFile(const GeneratableFile &file)
-{
- QFile fileHandle(file.filePath.toString());
- fileHandle.open(QIODevice::WriteOnly);
- QTextStream stream(&fileHandle);
- stream << file.content;
- fileHandle.close();
-
- return true;
-}
-
-void FileQueue::filterFiles(const Utils::FilePaths keepFiles)
-{
- QtConcurrent::blockingFilter(m_queuedFiles, [keepFiles](const GeneratableFile &qf) {
- return keepFiles.contains(qf.filePath);
- });
-}
-
-QString readTemplate(const QString &templatePath)
-{
- QFile templatefile(templatePath);
- templatefile.open(QIODevice::ReadOnly);
- QTextStream stream(&templatefile);
- QString content = stream.readAll();
- templatefile.close();
-
- return content;
-}
-
-const QString projectEnvironmentVariable(const QString &key)
-{
- QString value = {};
-
- if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem()) {
- auto envItems = buildSystem->environment();
- auto confEnv = std::find_if(envItems.begin(), envItems.end(), [key](EnvironmentItem &item) {
- return item.name == key;
- });
- if (confEnv != envItems.end())
- value = confEnv->value;
- }
-
- return value;
-}
-
-const QDir::Filters FILES_ONLY = QDir::Files;
-const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
-
-const char MAIN_CMAKEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincmakelists.tpl";
-const char QMLMODULES_FILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodules.tpl";
-
-bool CmakeFileGenerator::prepare(const FilePath &rootDir, bool checkFileBelongs)
-{
- m_checkFileIsInProject = checkFileBelongs;
-
- FilePath contentDir = rootDir.pathAppended(DIRNAME_CONTENT);
- FilePath importDir = rootDir.pathAppended(DIRNAME_IMPORT);
- FilePath assetImportDir = rootDir.pathAppended(DIRNAME_ASSETIMPORT);
-
- generateModuleCmake(contentDir);
- generateImportCmake(importDir);
- generateImportCmake(assetImportDir);
- generateMainCmake(rootDir);
- generateEntryPointFiles(rootDir);
-
- return true;
-}
-
-const FileQueue CmakeFileGenerator::fileQueue() const
-{
- return m_fileQueue;
-}
-
-void CmakeFileGenerator::filterFileQueue(const Utils::FilePaths &keepFiles)
-{
- m_fileQueue.filterFiles(keepFiles);
-}
-
-bool CmakeFileGenerator::execute()
-{
- return m_fileQueue.writeQueuedFiles();
-}
-
-FilePaths CmakeFileGenerator::invalidFileNames() const
-{
- return m_invalidFileNames;
-}
-
-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 CmakeFileGenerator::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::ProjectManager::startupProject()->displayName();
- QString appName = projectName + "App";
-
- QString fileSection = "";
- const QString qtcontrolsConfFile = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
- if (!qtcontrolsConfFile.isEmpty())
- fileSection = QString(" FILES\n %1").arg(qtcontrolsConfFile);
-
- QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH)
- .arg(appName)
- .arg(fileSection);
-
- queueCmakeFile(rootDir, cmakeFileContent);
-
- QString subdirIncludes;
- subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_CONTENT));
- subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_IMPORT));
- if (rootDir.pathAppended(DIRNAME_ASSETIMPORT).exists())
- subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_ASSETIMPORT));
-
- QString modulesAsPlugins;
- for (const QString &moduleName : m_moduleNames)
- modulesAsPlugins.append(" " + moduleName + "plugin\n");
-
- QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH)
- .arg(appName)
- .arg(subdirIncludes)
- .arg(modulesAsPlugins);
-
- m_fileQueue.queueFile(rootDir.pathAppended(FILENAME_MODULES), moduleFileContent);
-}
-
-void CmakeFileGenerator::generateImportCmake(const FilePath &dir, const QString &modulePrefix)
-{
- if (!dir.exists())
- return;
-
- QString fileContent;
-
- fileContent.append(DO_NOT_EDIT_FILE_COMMENT);
- FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
- for (FilePath &subDir : subDirs) {
- if (isDirBlacklisted(subDir))
- continue;
- if (getDirectoryTreeQmls(subDir).isEmpty() && getDirectoryTreeResources(subDir).isEmpty())
- continue;
- fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
- QString prefix = modulePrefix.isEmpty() ?
- QString(modulePrefix % subDir.fileName()) :
- QString(QString(modulePrefix + '.') + subDir.fileName());
- if (getDirectoryQmls(subDir).isEmpty()) {
- generateImportCmake(subDir, prefix);
- } else {
- generateModuleCmake(subDir, prefix);
- }
- }
-
- queueCmakeFile(dir, fileContent);
-}
-
-const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE";
-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";
-
-void CmakeFileGenerator::generateModuleCmake(const FilePath &dir, const QString &uri)
-{
- QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH);
-
- QString singletonContent;
- FilePaths qmldirFileList = dir.dirEntries({QStringList(FILENAME_QMLDIR), FILES_ONLY});
- if (!qmldirFileList.isEmpty()) {
- QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
- for (QString &singleton : singletons) {
- 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(" %1\n").arg(qmlFile));
-
- QStringList resourceFileList = getDirectoryTreeResources(dir);
- QString resourceFiles;
- for (QString &resourceFile : resourceFileList)
- resourceFiles.append(QString(" %1\n").arg(resourceFile));
-
- QString moduleContent;
- if (!qmlFiles.isEmpty()) {
- moduleContent.append(QString(" QML_FILES\n%1").arg(qmlFiles));
- }
- if (!resourceFiles.isEmpty()) {
- moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles));
- }
-
- QString moduleUri = uri.isEmpty() ?
- dir.fileName() :
- uri;
-
- QString moduleName = QString(moduleUri).replace('.', '_');
- m_moduleNames.append(moduleName);
-
- QString fileContent;
- fileContent.append(fileTemplate.arg(singletonContent, moduleName, moduleUri, moduleContent));
- queueCmakeFile(dir, fileContent);
-}
-
-QStringList CmakeFileGenerator::getSingletonsFromQmldirFile(const FilePath &filePath)
-{
- QStringList singletons;
- QFile f(filePath.toString());
- f.open(QIODevice::ReadOnly);
- QTextStream stream(&f);
-
- while (!stream.atEnd()) {
- QString line = stream.readLine();
- if (line.startsWith("singleton", Qt::CaseInsensitive)) {
- QStringList tokenizedLine = line.split(QRegularExpression("\\s+"));
- QString fileName = tokenizedLine.last();
- if (fileName.endsWith(".qml", Qt::CaseInsensitive)) {
- singletons.append(fileName);
- }
- }
- }
-
- f.close();
-
- return singletons;
-}
-
-QStringList CmakeFileGenerator::getDirectoryQmls(const FilePath &dir)
-{
- QStringList moduleFiles;
-
- const QStringList qmlFilesOnly(FILENAME_FILTER_QML);
- FilePaths allFiles = dir.dirEntries({qmlFilesOnly, FILES_ONLY});
- for (FilePath &file : allFiles) {
- if (includeFile(file)) {
- moduleFiles.append(file.fileName());
- }
- }
-
- return moduleFiles;
-}
-
-QStringList CmakeFileGenerator::getDirectoryResources(const FilePath &dir)
-{
- QStringList moduleFiles;
-
- FilePaths allFiles = dir.dirEntries(FILES_ONLY);
- for (FilePath &file : allFiles) {
- if (!file.fileName().endsWith(".qml", Qt::CaseInsensitive) && includeFile(file)) {
- moduleFiles.append(file.fileName());
- }
- }
-
- return moduleFiles;
-}
-
-QStringList CmakeFileGenerator::getDirectoryTreeQmls(const FilePath &dir)
-{
- QStringList qmlFileList;
-
- qmlFileList.append(getDirectoryQmls(dir));
-
- FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
- for (FilePath &subDir : subDirsList) {
- if (isDirBlacklisted(subDir))
- continue;
- QStringList subDirQmlFiles = getDirectoryTreeQmls(subDir);
- for (QString &qmlFile : subDirQmlFiles) {
- qmlFileList.append(subDir.fileName().append('/').append(qmlFile));
- }
- }
-
- return qmlFileList;
-}
-
-static void appendWidthQuotes(QStringList &list, const QString &string)
-{
- if (string.contains(' '))
- list.append("\"" + string + "\"");
- else
- list.append(string);
-}
-
-QStringList CmakeFileGenerator::getDirectoryTreeResources(const FilePath &dir)
-{
- QStringList resourceFileList;
-
- //for (const auto &string : getDirectoryResources(dir))
- // appendWidthQuotes(resourceFileList, string);
- resourceFileList.append(getDirectoryResources(dir));
-
- FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
- for (FilePath &subDir : subDirsList) {
- if (isDirBlacklisted(subDir))
- continue;
- QStringList subDirResources = getDirectoryTreeResources(subDir);
- for (QString &resource : subDirResources) {
- appendWidthQuotes(resourceFileList, subDir.fileName().append('/').append(resource));
- }
- }
-
- return resourceFileList;
-}
-
-void CmakeFileGenerator::queueCmakeFile(const FilePath &dir, const QString &content)
-{
- FilePath filePath = dir.pathAppended(FILENAME_CMAKELISTS);
- m_fileQueue.queueFile(filePath, content);
-}
-
-bool CmakeFileGenerator::isFileBlacklisted(const QString &fileName)
-{
- return (!fileName.compare(FILENAME_QMLDIR) ||
- !fileName.compare(FILENAME_CMAKELISTS));
-}
-
-bool CmakeFileGenerator::isDirBlacklisted(const FilePath &dir)
-{
- return (!dir.fileName().compare(DIRNAME_DESIGNER));
-}
-
-bool CmakeFileGenerator::validFileName(const Utils::FilePath &filePath)
-{
- QStringList invalidChars = {"!", "\"", "£", "$", "%", "!", "^", "&", "*", "(", ")", "=", "+",
- "'", ",", ";", ":", "#", "~", "{", "{", "[", "]", "<", ">", "?"};
- const QString baseName = filePath.baseName();
- for (const auto &c : invalidChars) {
- if (baseName.contains(c))
- return false;
- }
- return true;
-}
-
-bool CmakeFileGenerator::includeFile(const FilePath &filePath)
-{
- if (m_checkFileIsInProject) {
- ProjectExplorer::Project *project = ProjectExplorer::ProjectManager::startupProject();
- if (!project->isKnownFile(filePath))
- return false;
- }
-
- if (validFileName(filePath))
- return !isFileBlacklisted(filePath.fileName());
- else
- m_invalidFileNames.append(filePath);
-
- return false;
-}
-
-bool CmakeFileGenerator::generateEntryPointFiles(const FilePath &dir)
-{
- const QString qtcontrolsConf = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
- if (!qtcontrolsConf.isEmpty())
- m_resourceFileLocations.append(qtcontrolsConf);
-
- bool cppOk = generateMainCpp(dir);
- bool qmlOk = generateMainQml(dir);
-
- return cppOk && qmlOk;
-}
-
-const char MAIN_CPPFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
-const char MAIN_CPPFILE_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl";
-const char MAIN_CPPFILE_HEADER_PLUGIN_LINE[] = "Q_IMPORT_QML_PLUGIN(%1)\n";
-const char ENV_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectenvheader.tpl";
-const char ENV_HEADER_VARIABLE_LINE[] = " qputenv(\"%1\", \"%2\");\n";
-
-bool CmakeFileGenerator::generateMainCpp(const FilePath &dir)
-{
- FilePath srcDir = dir.pathAppended(DIRNAME_CPP);
-
- QString cppContent = GenerateCmake::readTemplate(MAIN_CPPFILE_TEMPLATE_PATH);
- FilePath cppFilePath = srcDir.pathAppended(FILENAME_MAINCPP);
- bool cppOk = m_fileQueue.queueFile(cppFilePath, cppContent);
-
- QString modulesAsPlugins;
- for (const QString &moduleName : m_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(FILENAME_MAINCPP_HEADER);
- bool pluginHeaderOk = m_fileQueue.queueFile(headerFilePath, headerContent);
-
- bool envHeaderOk = true;
- QString environment;
-
- if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem()) {
- for (EnvironmentItem &envItem : buildSystem->environment()) {
- QString key = envItem.name;
- QString value = envItem.value;
- if (isFileResource(value))
- value.prepend(":/");
- environment.append(QString(ENV_HEADER_VARIABLE_LINE).arg(key).arg(value));
- }
- QString envHeaderContent = GenerateCmake::readTemplate(ENV_HEADER_TEMPLATE_PATH)
- .arg(environment);
- FilePath envHeaderPath = srcDir.pathAppended(FILENAME_ENV_HEADER);
- envHeaderOk = m_fileQueue.queueFile(envHeaderPath, envHeaderContent);
- }
-
- return cppOk && pluginHeaderOk && envHeaderOk;
-}
-
-const char MAIN_QMLFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmainqml.tpl";
-
-bool CmakeFileGenerator::generateMainQml(const FilePath &dir)
-{
- QString content = GenerateCmake::readTemplate(MAIN_QMLFILE_TEMPLATE_PATH);
- FilePath filePath = dir.pathAppended(FILENAME_MAINQML);
- return m_fileQueue.queueFile(filePath, content);
-}
-
-bool CmakeFileGenerator::isFileResource(const QString &relativeFilePath)
-{
- if (m_resourceFileLocations.contains(relativeFilePath))
- return true;
-
- return false;
-}
-
-
-
-} //GenerateCmake
-} //QmlProjectManager
-
diff --git a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h
deleted file mode 100644
index db025daa27..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <projectexplorer/project.h>
-
-#include <utils/fileutils.h>
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-struct GeneratableFile {
- Utils::FilePath filePath;
- QString content;
- bool fileExists;
-};
-
-bool operator==(const GeneratableFile &left, const GeneratableFile &right);
-
-void generateMenuEntry(QObject *parent);
-void onGenerateCmakeLists();
-bool isErrorFatal(int error);
-int isProjectCorrectlyFormed(const Utils::FilePath &rootDir);
-void showProjectDirErrorDialog(int error);
-QString readTemplate(const QString &templatePath);
-const QString projectEnvironmentVariable(const QString &key);
-
-class FileQueue {
-public:
- bool queueFile(const Utils::FilePath &filePath, const QString &fileContent);
- const QVector<GeneratableFile> queuedFiles() const;
- bool writeQueuedFiles();
- void filterFiles(const Utils::FilePaths keepFiles);
-
-private:
- bool writeFile(const GeneratableFile &file);
-
-private:
- QVector<GeneratableFile> m_queuedFiles;
-};
-
-class CmakeFileGenerator {
-public:
- bool prepare(const Utils::FilePath &rootDir, bool check = true);
- const FileQueue fileQueue() const;
- void filterFileQueue(const Utils::FilePaths &keepFiles);
- bool execute();
- Utils::FilePaths invalidFileNames() const;
-
-private:
- void generateMainCmake(const Utils::FilePath &rootDir);
- void generateImportCmake(const Utils::FilePath &dir, const QString &modulePrefix = QString());
- void generateModuleCmake(const Utils::FilePath &dir, const QString &moduleUri = QString());
- bool generateEntryPointFiles(const Utils::FilePath &dir);
- bool generateMainCpp(const Utils::FilePath &dir);
- bool generateMainQml(const Utils::FilePath &dir);
- QStringList getDirectoryQmls(const Utils::FilePath &dir);
- QStringList getDirectoryResources(const Utils::FilePath &dir);
- QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
- QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
- QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
- void queueCmakeFile(const Utils::FilePath &filePath, const QString &content);
- bool isFileResource(const QString &relativeFilePath);
- bool isFileBlacklisted(const QString &fileName);
- bool isDirBlacklisted(const Utils::FilePath &dir);
- bool includeFile(const Utils::FilePath &filePath);
- bool validFileName(const Utils::FilePath &filePath);
-
-private:
- FileQueue m_fileQueue;
- QStringList m_resourceFileLocations;
- QStringList m_moduleNames;
- bool m_checkFileIsInProject;
-
- Utils::FilePaths m_invalidFileNames;
-};
-
-} //GenerateCmake
-
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h
deleted file mode 100644
index b983ce7fec..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#ifndef GENERATECMAKELISTSCONSTANTS_H
-#define GENERATECMAKELISTSCONSTANTS_H
-
-#pragma once
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-namespace Constants {
-
-const char DIRNAME_CONTENT[] = "content";
-const char DIRNAME_IMPORT[] = "imports";
-const char DIRNAME_ASSET[] = "assets";
-const char DIRNAME_ASSETIMPORT[] = "asset_imports";
-const char DIRNAME_CPP[] = "src";
-const char DIRNAME_DESIGNER[] = "designer";
-
-const char FILENAME_CMAKELISTS[] = "CMakeLists.txt";
-const char FILENAME_APPMAINQML[] = "App.qml";
-const char FILENAME_MAINQML[] = "main.qml";
-const char FILENAME_MAINCPP[] = "main.cpp";
-const char FILENAME_MAINCPP_HEADER[] = "import_qml_plugins.h";
-const char FILENAME_MODULES[] = "qmlmodules";
-const char FILENAME_QMLDIR[] = "qmldir";
-const char FILENAME_ENV_HEADER[] = "app_environment.h";
-
-const char FILENAME_SUFFIX_QMLPROJECT[] = "qmlproject";
-const char FILENAME_SUFFIX_QML[] = "qml";
-const char FILENAME_SUFFIX_USER[] = "user";
-
-const char FILENAME_FILTER_QMLPROJECT[] = "*.qmlproject";
-const char FILENAME_FILTER_QML[] = "*.qml";
-
-const char ENV_VARIABLE_CONTROLCONF[] = "QT_QUICK_CONTROLS_CONF";
-
-} //Constants
-} //GenerateCmake
-} //QmlProjectManager
-
-#endif // GENERATECMAKELISTSCONSTANTS_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectappmainqml.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectappmainqml.tpl
deleted file mode 100644
index 35f8218dc6..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectappmainqml.tpl
+++ /dev/null
@@ -1,14 +0,0 @@
-import QtQuick
-import QtQuick.Window
-
-Window {
- visible: true
- title: "%1"
- width: mainScreen.width
- height: mainScreen.height
-
- %1 {
- id: mainScreen
- }
-
-}
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectenvheader.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectenvheader.tpl
deleted file mode 100644
index bf60adb4ac..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectenvheader.tpl
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * This file is automatically generated by Qt Design Studio.
- * Do not change.
-*/
-
-#include <QGuiApplication>
-
-void set_qt_environment()
-{
-%1
-}
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincppheader.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincppheader.tpl
deleted file mode 100644
index 60cef09a82..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincppheader.tpl
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * This file is automatically generated by Qt Design Studio.
- * Do not change.
-*/
-
-#include <QtQml/qqmlextensionplugin.h>
-
-%1
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmainqml.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmainqml.tpl
deleted file mode 100644
index fa8f6d1cc1..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmainqml.tpl
+++ /dev/null
@@ -1,6 +0,0 @@
-import QtQuick
-import content
-
-App {
-}
-
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl
deleted file mode 100644
index 93573a1ed7..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl
+++ /dev/null
@@ -1,12 +0,0 @@
-### This file is automatically generated by Qt Design Studio.
-### Do not change
-
-%1
-
-qt_add_library(%2 STATIC)
-qt6_add_qml_module(%2
- URI "%3"
- VERSION 1.0
- RESOURCE_PREFIX "/qt/qml"
-%4
-)
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl
deleted file mode 100644
index 2b74c49af3..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl
+++ /dev/null
@@ -1,16 +0,0 @@
-### This file is automatically generated by Qt Design Studio.
-### Do not change
-
-qt6_add_qml_module(%1
- URI "Main"
- VERSION 1.0
- RESOURCE_PREFIX "/qt/qml"
- NO_PLUGIN
- QML_FILES main.qml
-)
-
-%2
-
-target_link_libraries(%1 PRIVATE
-%3
-)
diff --git a/src/plugins/qmlprojectmanager/cmakegen/templates/cmakelists_txt_shared.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakelists_txt_shared.tpl
new file mode 100644
index 0000000000..3db7152bff
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakelists_txt_shared.tpl
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE QtCreatorProject>
+<qtcreator>
+ <data>
+ <variable>ProjectExplorer.Project.PluginSettings</variable>
+ <valuemap type="QVariantMap">
+ <valuelist type="QVariantList" key="ProjectExplorer.Project.Environment">
+ <value type="QString">QTC_DEFAULT_BUILD_DIRECTORY_TEMPLATE=../%{Asciify:%{Project:Name}-%{BuildConfig:Name}}</value>
+ </valuelist>
+ </valuemap>
+</data>
+<data>
+ <variable>Version</variable>
+ <value type="int">22</value>
+</data>
+</qtcreator>
diff --git a/src/plugins/qmlprojectmanager/cmakegen/gencmakemodule.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakemodule_v1.tpl
index b81d253c90..25d894b347 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/gencmakemodule.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakemodule_v1.tpl
@@ -8,7 +8,6 @@ qt6_add_qml_module(%1
URI "%2"
VERSION 1.0
RESOURCE_PREFIX "/qt/qml"
-%4
-)
+%4)
%5
diff --git a/src/plugins/qmlprojectmanager/cmakegen/gencmakeroot.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v0.tpl
index a23a311c1a..a23a311c1a 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/gencmakeroot.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v0.tpl
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincmakelists.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v1.tpl
index 9ca0ace63b..a5d5e2bd02 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincmakelists.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v1.tpl
@@ -1,3 +1,4 @@
+
cmake_minimum_required(VERSION 3.21.1)
option(LINK_INSIGHT "Link Qt Insight Tracker library" ON)
@@ -5,6 +6,8 @@ option(BUILD_QDS_COMPONENTS "Build design studio components" ON)
project(%1 LANGUAGES CXX)
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml)
@@ -19,34 +22,25 @@ if (Qt6_VERSION VERSION_GREATER_EQUAL 6.3)
qt_standard_project_setup()
endif()
-qt_add_executable(%1 src/main.cpp)
-
-qt_add_resources(%1 "configuration"
+qt_add_executable(${CMAKE_PROJECT_NAME})
+qt_add_resources(${CMAKE_PROJECT_NAME} "configuration"
PREFIX "/"
-%2
-)
+ FILES
+%2)
-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(qds)
if (BUILD_QDS_COMPONENTS)
- include(${CMAKE_CURRENT_SOURCE_DIR}/qmlcomponents)
+ include(qmlcomponents OPTIONAL)
endif()
-include(${CMAKE_CURRENT_SOURCE_DIR}/qmlmodules)
-
if (LINK_INSIGHT)
- include(${CMAKE_CURRENT_SOURCE_DIR}/insight)
+ include(insight OPTIONAL)
endif ()
include(GNUInstallDirs)
-install(TARGETS %1
+install(TARGETS ${CMAKE_PROJECT_NAME}
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
-
diff --git a/src/plugins/qmlprojectmanager/cmakegen/templates/environment_h.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/environment_h.tpl
new file mode 100644
index 0000000000..d835c942f6
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/environment_h.tpl
@@ -0,0 +1,24 @@
+/*
+ * This file is automatically generated by Qt Design Studio.
+ * Do not change.
+*/
+
+#include <QGuiApplication>
+#include "qqmlextensionplugin.h"
+
+%1
+
+#ifdef BUILD_QDS_COMPONENTS
+
+Q_IMPORT_QML_PLUGIN(QtQuick_Studio_ComponentsPlugin)
+Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EffectsPlugin)
+Q_IMPORT_QML_PLUGIN(QtQuick_Studio_ApplicationPlugin)
+Q_IMPORT_QML_PLUGIN(FlowViewPlugin)
+Q_IMPORT_QML_PLUGIN(QtQuick_Studio_LogicHelperPlugin)
+Q_IMPORT_QML_PLUGIN(QtQuick_Studio_MultiTextPlugin)
+Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSimulatorPlugin)
+Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSystemPlugin)
+
+#endif
+
+%2
diff --git a/src/plugins/qmlprojectmanager/cmakegen/gencmakeheadercomponents.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/import_qml_components_h.tpl
index 167481d7c7..84d3c1c777 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/gencmakeheadercomponents.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/import_qml_components_h.tpl
@@ -17,3 +17,4 @@ Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSimulatorPlugin)
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSystemPlugin)
#endif
+
diff --git a/src/plugins/qmlprojectmanager/cmakegen/templates/insight.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/insight.tpl
new file mode 100644
index 0000000000..8245e31f0d
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/insight.tpl
@@ -0,0 +1,19 @@
+### This file is automatically generated by Qt Design Studio.
+### Do not change
+
+if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/qtinsight.conf)
+ if (QT_VERSION GREATER_EQUAL 6.5.0)
+ find_package(Qt6 REQUIRED COMPONENTS InsightTracker)
+
+ qt_add_resources(${CMAKE_PROJECT_NAME} "configuration"
+ PREFIX "/"
+ FILES
+ qtinsight.conf
+ )
+ target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
+ Qt6::InsightTracker
+ )
+ else()
+ message(WARNING "You need Qt 6.5.0 or newer to build the application.")
+ endif()
+endif()
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v0.tpl
index 0ff9201d91..0ff9201d91 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v0.tpl
diff --git a/src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v1.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v1.tpl
new file mode 100644
index 0000000000..4d2a526d76
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v1.tpl
@@ -0,0 +1,31 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+#include "autogen/environment.h"
+
+int main(int argc, char *argv[])
+{
+ set_qt_environment();
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ const QUrl url(mainQmlFile);
+ QObject::connect(
+ &engine, &QQmlApplicationEngine::objectCreated, &app,
+ [url](QObject *obj, const QUrl &objUrl) {
+ if (!obj && url == objUrl)
+ QCoreApplication::exit(-1);
+ }, Qt::QueuedConnection);
+
+ engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml");
+ engine.addImportPath(":/");
+ engine.load(url);
+
+ if (engine.rootObjects().isEmpty())
+ return -1;
+
+ return app.exec();
+}
diff --git a/src/plugins/qmlprojectmanager/cmakegen/templates/qmlcomponents.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/qmlcomponents.tpl
new file mode 100644
index 0000000000..5640b85844
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/qmlcomponents.tpl
@@ -0,0 +1,36 @@
+### This file is automatically generated by Qt Design Studio.
+### Do not change
+
+message("Building designer components.")
+
+set(QT_QDS_COMPONENTS_NOWARN on)
+set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml")
+
+include(FetchContent)
+FetchContent_Declare(
+ ds
+ GIT_TAG qds-4.5
+ GIT_REPOSITORY https://code.qt.io/qt-labs/qtquickdesigner-components.git
+)
+
+FetchContent_GetProperties(ds)
+FetchContent_Populate(ds)
+
+target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
+ QuickStudioComponentsplugin
+ QuickStudioDesignEffectsplugin
+ QuickStudioEffectsplugin
+ QuickStudioApplicationplugin
+ FlowViewplugin
+ QuickStudioLogicHelperplugin
+ QuickStudioMultiTextplugin
+ QuickStudioEventSimulatorplugin
+ QuickStudioEventSystemplugin
+ QuickStudioUtilsplugin
+)
+
+add_subdirectory(${ds_SOURCE_DIR} ${ds_BINARY_DIR})
+
+target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
+ BULD_QDS_COMPONENTS=true
+)
diff --git a/src/plugins/qmlprojectmanager/cmakegen/templates/qtquickcontrols2_conf.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/qtquickcontrols2_conf.tpl
new file mode 100644
index 0000000000..eb1f825a38
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/qtquickcontrols2_conf.tpl
@@ -0,0 +1,7 @@
+; This file can be edited to change the style of the application
+; Read "Qt Quick Controls 2 Configuration File" for details:
+; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html
+
+[Controls]
+Style=Basic
+
diff --git a/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp b/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp
index 7a35d9f15e..983b712633 100644
--- a/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp
+++ b/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp
@@ -56,7 +56,7 @@ QmlMainFileAspect::~QmlMainFileAspect()
delete m_fileListCombo;
}
-void QmlMainFileAspect::addToLayout(Layouting::LayoutItem &parent)
+void QmlMainFileAspect::addToLayout(Layouting::Layout &parent)
{
QTC_ASSERT(!m_fileListCombo, delete m_fileListCombo);
m_fileListCombo = new QComboBox;
diff --git a/src/plugins/qmlprojectmanager/qmlmainfileaspect.h b/src/plugins/qmlprojectmanager/qmlmainfileaspect.h
index 4a64055b6c..fd875dde79 100644
--- a/src/plugins/qmlprojectmanager/qmlmainfileaspect.h
+++ b/src/plugins/qmlprojectmanager/qmlmainfileaspect.h
@@ -42,7 +42,7 @@ public:
Utils::FilePath currentFile;
};
- void addToLayout(Layouting::LayoutItem &parent) final;
+ void addToLayout(Layouting::Layout &parent) final;
void toMap(Utils::Store &map) const final;
void fromMap(const Utils::Store &map) final;
diff --git a/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp b/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp
index ae16f09fc2..e6028e1d7d 100644
--- a/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp
+++ b/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp
@@ -21,7 +21,7 @@ namespace QmlProjectManager {
static bool isMultilanguagePresent()
{
- const QVector<ExtensionSystem::PluginSpec *> &specs = ExtensionSystem::PluginManager::plugins();
+ const ExtensionSystem::PluginSpecs &specs = ExtensionSystem::PluginManager::plugins();
return std::find_if(specs.cbegin(), specs.cend(),
[](ExtensionSystem::PluginSpec *spec) {
return spec->name() == "MultiLanguage";
@@ -41,7 +41,7 @@ static FilePath getMultilanguageDatabaseFilePath(ProjectExplorer::Target *target
static QObject *getPreviewPlugin()
{
- const QVector<ExtensionSystem::PluginSpec *> &specs = ExtensionSystem::PluginManager::plugins();
+ const ExtensionSystem::PluginSpecs &specs = ExtensionSystem::PluginManager::plugins();
const auto pluginIt = std::find_if(specs.cbegin(), specs.cend(),
[](const ExtensionSystem::PluginSpec *p) {
return p->name() == "QmlPreview";
diff --git a/src/plugins/qmlprojectmanager/qmlprojectconstants.h b/src/plugins/qmlprojectmanager/qmlprojectconstants.h
index a937979954..ad77948105 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectconstants.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectconstants.h
@@ -13,7 +13,6 @@ const char customQtForMCUs[] = "CustomQtForMCUs";
const char customQt6Project[] = "CustomQt6Project";
const char mainFilePath[] = "MainFilePath";
-const char customImportPaths[] = "CustomImportPaths";
const char canonicalProjectDir[] ="CanonicalProjectDir";
const char enviromentLaunchedQDS[] = "QTC_LAUNCHED_QDS";
diff --git a/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp b/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp
index 32506183fa..0270a290fd 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qmlprojectgenerator.h"
-#include "../cmakegen/generatecmakelists.h"
+#include "../cmakegen/cmakewriter.h"
#include "../qmlprojectmanagertr.h"
#include <coreplugin/documentmanager.h>
@@ -61,7 +61,7 @@ bool QmlProjectFileGenerator::execute()
importDirs.removeAll("content");
const QString importPaths = createDirArrayEntry("importPaths", importDirs);
- const QString fileContent = GenerateCmake::readTemplate(QMLPROJECT_FILE_TEMPLATE_PATH)
+ const QString fileContent = GenerateCmake::CMakeWriter::readTemplate(QMLPROJECT_FILE_TEMPLATE_PATH)
.arg(contentEntry, imageEntry, jsEntry, assetEntry, importPaths);
QFile file(m_targetFile.toString());
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs b/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
index 76fcd70157..0fa49b5102 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
@@ -47,14 +47,10 @@ QtcPlugin {
name: "CMake Generator"
prefix: "cmakegen/"
files: [
- "generatecmakelists.cpp", "generatecmakelists.h",
- "generatecmakelistsconstants.h",
- "checkablefiletreeitem.cpp", "checkablefiletreeitem.h",
"cmakegenerator.cpp", "cmakegenerator.h",
- "cmakegeneratordialogtreemodel.cpp", "cmakegeneratordialogtreemodel.h",
- "cmakegeneratordialog.cpp", "cmakegeneratordialog.h",
- "cmakeprojectconverter.cpp", "cmakeprojectconverter.h",
- "cmakeprojectconverterdialog.cpp", "cmakeprojectconverterdialog.h",
+ "cmakewriter.cpp", "cmakewriter.h",
+ "cmakewriterv0.cpp", "cmakewriterv0.h",
+ "cmakewriterv1.cpp", "cmakewriterv1.h"
]
}
diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
index 62abce5fe9..1bc61c3b82 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
@@ -9,8 +9,7 @@
#include "qmlprojectmanagertr.h"
#include "qmlprojectrunconfiguration.h"
#include "projectfilecontenttools.h"
-#include "cmakegen/cmakeprojectconverter.h"
-#include "cmakegen/generatecmakelists.h"
+#include "cmakegen/cmakegenerator.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
@@ -101,11 +100,6 @@ static void clearAlwaysOpenWithMode()
ICore::settings()->remove(QmlProjectManager::Constants::ALWAYS_OPEN_UI_MODE);
}
-class QmlProjectPluginPrivate
-{
-public:
-};
-
void openQDS(const FilePath &fileName)
{
const FilePath qdsPath = qdsInstallationEntry();
@@ -230,6 +224,26 @@ static QmlBuildSystem *qmlBuildSystemforFileNode(const FileNode *fileNode)
return nullptr;
}
+class ExternalDesignStudioFactory : public Core::IEditorFactory
+{
+public:
+ ExternalDesignStudioFactory()
+ {
+ setId("Qt.QtDesignStudio");
+ setDisplayName(Tr::tr("Qt Design Studio"));
+ setMimeTypes({Utils::Constants::QMLUI_MIMETYPE});
+ setEditorStarter([](const FilePath &filePath, [[maybe_unused]] QString *errorMessage) {
+ openInQDSWithProject(filePath);
+ return true;
+ });
+ }
+};
+
+void setupExternalDesignStudio()
+{
+ static ExternalDesignStudioFactory theExternalDesignStudioFactory;
+}
+
class QmlProjectPlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT
@@ -275,6 +289,7 @@ private:
void QmlProjectPlugin::initialize()
{
setupQmlProjectRunConfiguration();
+ setupExternalDesignStudio();
if (!qmlDesignerEnabled()) {
m_landingPage = new QdsLandingPage();
@@ -386,11 +401,9 @@ void QmlProjectPlugin::initialize()
mainUifileAction->setEnabled(buildSystem->mainUiFilePath()
!= fileNode->filePath());
});
- }
- GenerateCmake::generateMenuEntry(this);
- if (ICore::isQtDesignStudio())
- GenerateCmake::CmakeProjectConverter::generateMenuEntry(this);
+ GenerateCmake::CMakeGenerator::createMenuAction(this);
+ }
}
void QmlProjectPlugin::displayQmlLandingPage()
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
index 5742b945a8..503738eba5 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
@@ -97,12 +97,12 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id)
// arguments from .qmlproject file
const QmlBuildSystem *bs = qobject_cast<QmlBuildSystem *>(target->buildSystem());
- for (const QString &importPath : bs->customImportPaths()) {
+ for (const QString &importPath : bs->absoluteImportPaths()) {
cmd.addArg("-I");
- cmd.addArg(bs->targetDirectory().pathAppended(importPath).path());
+ cmd.addArg(importPath);
}
- for (const QString &fileSelector : bs->customFileSelectors()) {
+ for (const QString &fileSelector : bs->fileSelectors()) {
cmd.addArg("-S");
cmd.addArg(fileSelector);
}