forked from qt-creator/qt-creator
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:
@@ -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
|
||||||
|
@@ -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();
|
||||||
|
@@ -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;
|
||||||
|
@@ -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();
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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());
|
||||||
|
@@ -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;
|
||||||
|
@@ -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.
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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()) {
|
||||||
|
@@ -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);
|
||||||
|
@@ -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) ||
|
||||||
|
Reference in New Issue
Block a user