Introduce mockImports and allow resources in the root folder

mockImports is a secial import path which is only considered
by Design Studio and ignored by the cmake exporter.
This prevents name clashes between qml mock modules and their
c++/python counter parts.

Fixes: QDS-13466
Fixes: QDS-13469
Change-Id: I64026ea9d8823f3d5e818a352ccb565fa29c1933
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Knud Dollereder
2024-09-11 13:13:21 +02:00
parent 6ec3c8f9c9
commit 9f6221d3cd
12 changed files with 131 additions and 25 deletions

View File

@@ -147,6 +147,7 @@ QString jsonToQmlProject(const QJsonObject &rootObject)
appendBool("enablePythonGeneration", deploymentConfig["enablePythonGeneration"].toBool()); appendBool("enablePythonGeneration", deploymentConfig["enablePythonGeneration"].toBool());
appendBool("widgetApp", runConfig["widgetApp"].toBool()); appendBool("widgetApp", runConfig["widgetApp"].toBool());
appendStringArray("importPaths", rootObject["importPaths"].toVariant().toStringList()); appendStringArray("importPaths", rootObject["importPaths"].toVariant().toStringList());
appendStringArray("mockImports", rootObject["mockImports"].toVariant().toStringList());
appendBreak(); appendBreak();
appendString("qdsVersion", versionConfig["designStudio"].toString()); appendString("qdsVersion", versionConfig["designStudio"].toString());
appendString("quickVersion", versionConfig["qtQuick"].toString()); appendString("quickVersion", versionConfig["qtQuick"].toString());
@@ -411,6 +412,8 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
} else if (propName.contains("importpaths", Qt::CaseInsensitive)) { } else if (propName.contains("importpaths", Qt::CaseInsensitive)) {
objKey = "importPaths"; objKey = "importPaths";
importPaths = value.toVariant().toStringList(); importPaths = value.toVariant().toStringList();
} else if (propName.contains("mockImports", Qt::CaseInsensitive)) {
objKey = "mockImports";
} else { } else {
currentObj = &otherProperties; currentObj = &otherProperties;
objKey = propName; // With prefix objKey = propName; // With prefix

View File

@@ -212,6 +212,16 @@ void QmlProjectItem::setImportPaths(const QStringList &importPaths)
insertAndUpdateProjectFile("importPaths", QJsonArray::fromStringList(importPaths)); insertAndUpdateProjectFile("importPaths", QJsonArray::fromStringList(importPaths));
} }
QStringList QmlProjectItem::mockImports() const
{
return m_project["mockImports"].toVariant().toStringList();
}
void QmlProjectItem::setMockImports(const QStringList &paths)
{
insertAndUpdateProjectFile("mockImports", QJsonArray::fromStringList(paths));
}
void QmlProjectItem::addImportPath(const QString &importPath) void QmlProjectItem::addImportPath(const QString &importPath)
{ {
QJsonArray importPaths = m_project["importPaths"].toArray(); QJsonArray importPaths = m_project["importPaths"].toArray();

View File

@@ -46,6 +46,9 @@ public:
void setImportPaths(const QStringList &paths); void setImportPaths(const QStringList &paths);
void addImportPath(const QString &importPath); void addImportPath(const QString &importPath);
QStringList mockImports() const;
void setMockImports(const QStringList &paths);
QStringList qmlProjectModules() const; QStringList qmlProjectModules() const;
QStringList fileSelectors() const; QStringList fileSelectors() const;

View File

@@ -716,14 +716,24 @@ QStringList QmlBuildSystem::shaderToolFiles() const
return m_projectItem->shaderToolFiles(); return m_projectItem->shaderToolFiles();
} }
QStringList QmlBuildSystem::allImports() const
{
return m_projectItem->importPaths() + m_projectItem->mockImports();
}
QStringList QmlBuildSystem::importPaths() const QStringList QmlBuildSystem::importPaths() const
{ {
return m_projectItem->importPaths(); return m_projectItem->importPaths();
} }
QStringList QmlBuildSystem::mockImports() const
{
return m_projectItem->mockImports();
}
QStringList QmlBuildSystem::absoluteImportPaths() const QStringList QmlBuildSystem::absoluteImportPaths() const
{ {
return Utils::transform<QStringList>(m_projectItem->importPaths(), [&](const QString &importPath) { return Utils::transform<QStringList>(allImports(), [&](const QString &importPath) {
Utils::FilePath filePath = Utils::FilePath::fromString(importPath); Utils::FilePath filePath = Utils::FilePath::fromString(importPath);
if (!filePath.isAbsolutePath()) if (!filePath.isAbsolutePath())
return (projectDirectory() / importPath).toString(); return (projectDirectory() / importPath).toString();

View File

@@ -73,7 +73,9 @@ public:
Utils::EnvironmentItems environment() const; Utils::EnvironmentItems environment() const;
QStringList allImports() const;
QStringList importPaths() const; QStringList importPaths() const;
QStringList mockImports() const;
QStringList absoluteImportPaths() const; QStringList absoluteImportPaths() const;
QStringList fileSelectors() const; QStringList fileSelectors() const;

View File

@@ -172,7 +172,7 @@ bool CMakeGenerator::checkUri(const QString& uri, const Utils::FilePath &path) c
Utils::FilePath relative = path.relativeChildPath(m_root->dir); Utils::FilePath relative = path.relativeChildPath(m_root->dir);
QList<QStringView> pathComponents = relative.pathView().split('/', Qt::SkipEmptyParts); QList<QStringView> pathComponents = relative.pathView().split('/', Qt::SkipEmptyParts);
for (const auto& import : buildSystem()->importPaths()) { for (const auto& import : buildSystem()->allImports()) {
Utils::FilePath importPath = Utils::FilePath::fromUserInput(import); Utils::FilePath importPath = Utils::FilePath::fromUserInput(import);
for (const auto& component : importPath.pathView().split('/', Qt::SkipEmptyParts)) { for (const auto& component : importPath.pathView().split('/', Qt::SkipEmptyParts)) {
if (component == pathComponents.first()) if (component == pathComponents.first())
@@ -219,8 +219,24 @@ void CMakeGenerator::createSourceFiles() const
m_writer->writeSourceFiles(sourceNode, m_root); m_writer->writeSourceFiles(sourceNode, m_root);
} }
bool CMakeGenerator::isMockModule(const NodePtr &node) const
{
QTC_ASSERT(buildSystem(), return false);
Utils::FilePath dir = node->dir.parentDir();
QString mockDir = dir.relativeChildPath(m_root->dir).path();
for (const QString &import : buildSystem()->mockImports()) {
if (import == mockDir)
return true;
}
return false;
}
void CMakeGenerator::readQmlDir(const Utils::FilePath &filePath, NodePtr &node) const void CMakeGenerator::readQmlDir(const Utils::FilePath &filePath, NodePtr &node) const
{ {
if (isMockModule(node))
node->type = Node::Type::MockModule;
else
node->type = Node::Type::Module; node->type = Node::Type::Module;
QFile f(filePath.toString()); QFile f(filePath.toString());

View File

@@ -42,6 +42,7 @@ public:
private: private:
bool ignore(const Utils::FilePath &path) const; bool ignore(const Utils::FilePath &path) const;
bool checkUri(const QString& uri, const Utils::FilePath &path) const; bool checkUri(const QString& uri, const Utils::FilePath &path) const;
bool isMockModule(const NodePtr &node) const;
void createCMakeFiles(const NodePtr &node) const; void createCMakeFiles(const NodePtr &node) const;
void createSourceFiles() const; void createSourceFiles() const;

View File

@@ -17,6 +17,13 @@ namespace QmlProjectManager {
namespace QmlProjectExporter { namespace QmlProjectExporter {
const char TEMPLATE_RESOURCES[] = R"(
qt6_add_resources(%1 %2
PREFIX "%3"
VERSION 1.0
FILES %4
))";
const char TEMPLATE_BIG_RESOURCES[] = R"( const char TEMPLATE_BIG_RESOURCES[] = R"(
qt6_add_resources(%1 %2 qt6_add_resources(%1 %2
BIG_RESOURCES BIG_RESOURCES
@@ -235,29 +242,57 @@ QString CMakeWriter::makeSetEnvironmentFn() const
return out; return out;
} }
std::tuple<QString, QString> CMakeWriter::makeResourcesBlocks(const NodePtr &node) const std::tuple<QString, QString> CMakeWriter::makeResourcesBlocksRoot(const NodePtr &node) const
{ {
QString resourcesOut; QString resourcesOut;
QString bigResourcesOut; QString bigResourcesOut;
QString resourceFiles; QStringList res;
std::vector<QString> bigResources; QStringList bigRes;
for (const Utils::FilePath &path : assets(node)) { collectResources(node, res, bigRes);
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()) if (!res.isEmpty()) {
resourcesOut.append(QString("\tRESOURCES\n%1").arg(resourceFiles));
QString templatePostfix;
if (!bigResources.empty()) {
QString resourceContent; QString resourceContent;
for (const QString &res : bigResources) for (const QString &r : res)
resourceContent.append(QString("\n %1").arg(res)); resourceContent.append(QString("\n\t\t%1").arg(r));
const QString resourceName = node->name + "Resource";
resourcesOut = QString::fromUtf8(TEMPLATE_RESOURCES, -1)
.arg("${CMAKE_PROJECT_NAME}", resourceName, "/qt/qml", resourceContent);
}
if (!bigRes.isEmpty()) {
QString bigResourceContent;
for (const QString &r : bigRes)
bigResourceContent.append(QString("\n\t\t%1").arg(r));
const QString resourceName = node->name + "BigResource";
bigResourcesOut = QString::fromUtf8(TEMPLATE_BIG_RESOURCES, -1)
.arg("${CMAKE_PROJECT_NAME}", resourceName, "/qt/qml", bigResourceContent);
}
return {resourcesOut, bigResourcesOut};
}
std::tuple<QString, QString> CMakeWriter::makeResourcesBlocksModule(const NodePtr &node) const
{
QString resourcesOut;
QString bigResourcesOut;
QStringList res;
QStringList bigRes;
collectResources(node, res, bigRes);
if (!res.isEmpty()) {
resourcesOut = "\tRESOURCES\n";
for (const QString &r : res)
resourcesOut.append(QString("\t\t%1\n").arg(r));
}
if (!bigRes.isEmpty()) {
QString resourceContent;
for (const QString &res : bigRes)
resourceContent.append(QString("\n\t\t%1").arg(res));
const QString prefixPath = QString(node->uri).replace('.', '/'); const QString prefixPath = QString(node->uri).replace('.', '/');
const QString prefix = "/qt/qml/" + prefixPath; const QString prefix = "/qt/qml/" + prefixPath;
@@ -278,6 +313,17 @@ void CMakeWriter::collectPlugins(const NodePtr &node, std::vector<QString> &out)
collectPlugins(child, out); collectPlugins(child, out);
} }
void CMakeWriter::collectResources(const NodePtr &node, QStringList &res, QStringList &bigRes) const
{
for (const Utils::FilePath &path : assets(node)) {
if (path.fileSize() > 5000000) {
bigRes.push_back(makeRelative(node, path));
} else {
res.append(makeRelative(node, path));
}
}
}
} // End namespace QmlProjectExporter. } // End namespace QmlProjectExporter.
} // End namespace QmlProjectManager. } // End namespace QmlProjectManager.

View File

@@ -20,6 +20,7 @@ struct Node
Module, Module,
Library, Library,
Folder, Folder,
MockModule
}; };
std::shared_ptr<Node> parent = nullptr; std::shared_ptr<Node> parent = nullptr;
@@ -63,6 +64,8 @@ public:
static void writeFile(const Utils::FilePath &path, const QString &content); static void writeFile(const Utils::FilePath &path, const QString &content);
CMakeWriter(CMakeGenerator *parent); CMakeWriter(CMakeGenerator *parent);
virtual ~CMakeWriter() = default;
const CMakeGenerator *parent() const; const CMakeGenerator *parent() const;
virtual bool isPlugin(const NodePtr &node) const; virtual bool isPlugin(const NodePtr &node) const;
@@ -89,11 +92,12 @@ protected:
QString makeSingletonBlock(const NodePtr &node) const; QString makeSingletonBlock(const NodePtr &node) const;
QString makeSubdirectoriesBlock(const NodePtr &node) const; QString makeSubdirectoriesBlock(const NodePtr &node) const;
QString makeSetEnvironmentFn() const; QString makeSetEnvironmentFn() const;
std::tuple<QString, QString> makeResourcesBlocks(const NodePtr &node) const; std::tuple<QString, QString> makeResourcesBlocksRoot(const NodePtr &node) const;
std::tuple<QString, QString> makeResourcesBlocksModule(const NodePtr &node) const;
private: private:
void collectPlugins(const NodePtr &node, std::vector<QString> &out) const; void collectPlugins(const NodePtr &node, std::vector<QString> &out) const;
void collectResources(const NodePtr &node, QStringList &res, QStringList &bigRes) const;
const CMakeGenerator *m_parent = nullptr; const CMakeGenerator *m_parent = nullptr;
}; };

View File

@@ -106,7 +106,7 @@ void CMakeWriterV0::writeModuleCMakeFile(const NodePtr &node, const NodePtr &roo
QString qmlModulesContent; QString qmlModulesContent;
qmlModulesContent.append(makeQmlFilesBlock(node)); qmlModulesContent.append(makeQmlFilesBlock(node));
auto [resources, bigResources] = makeResourcesBlocks(node); auto [resources, bigResources] = makeResourcesBlocksModule(node);
qmlModulesContent.append(resources); qmlModulesContent.append(resources);
if (!qmlModulesContent.isEmpty()) { if (!qmlModulesContent.isEmpty()) {

View File

@@ -88,7 +88,17 @@ void CMakeWriterV1::writeModuleCMakeFile(const NodePtr &node, const NodePtr &) c
const Utils::FilePath userFile = node->dir.pathAppended("qds.cmake"); const Utils::FilePath userFile = node->dir.pathAppended("qds.cmake");
QString userFileContent(DO_NOT_EDIT_FILE); QString userFileContent(DO_NOT_EDIT_FILE);
userFileContent.append(makeSubdirectoriesBlock(node)); userFileContent.append(makeSubdirectoriesBlock(node));
auto [resources, bigResources] = makeResourcesBlocksRoot(node);
if (!resources.isEmpty()) {
userFileContent.append(resources);
userFileContent.append("\n"); userFileContent.append("\n");
}
if (!bigResources.isEmpty()) {
userFileContent.append(bigResources);
userFileContent.append("\n");
}
QString pluginNames; QString pluginNames;
std::vector<QString> plugs = plugins(node); std::vector<QString> plugs = plugins(node);
@@ -102,6 +112,7 @@ void CMakeWriterV1::writeModuleCMakeFile(const NodePtr &node, const NodePtr &) c
"target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE\n" "target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE\n"
"%1)"); "%1)");
userFileContent.append("\n");
userFileContent.append(linkLibrariesTemplate.arg(pluginNames)); userFileContent.append(linkLibrariesTemplate.arg(pluginNames));
writeFile(userFile, userFileContent); writeFile(userFile, userFileContent);
return; return;
@@ -119,7 +130,7 @@ void CMakeWriterV1::writeModuleCMakeFile(const NodePtr &node, const NodePtr &) c
prefix.append(makeSubdirectoriesBlock(node)); prefix.append(makeSubdirectoriesBlock(node));
prefix.append(makeSingletonBlock(node)); prefix.append(makeSingletonBlock(node));
auto [resources, bigResources] = makeResourcesBlocks(node); auto [resources, bigResources] = makeResourcesBlocksModule(node);
QString moduleContent; QString moduleContent;
moduleContent.append(makeQmlFilesBlock(node)); moduleContent.append(makeQmlFilesBlock(node));
moduleContent.append(resources); moduleContent.append(resources);

View File

@@ -33,7 +33,7 @@ bool isAssetFile(const Utils::FilePath &path)
{ {
static const QStringList suffixes = { static const QStringList suffixes = {
"js", "ts", "json", "hints", "mesh", "qad", "qsb", "frag", "js", "ts", "json", "hints", "mesh", "qad", "qsb", "frag",
"frag.qsb", "vert", "vert.qsb", "mng" "frag.qsb", "vert", "vert.qsb", "mng", "wav"
}; };
return return
suffixes.contains(path.suffix(), Qt::CaseInsensitive) || suffixes.contains(path.suffix(), Qt::CaseInsensitive) ||