forked from qt-creator/qt-creator
QmlDesigner: Add generated components when adding to content lib
Also few relevant fixes and tweaks. Fixes: QDS-13746 Change-Id: I2a22d535591d6908ca3960145cb01682844aee38 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Ali Kianian <ali.kianian@qt.io>
This commit is contained in:
@@ -38,6 +38,11 @@ Utils::FilePath AssetPath::absFilPath() const
|
|||||||
return basePath.pathAppended(relativePath);
|
return basePath.pathAppended(relativePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray AssetPath::fileContent() const
|
||||||
|
{
|
||||||
|
return absFilPath().fileContents().value_or("");
|
||||||
|
}
|
||||||
|
|
||||||
BundleHelper::BundleHelper(AbstractView *view, QWidget *widget)
|
BundleHelper::BundleHelper(AbstractView *view, QWidget *widget)
|
||||||
: m_view(view)
|
: m_view(view)
|
||||||
, m_widget(widget)
|
, m_widget(widget)
|
||||||
@@ -186,7 +191,7 @@ void BundleHelper::importBundleToProject()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString typePrefix = compUtils.userBundleType(bundleId);
|
QString typePrefix = compUtils.userBundleType(bundleId);
|
||||||
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
|
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.section('.', 0, 0)).toLatin1();
|
||||||
|
|
||||||
QString err = m_importer->importComponent(bundlePath.toFSPathString(), type, qml, files);
|
QString err = m_importer->importComponent(bundlePath.toFSPathString(), type, qml, files);
|
||||||
|
|
||||||
@@ -211,12 +216,6 @@ void BundleHelper::exportComponent(const ModelNode &node)
|
|||||||
if (exportPath.isEmpty())
|
if (exportPath.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// targetPath is a temp path for collecting and zipping assets, actual export target is where
|
|
||||||
// the user chose to export (i.e. exportPath)
|
|
||||||
QTemporaryDir tempDir;
|
|
||||||
QTC_ASSERT(tempDir.isValid(), return);
|
|
||||||
auto targetPath = Utils::FilePath::fromString(tempDir.path());
|
|
||||||
|
|
||||||
m_zipWriter = std::make_unique<ZipWriter>(exportPath);
|
m_zipWriter = std::make_unique<ZipWriter>(exportPath);
|
||||||
|
|
||||||
Utils::FilePath compFilePath = Utils::FilePath::fromString(ModelUtils::componentFilePath(node));
|
Utils::FilePath compFilePath = Utils::FilePath::fromString(ModelUtils::componentFilePath(node));
|
||||||
@@ -224,14 +223,14 @@ void BundleHelper::exportComponent(const ModelNode &node)
|
|||||||
QString compBaseName = compFilePath.completeBaseName();
|
QString compBaseName = compFilePath.completeBaseName();
|
||||||
QString compFileName = compFilePath.fileName();
|
QString compFileName = compFilePath.fileName();
|
||||||
|
|
||||||
QString iconPath = QLatin1String("icons/%1").arg(UniqueName::generateId(compBaseName) + ".png");
|
m_iconPath = QLatin1String("icons/%1").arg(UniqueName::generateId(compBaseName) + ".png");
|
||||||
|
|
||||||
const QSet<AssetPath> compDependencies = getComponentDependencies(compFilePath, compDir);
|
const QSet<AssetPath> compDependencies = getComponentDependencies(compFilePath, compDir);
|
||||||
|
|
||||||
QStringList filesList;
|
QStringList filesList;
|
||||||
for (const AssetPath &asset : compDependencies) {
|
for (const AssetPath &asset : compDependencies) {
|
||||||
Utils::FilePath assetAbsPath = asset.absFilPath();
|
Utils::FilePath assetAbsPath = asset.absFilPath();
|
||||||
QByteArray assetContent = assetAbsPath.fileContents().value_or("");
|
QByteArray assetContent = asset.fileContent();
|
||||||
|
|
||||||
// remove imports of sub components
|
// remove imports of sub components
|
||||||
for (const QString &import : std::as_const(asset.importsToRemove)) {
|
for (const QString &import : std::as_const(asset.importsToRemove)) {
|
||||||
@@ -252,7 +251,7 @@ void BundleHelper::exportComponent(const ModelNode &node)
|
|||||||
itemsArr.append(QJsonObject {
|
itemsArr.append(QJsonObject {
|
||||||
{"name", node.simplifiedTypeName()},
|
{"name", node.simplifiedTypeName()},
|
||||||
{"qml", compFileName},
|
{"qml", compFileName},
|
||||||
{"icon", iconPath},
|
{"icon", m_iconPath},
|
||||||
{"files", QJsonArray::fromStringList(filesList)}
|
{"files", QJsonArray::fromStringList(filesList)}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -262,12 +261,9 @@ void BundleHelper::exportComponent(const ModelNode &node)
|
|||||||
jsonObj["id"] = compUtils.user3DBundleId();
|
jsonObj["id"] = compUtils.user3DBundleId();
|
||||||
jsonObj["version"] = BUNDLE_VERSION;
|
jsonObj["version"] = BUNDLE_VERSION;
|
||||||
|
|
||||||
Utils::FilePath jsonFilePath = targetPath.pathAppended(Constants::BUNDLE_JSON_FILENAME);
|
m_zipWriter->addFile(Constants::BUNDLE_JSON_FILENAME, QJsonDocument(jsonObj).toJson());
|
||||||
m_zipWriter->addFile(jsonFilePath.fileName(), QJsonDocument(jsonObj).toJson());
|
|
||||||
|
|
||||||
// add icon
|
// add icon
|
||||||
m_iconSavePath = targetPath.pathAppended(iconPath);
|
|
||||||
m_iconSavePath.parentDir().ensureWritableDir();
|
|
||||||
getImageFromCache(compFilePath.path(), [&](const QImage &image) {
|
getImageFromCache(compFilePath.path(), [&](const QImage &image) {
|
||||||
addIconAndCloseZip(image);
|
addIconAndCloseZip(image);
|
||||||
});
|
});
|
||||||
@@ -293,6 +289,7 @@ void BundleHelper::exportNode(const ModelNode &node, const QPixmap &iconPixmap)
|
|||||||
|
|
||||||
QString qml = nodeNameToComponentFileName(name);
|
QString qml = nodeNameToComponentFileName(name);
|
||||||
QString iconBaseName = UniqueName::generateId(name);
|
QString iconBaseName = UniqueName::generateId(name);
|
||||||
|
m_iconPath = QLatin1String("icons/%1.png").arg(iconBaseName);
|
||||||
|
|
||||||
// generate and save Qml file
|
// generate and save Qml file
|
||||||
auto [qmlString, depAssets] = modelNodeToQmlString(node);
|
auto [qmlString, depAssets] = modelNodeToQmlString(node);
|
||||||
@@ -307,15 +304,13 @@ void BundleHelper::exportNode(const ModelNode &node, const QPixmap &iconPixmap)
|
|||||||
QTC_ASSERT_EXPECTED(result, return);
|
QTC_ASSERT_EXPECTED(result, return);
|
||||||
m_zipWriter->addFile(qmlFilePath.fileName(), qmlString.toUtf8());
|
m_zipWriter->addFile(qmlFilePath.fileName(), qmlString.toUtf8());
|
||||||
|
|
||||||
QString iconPath = QLatin1String("icons/%1.png").arg(iconBaseName);
|
|
||||||
|
|
||||||
// add the item to the bundle json
|
// add the item to the bundle json
|
||||||
QJsonObject jsonObj;
|
QJsonObject jsonObj;
|
||||||
QJsonArray itemsArr;
|
QJsonArray itemsArr;
|
||||||
itemsArr.append(QJsonObject {
|
itemsArr.append(QJsonObject {
|
||||||
{"name", name},
|
{"name", name},
|
||||||
{"qml", qml},
|
{"qml", qml},
|
||||||
{"icon", iconPath},
|
{"icon", m_iconPath},
|
||||||
{"files", QJsonArray::fromStringList(depAssetsRelativePaths)}
|
{"files", QJsonArray::fromStringList(depAssetsRelativePaths)}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -331,7 +326,7 @@ void BundleHelper::exportNode(const ModelNode &node, const QPixmap &iconPixmap)
|
|||||||
|
|
||||||
// add item's dependency assets to the bundle zip and target path (for icon generation)
|
// add item's dependency assets to the bundle zip and target path (for icon generation)
|
||||||
for (const AssetPath &assetPath : depAssetsList) {
|
for (const AssetPath &assetPath : depAssetsList) {
|
||||||
auto assetContent = assetPath.absFilPath().fileContents().value_or("");
|
QByteArray assetContent = assetPath.fileContent();
|
||||||
m_zipWriter->addFile(assetPath.relativePath, assetContent);
|
m_zipWriter->addFile(assetPath.relativePath, assetContent);
|
||||||
|
|
||||||
Utils::FilePath assetTargetPath = targetPath.pathAppended(assetPath.relativePath);
|
Utils::FilePath assetTargetPath = targetPath.pathAppended(assetPath.relativePath);
|
||||||
@@ -352,7 +347,6 @@ void BundleHelper::exportNode(const ModelNode &node, const QPixmap &iconPixmap)
|
|||||||
iconPixmapToSave = iconPixmap;
|
iconPixmapToSave = iconPixmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_iconSavePath = targetPath.pathAppended(iconPath);
|
|
||||||
if (iconPixmapToSave.isNull()) {
|
if (iconPixmapToSave.isNull()) {
|
||||||
getImageFromCache(qmlFilePath.toFSPathString(), [&](const QImage &image) {
|
getImageFromCache(qmlFilePath.toFSPathString(), [&](const QImage &image) {
|
||||||
addIconAndCloseZip(image);
|
addIconAndCloseZip(image);
|
||||||
@@ -556,7 +550,7 @@ void BundleHelper::addIconAndCloseZip(const auto &image) { // auto: QImage or QP
|
|||||||
buffer.open(QIODevice::WriteOnly);
|
buffer.open(QIODevice::WriteOnly);
|
||||||
image.save(&buffer, "PNG");
|
image.save(&buffer, "PNG");
|
||||||
|
|
||||||
m_zipWriter->addFile("icons/" + m_iconSavePath.fileName(), iconByteArray);
|
m_zipWriter->addFile(m_iconPath, iconByteArray);
|
||||||
m_zipWriter->close();
|
m_zipWriter->close();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -664,7 +658,7 @@ Utils::FilePath getComponentFilePath(const QString &nodeType, const Utils::FileP
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
QSet<AssetPath> BundleHelper::getComponentDependencies(const Utils::FilePath &filePath,
|
QSet<AssetPath> BundleHelper::getComponentDependencies(const Utils::FilePath &filePath,
|
||||||
const Utils::FilePath &mainCompDir)
|
const Utils::FilePath &mainCompDir) const
|
||||||
{
|
{
|
||||||
QSet<AssetPath> depList;
|
QSet<AssetPath> depList;
|
||||||
AssetPath compAssetPath = {mainCompDir, filePath.relativePathFrom(mainCompDir).toFSPathString()};
|
AssetPath compAssetPath = {mainCompDir, filePath.relativePathFrom(mainCompDir).toFSPathString()};
|
||||||
|
@@ -32,6 +32,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
Utils::FilePath absFilPath() const;
|
Utils::FilePath absFilPath() const;
|
||||||
|
QByteArray fileContent() const;
|
||||||
|
|
||||||
bool operator==(const AssetPath &other) const
|
bool operator==(const AssetPath &other) const
|
||||||
{
|
{
|
||||||
@@ -62,6 +63,8 @@ public:
|
|||||||
QString nodeNameToComponentFileName(const QString &name) const;
|
QString nodeNameToComponentFileName(const QString &name) const;
|
||||||
QPair<QString, QSet<AssetPath>> modelNodeToQmlString(const ModelNode &node, int depth = 0);
|
QPair<QString, QSet<AssetPath>> modelNodeToQmlString(const ModelNode &node, int depth = 0);
|
||||||
QString getImportPath() const;
|
QString getImportPath() const;
|
||||||
|
QSet<AssetPath> getComponentDependencies(const Utils::FilePath &filePath,
|
||||||
|
const Utils::FilePath &mainCompDir) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createImporter();
|
void createImporter();
|
||||||
@@ -71,8 +74,6 @@ private:
|
|||||||
void addIconAndCloseZip(const auto &image);
|
void addIconAndCloseZip(const auto &image);
|
||||||
Utils::FilePath componentPath(const NodeMetaInfo &metaInfo) const;
|
Utils::FilePath componentPath(const NodeMetaInfo &metaInfo) const;
|
||||||
QSet<AssetPath> getBundleComponentDependencies(const ModelNode &node) const;
|
QSet<AssetPath> getBundleComponentDependencies(const ModelNode &node) const;
|
||||||
QSet<AssetPath> getComponentDependencies(const Utils::FilePath &filePath,
|
|
||||||
const Utils::FilePath &mainCompDir);
|
|
||||||
void exportComponent(const ModelNode &node);
|
void exportComponent(const ModelNode &node);
|
||||||
void exportNode(const ModelNode &node, const QPixmap &iconPixmap = QPixmap());
|
void exportNode(const ModelNode &node, const QPixmap &iconPixmap = QPixmap());
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ private:
|
|||||||
Utils::UniqueObjectPtr<BundleImporter> m_importer;
|
Utils::UniqueObjectPtr<BundleImporter> m_importer;
|
||||||
std::unique_ptr<ZipWriter> m_zipWriter;
|
std::unique_ptr<ZipWriter> m_zipWriter;
|
||||||
std::unique_ptr<QTemporaryDir> m_tempDir;
|
std::unique_ptr<QTemporaryDir> m_tempDir;
|
||||||
Utils::FilePath m_iconSavePath;
|
QString m_iconPath;
|
||||||
|
|
||||||
static constexpr char BUNDLE_VERSION[] = "1.0";
|
static constexpr char BUNDLE_VERSION[] = "1.0";
|
||||||
};
|
};
|
||||||
|
@@ -84,7 +84,7 @@ void ContentLibraryUserModel::addItem(const QString &bundleId, const QString &na
|
|||||||
auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
|
auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
|
||||||
|
|
||||||
QString typePrefix = compUtils.userBundleType(bundleId);
|
QString typePrefix = compUtils.userBundleType(bundleId);
|
||||||
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
|
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.section('.', 0, 0)).toLatin1();
|
||||||
|
|
||||||
SectionIndex sectionIndex = bundleIdToSectionIndex(bundleId);
|
SectionIndex sectionIndex = bundleIdToSectionIndex(bundleId);
|
||||||
|
|
||||||
@@ -308,7 +308,7 @@ void ContentLibraryUserModel::updateImportedState(const QStringList &importedIte
|
|||||||
bool changed = false;
|
bool changed = false;
|
||||||
for (QObject *item : items) {
|
for (QObject *item : items) {
|
||||||
ContentLibraryItem *castedItem = qobject_cast<ContentLibraryItem *>(item);
|
ContentLibraryItem *castedItem = qobject_cast<ContentLibraryItem *>(item);
|
||||||
changed |= castedItem->setImported(importedItems.contains(castedItem->qml().chopped(4)));
|
changed |= castedItem->setImported(importedItems.contains(castedItem->qml().section('.', 0, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
|
@@ -570,17 +570,18 @@ void ContentLibraryView::addLibAssets(const QStringList &paths)
|
|||||||
m_widget->userModel()->addTextures(targetPathsToAdd);
|
m_widget->userModel()->addTextures(targetPathsToAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: combine this method with BundleHelper::exportComponent()
|
||||||
void ContentLibraryView::addLib3DComponent(const ModelNode &node)
|
void ContentLibraryView::addLib3DComponent(const ModelNode &node)
|
||||||
{
|
{
|
||||||
auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
|
auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
|
||||||
|
auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/3d/");
|
||||||
|
|
||||||
m_bundleId = compUtils.user3DBundleId();
|
m_bundleId = compUtils.user3DBundleId();
|
||||||
|
|
||||||
QString compBaseName = node.simplifiedTypeName();
|
Utils::FilePath compFilePath = Utils::FilePath::fromString(ModelUtils::componentFilePath(node));
|
||||||
QString compFileName = compBaseName + ".qml";
|
Utils::FilePath compDir = compFilePath.parentDir();
|
||||||
|
QString compBaseName = compFilePath.completeBaseName();
|
||||||
auto compDir = Utils::FilePath::fromString(ModelUtils::componentFilePath(node)).parentDir();
|
QString compFileName = compFilePath.fileName();
|
||||||
auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/3d/");
|
|
||||||
|
|
||||||
// confirm overwrite if an item with same name exists
|
// confirm overwrite if an item with same name exists
|
||||||
if (bundlePath.pathAppended(compFileName).exists()) {
|
if (bundlePath.pathAppended(compFileName).exists()) {
|
||||||
@@ -599,24 +600,28 @@ void ContentLibraryView::addLib3DComponent(const ModelNode &node)
|
|||||||
m_iconSavePath = bundlePath.pathAppended(iconPath);
|
m_iconSavePath = bundlePath.pathAppended(iconPath);
|
||||||
m_iconSavePath.parentDir().ensureWritableDir();
|
m_iconSavePath.parentDir().ensureWritableDir();
|
||||||
|
|
||||||
const Utils::FilePaths sourceFiles = compDir.dirEntries({{}, QDir::Files, QDirIterator::Subdirectories});
|
const QSet<AssetPath> compDependencies = m_bundleHelper->getComponentDependencies(compFilePath, compDir);
|
||||||
const QStringList ignoreList {"_importdata.json", "qmldir", compBaseName + ".hints"};
|
|
||||||
QStringList filesList; // 3D component's assets (dependencies)
|
QStringList filesList; // 3D component's assets (dependencies)
|
||||||
|
for (const AssetPath &asset : compDependencies) {
|
||||||
|
Utils::FilePath assetAbsPath = asset.absFilPath();
|
||||||
|
QByteArray assetContent = asset.fileContent();
|
||||||
|
|
||||||
for (const Utils::FilePath &sourcePath : sourceFiles) {
|
// remove imports of sub components
|
||||||
Utils::FilePath relativePath = sourcePath.relativePathFrom(compDir);
|
for (const QString &import : std::as_const(asset.importsToRemove)) {
|
||||||
if (ignoreList.contains(sourcePath.fileName()) || relativePath.startsWith("source scene"))
|
int removeIdx = assetContent.indexOf(QByteArray("import " + import.toLatin1()));
|
||||||
continue;
|
int removeLen = assetContent.indexOf('\n', removeIdx) - removeIdx;
|
||||||
|
assetContent.remove(removeIdx, removeLen);
|
||||||
|
}
|
||||||
|
|
||||||
Utils::FilePath targetPath = bundlePath.pathAppended(relativePath.path());
|
Utils::FilePath targetPath = bundlePath.pathAppended(asset.relativePath);
|
||||||
targetPath.parentDir().ensureWritableDir();
|
targetPath.parentDir().ensureWritableDir();
|
||||||
|
|
||||||
// copy item from project to user bundle
|
auto result = targetPath.writeFileContents(assetContent);
|
||||||
auto result = sourcePath.copyFile(targetPath);
|
|
||||||
QTC_ASSERT_EXPECTED(result,);
|
QTC_ASSERT_EXPECTED(result,);
|
||||||
|
|
||||||
if (sourcePath.fileName() != compFileName) // skip component file (only collect dependencies)
|
if (assetAbsPath.fileName() != compFileName) // skip component file (only collect dependencies)
|
||||||
filesList.append(relativePath.path());
|
filesList.append(asset.relativePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the item to the bundle json
|
// add the item to the bundle json
|
||||||
|
@@ -78,7 +78,7 @@ void UserItemCategory::loadBundle(bool force)
|
|||||||
|
|
||||||
QString name = itemObj.value("name").toString();
|
QString name = itemObj.value("name").toString();
|
||||||
QString qml = itemObj.value("qml").toString();
|
QString qml = itemObj.value("qml").toString();
|
||||||
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
|
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.section('.', 0, 0)).toLatin1();
|
||||||
QUrl icon = m_bundlePath.pathAppended(itemObj.value("icon").toString()).toUrl();
|
QUrl icon = m_bundlePath.pathAppended(itemObj.value("icon").toString()).toUrl();
|
||||||
QStringList files = itemObj.value("files").toVariant().toStringList();
|
QStringList files = itemObj.value("files").toVariant().toStringList();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user