forked from qt-creator/qt-creator
QmlProjectExporter: Copy the qtquickdesigner-components into the project
This way git is not a requirement anymore to build a project which was an issue for some users on some platforms. Fixes: QDS-14168 Change-Id: Iabfa57d0a38ccd16ae044bb4556df978a71198f6 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -290,7 +290,7 @@ bool FileFilterItem::fileMatches(const QString &fileName) const
|
|||||||
|
|
||||||
bool FileFilterItem::ignoreDirectory(const QFileInfo &file) const
|
bool FileFilterItem::ignoreDirectory(const QFileInfo &file) const
|
||||||
{
|
{
|
||||||
static const QStringList blackList = { "CMakeCache.txt", "build.ninja" };
|
static const QStringList blackList = {"CMakeCache.txt", "build.ninja", "ignore-in-qds"};
|
||||||
return blackList.contains(file.fileName());
|
return blackList.contains(file.fileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -169,7 +169,11 @@ bool CMakeGenerator::ignore(const Utils::FilePath &path) const
|
|||||||
if (!m_root->dir.exists())
|
if (!m_root->dir.exists())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
static const QStringList fileNames = { "CMakeCache.txt", "build.ninja" };
|
static const QStringList dirNames = { DEPENDENCIES_DIR };
|
||||||
|
if (dirNames.contains(path.fileName()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
static const QStringList fileNames = {COMPONENTS_IGNORE_FILE, "CMakeCache.txt", "build.ninja"};
|
||||||
|
|
||||||
Utils::FilePath dir = path;
|
Utils::FilePath dir = path;
|
||||||
while (dir.isChildOf(m_root->dir)) {
|
while (dir.isChildOf(m_root->dir)) {
|
||||||
|
@@ -40,9 +40,13 @@ CMakeWriter::Ptr CMakeWriter::create(CMakeGenerator *parent)
|
|||||||
const QmlBuildSystem *buildSystem = parent->buildSystem();
|
const QmlBuildSystem *buildSystem = parent->buildSystem();
|
||||||
QTC_ASSERT(buildSystem, return {});
|
QTC_ASSERT(buildSystem, return {});
|
||||||
|
|
||||||
const QString versionString = buildSystem->versionDesignStudio();
|
auto [major, minor, patch] = versionFromString(buildSystem->versionDesignStudio());
|
||||||
bool ok = false;
|
|
||||||
if (float version = versionString.toFloat(&ok); ok && version > 4.4)
|
bool useV1 = false;
|
||||||
|
if (major.has_value())
|
||||||
|
useV1 = minor.has_value() ? *major >= 4 && *minor >= 5 : *major >= 5;
|
||||||
|
|
||||||
|
if (useV1)
|
||||||
return std::make_unique<CMakeWriterV1>(parent);
|
return std::make_unique<CMakeWriterV1>(parent);
|
||||||
|
|
||||||
CMakeGenerator::logIssue(
|
CMakeGenerator::logIssue(
|
||||||
@@ -58,6 +62,37 @@ CMakeWriter::Ptr CMakeWriter::create(CMakeGenerator *parent)
|
|||||||
return std::make_unique<CMakeWriterV0>(parent);
|
return std::make_unique<CMakeWriterV0>(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CMakeWriter::Version CMakeWriter::versionFromString(const QString &versionString)
|
||||||
|
{
|
||||||
|
const QStringList versions = versionString.split('.', Qt::SkipEmptyParts);
|
||||||
|
auto checkComponent = [&versions](qsizetype idx) -> std::optional<int> {
|
||||||
|
if (versions.size() >= idx+1) {
|
||||||
|
bool ok = false;
|
||||||
|
if (int version = versions[idx].toInt(&ok); ok)
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {checkComponent(0), checkComponent(1), checkComponent(2)};
|
||||||
|
}
|
||||||
|
|
||||||
|
CMakeWriter::Version CMakeWriter::versionFromIgnoreFile(const Utils::FilePath &path)
|
||||||
|
{
|
||||||
|
QString versionString;
|
||||||
|
QFile ignoreFile(path.toFSPathString());
|
||||||
|
if (ignoreFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
QTextStream stream(&ignoreFile);
|
||||||
|
QString firstLine = stream.readLine();
|
||||||
|
ignoreFile.close();
|
||||||
|
|
||||||
|
QStringList parts = firstLine.split(' ');
|
||||||
|
QTC_ASSERT(parts.size()==3, return {});
|
||||||
|
return versionFromString(parts[2]);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
QString CMakeWriter::readTemplate(const QString &templatePath)
|
QString CMakeWriter::readTemplate(const QString &templatePath)
|
||||||
{
|
{
|
||||||
QFile templatefile(templatePath);
|
QFile templatefile(templatePath);
|
||||||
@@ -174,18 +209,11 @@ QString CMakeWriter::makeFindPackageBlock(const NodePtr &node, const QmlBuildSys
|
|||||||
tail.append(" Quick3D");
|
tail.append(" Quick3D");
|
||||||
tail.append(")\n");
|
tail.append(")\n");
|
||||||
|
|
||||||
const QStringList versions = buildSystem->versionQtQuick().split('.', Qt::SkipEmptyParts);
|
auto [major, minor, patch] = versionFromString(buildSystem->versionQtQuick());
|
||||||
if (versions.size() < 2)
|
if (!major.has_value() || !minor.has_value())
|
||||||
return head + tail;
|
return head + tail;
|
||||||
|
|
||||||
bool majorOk = false;
|
const QString from = QString::number(*major) + "." + QString::number(*minor);
|
||||||
bool minorOk = false;
|
|
||||||
int major = versions[0].toInt(&majorOk);
|
|
||||||
int minor = versions[1].toInt(&minorOk);
|
|
||||||
if (!majorOk || !minorOk)
|
|
||||||
return head + tail;
|
|
||||||
|
|
||||||
const QString from = versions[0] + "." + versions[1];
|
|
||||||
QString out = head + " " + from + tail;
|
QString out = head + " " + from + tail;
|
||||||
|
|
||||||
if (major >= 6 && minor >= 3)
|
if (major >= 6 && minor >= 3)
|
||||||
@@ -224,7 +252,7 @@ QString CMakeWriter::makeSingletonBlock(const NodePtr &node) const
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CMakeWriter::makeSubdirectoriesBlock(const NodePtr &node) const
|
QString CMakeWriter::makeSubdirectoriesBlock(const NodePtr &node, const QStringList &others) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(parent(), return {});
|
QTC_ASSERT(parent(), return {});
|
||||||
|
|
||||||
@@ -234,6 +262,10 @@ QString CMakeWriter::makeSubdirectoriesBlock(const NodePtr &node) const
|
|||||||
|| n->type == Node::Type::App || parent()->hasChildModule(n))
|
|| n->type == Node::Type::App || parent()->hasChildModule(n))
|
||||||
str.append(QString("add_subdirectory(%1)\n").arg(n->dir.fileName()));
|
str.append(QString("add_subdirectory(%1)\n").arg(n->dir.fileName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const QString &other : others)
|
||||||
|
str.append(QString("add_subdirectory(%1)\n").arg(other));
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,6 +42,10 @@ using FileGetter = std::function<std::vector<Utils::FilePath>(const NodePtr &)>;
|
|||||||
|
|
||||||
class CMakeGenerator;
|
class CMakeGenerator;
|
||||||
|
|
||||||
|
const char DEPENDENCIES_DIR[] = "Dependencies";
|
||||||
|
const char COMPONENTS_DIR[] = "Components";
|
||||||
|
const char COMPONENTS_IGNORE_FILE[] = "ignore-in-qds";
|
||||||
|
|
||||||
const char ENV_VARIABLE_CONTROLCONF[] =
|
const char ENV_VARIABLE_CONTROLCONF[] =
|
||||||
"QT_QUICK_CONTROLS_CONF";
|
"QT_QUICK_CONTROLS_CONF";
|
||||||
|
|
||||||
@@ -58,8 +62,11 @@ class CMakeWriter
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<CMakeWriter>;
|
using Ptr = std::shared_ptr<CMakeWriter>;
|
||||||
|
using Version = std::tuple<std::optional<int>, std::optional<int>, std::optional<int>>;
|
||||||
|
|
||||||
static Ptr create(CMakeGenerator *parent);
|
static Ptr create(CMakeGenerator *parent);
|
||||||
|
static Version versionFromString(const QString &versionString);
|
||||||
|
static Version versionFromIgnoreFile(const Utils::FilePath &path);
|
||||||
static QString readTemplate(const QString &templatePath);
|
static QString readTemplate(const QString &templatePath);
|
||||||
static void writeFile(const Utils::FilePath &path, const QString &content);
|
static void writeFile(const Utils::FilePath &path, const QString &content);
|
||||||
|
|
||||||
@@ -90,7 +97,7 @@ protected:
|
|||||||
QString makeRelative(const NodePtr &node, const Utils::FilePath &path) const;
|
QString makeRelative(const NodePtr &node, const Utils::FilePath &path) const;
|
||||||
QString makeQmlFilesBlock(const NodePtr &node) const;
|
QString makeQmlFilesBlock(const NodePtr &node) const;
|
||||||
QString makeSingletonBlock(const NodePtr &node) const;
|
QString makeSingletonBlock(const NodePtr &node) const;
|
||||||
QString makeSubdirectoriesBlock(const NodePtr &node) const;
|
QString makeSubdirectoriesBlock(const NodePtr &node, const QStringList &others = {}) const;
|
||||||
QString makeSetEnvironmentFn() const;
|
QString makeSetEnvironmentFn() const;
|
||||||
std::tuple<QString, QString> makeResourcesBlocksRoot(const NodePtr &node) const;
|
std::tuple<QString, QString> makeResourcesBlocksRoot(const NodePtr &node) const;
|
||||||
std::tuple<QString, QString> makeResourcesBlocksModule(const NodePtr &node) const;
|
std::tuple<QString, QString> makeResourcesBlocksModule(const NodePtr &node) const;
|
||||||
|
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "qmlprojectmanager/buildsystem/qmlbuildsystem.h"
|
#include "qmlprojectmanager/buildsystem/qmlbuildsystem.h"
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
namespace QmlProjectManager {
|
namespace QmlProjectManager {
|
||||||
|
|
||||||
namespace QmlProjectExporter {
|
namespace QmlProjectExporter {
|
||||||
@@ -19,6 +21,12 @@ target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
|
|||||||
Qt${QT_VERSION_MAJOR}::Quick
|
Qt${QT_VERSION_MAJOR}::Quick
|
||||||
Qt${QT_VERSION_MAJOR}::Qml))";
|
Qt${QT_VERSION_MAJOR}::Qml))";
|
||||||
|
|
||||||
|
const char TEMPLATE_DEPENDENCIES_CMAKELISTS[] = R"(
|
||||||
|
if (BUILD_QDS_COMPONENTS)
|
||||||
|
add_subdirectory(%1)
|
||||||
|
endif()
|
||||||
|
)";
|
||||||
|
|
||||||
CMakeWriterV1::CMakeWriterV1(CMakeGenerator *parent)
|
CMakeWriterV1::CMakeWriterV1(CMakeGenerator *parent)
|
||||||
: CMakeWriter(parent)
|
: CMakeWriter(parent)
|
||||||
{}
|
{}
|
||||||
@@ -52,10 +60,49 @@ void CMakeWriterV1::writeRootCMakeFile(const NodePtr &node) const
|
|||||||
writeFile(insightPath, insightTemplate);
|
writeFile(insightPath, insightTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Utils::FilePath componentPath = cmakeFolderPath.pathAppended("qmlcomponents.cmake");
|
const Utils::FilePath dependenciesPath = node->dir.pathAppended(DEPENDENCIES_DIR);
|
||||||
if (!componentPath.exists()) {
|
const Utils::FilePath componentsPath = dependenciesPath.pathAppended(COMPONENTS_DIR);
|
||||||
const QString compTemplate = readTemplate(":/templates/qmlcomponents");
|
const Utils::FilePath componentsIgnoreFile = componentsPath.pathAppended(COMPONENTS_IGNORE_FILE);
|
||||||
writeFile(componentPath, compTemplate);
|
|
||||||
|
bool copyComponents = false;
|
||||||
|
// Note: If dependencies directory exists but not the components directory, we assunme
|
||||||
|
// the user has intentionally deleted it because he has the components installed in Qt.
|
||||||
|
if (!dependenciesPath.exists()) {
|
||||||
|
dependenciesPath.createDir();
|
||||||
|
copyComponents = true;
|
||||||
|
} else if (componentsIgnoreFile.exists()) {
|
||||||
|
auto normalizeVersion = [](const auto &version) -> std::tuple<int, int, int> {
|
||||||
|
auto [major, minor, patch] = version;
|
||||||
|
return {major.value_or(0), minor.value_or(0), patch.value_or(0)};
|
||||||
|
};
|
||||||
|
auto *bs = parent()->buildSystem();
|
||||||
|
auto versionDS = normalizeVersion(versionFromString(bs->versionDesignStudio()));
|
||||||
|
auto versionIgnore = normalizeVersion(versionFromIgnoreFile(componentsIgnoreFile));
|
||||||
|
if (versionDS > versionIgnore) {
|
||||||
|
copyComponents = true;
|
||||||
|
if (componentsPath.exists())
|
||||||
|
componentsPath.removeRecursively();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copyComponents) {
|
||||||
|
if (!componentsPath.exists())
|
||||||
|
componentsPath.createDir();
|
||||||
|
|
||||||
|
const Utils::FilePath componentsSrc =
|
||||||
|
Core::ICore::resourcePath("qmldesigner/Dependencies/qtquickdesigner-components");
|
||||||
|
|
||||||
|
if (componentsSrc.exists()) {
|
||||||
|
auto cpyResult = componentsSrc.copyRecursively(componentsPath);
|
||||||
|
if (cpyResult) {
|
||||||
|
QString depsTemplate =
|
||||||
|
QString::fromUtf8(TEMPLATE_DEPENDENCIES_CMAKELISTS, -1).arg(COMPONENTS_DIR);
|
||||||
|
writeFile(dependenciesPath.pathAppended("CMakeLists.txt"), depsTemplate);
|
||||||
|
} else {
|
||||||
|
CMakeGenerator::logIssue(
|
||||||
|
ProjectExplorer::Task::Error, cpyResult.error(), componentsSrc);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Utils::FilePath sharedFile = node->dir.pathAppended("CMakeLists.txt.shared");
|
const Utils::FilePath sharedFile = node->dir.pathAppended("CMakeLists.txt.shared");
|
||||||
@@ -87,7 +134,7 @@ void CMakeWriterV1::writeModuleCMakeFile(const NodePtr &node, const NodePtr &) c
|
|||||||
if (node->type == Node::Type::App) {
|
if (node->type == Node::Type::App) {
|
||||||
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, {DEPENDENCIES_DIR}));
|
||||||
|
|
||||||
auto [resources, bigResources] = makeResourcesBlocksRoot(node);
|
auto [resources, bigResources] = makeResourcesBlocksRoot(node);
|
||||||
if (!resources.isEmpty()) {
|
if (!resources.isEmpty()) {
|
||||||
|
Reference in New Issue
Block a user