QmlDesigner: Reload bundles when id change

i.e. when opening a project that has a different import folder style
from the currently open project.

Fixes: QDS-12639
Change-Id: I8d341c38ec771dc5e28c4436cd9ad191e27c38a8
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Mahmoud Badri
2024-04-30 23:49:58 +03:00
committed by Tim Jenssen
parent e0942ce2fb
commit 78dc251cc4
8 changed files with 160 additions and 91 deletions

View File

@@ -128,9 +128,21 @@ void ContentLibraryEffectsModel::createImporter(const QString &bundlePath, const
void ContentLibraryEffectsModel::loadBundle() void ContentLibraryEffectsModel::loadBundle()
{ {
if (m_bundleExists || m_probeBundleDir) auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
if (m_probeBundleDir || (m_bundleExists && m_bundleId == compUtils.effectsBundleId()))
return; return;
// clean up
qDeleteAll(m_bundleCategories);
m_bundleCategories.clear();
m_bundleExists = false;
m_isEmpty = true;
m_probeBundleDir = false;
m_bundleObj = {};
m_bundleId.clear();
m_bundlePath.clear();
QDir bundleDir; QDir bundleDir;
if (!qEnvironmentVariable("EFFECT_BUNDLE_PATH").isEmpty()) if (!qEnvironmentVariable("EFFECT_BUNDLE_PATH").isEmpty())
@@ -145,35 +157,33 @@ void ContentLibraryEffectsModel::loadBundle()
while (!bundleDir.cd("effect_bundle") && bundleDir.cdUp()) while (!bundleDir.cd("effect_bundle") && bundleDir.cdUp())
; // do nothing ; // do nothing
if (bundleDir.dirName() != "effect_bundle") // bundlePathDir not found if (bundleDir.dirName() != "effect_bundle") { // bundlePathDir not found
resetModel();
return; return;
}
} }
QString bundlePath = bundleDir.filePath("effect_bundle.json"); QString bundlePath = bundleDir.filePath("effect_bundle.json");
if (m_bundleObj.isEmpty()) { QFile bundleFile(bundlePath);
QFile propsFile(bundlePath); if (!bundleFile.open(QIODevice::ReadOnly)) {
qWarning("Couldn't open effect_bundle.json");
if (!propsFile.open(QIODevice::ReadOnly)) { resetModel();
qWarning("Couldn't open effect_bundle.json"); return;
return;
}
QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(propsFile.readAll());
if (bundleJsonDoc.isNull()) {
qWarning("Invalid effect_bundle.json file");
return;
} else {
m_bundleObj = bundleJsonDoc.object();
}
} }
QString bundleType = QmlDesignerPlugin::instance()->documentManager() QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(bundleFile.readAll());
.generatedComponentUtils().effectsBundleType(); if (bundleJsonDoc.isNull()) {
qWarning("Invalid effect_bundle.json file");
resetModel();
return;
}
// Substitute correct id to avoid issues with old bundles m_bundleId = compUtils.effectsBundleId();
const QString bundleId = bundleType.split('.').last(); m_bundleObj = bundleJsonDoc.object();
m_bundleObj["id"] = bundleId; m_bundleObj["id"] = m_bundleId;
QString bundleType = compUtils.effectsBundleType();
const QJsonObject catsObj = m_bundleObj.value("categories").toObject(); const QJsonObject catsObj = m_bundleObj.value("categories").toObject();
const QStringList categories = catsObj.keys(); const QStringList categories = catsObj.keys();
@@ -181,9 +191,9 @@ void ContentLibraryEffectsModel::loadBundle()
auto category = new ContentLibraryEffectsCategory(this, cat); auto category = new ContentLibraryEffectsCategory(this, cat);
const QJsonObject itemsObj = catsObj.value(cat).toObject(); const QJsonObject itemsObj = catsObj.value(cat).toObject();
const QStringList items = itemsObj.keys(); const QStringList itemsNames = itemsObj.keys();
for (const QString &item : items) { for (const QString &itemName : itemsNames) {
const QJsonObject itemObj = itemsObj.value(item).toObject(); const QJsonObject itemObj = itemsObj.value(itemName).toObject();
QStringList files; QStringList files;
const QJsonArray assetsArr = itemObj.value("files").toArray(); const QJsonArray assetsArr = itemObj.value("files").toArray();
@@ -195,7 +205,7 @@ void ContentLibraryEffectsModel::loadBundle()
TypeName type = QLatin1String("%1.%2") TypeName type = QLatin1String("%1.%2")
.arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml .arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
auto bundleItem = new ContentLibraryEffect(category, item, qml, type, icon, files); auto bundleItem = new ContentLibraryEffect(category, itemName, qml, type, icon, files);
category->addBundleItem(bundleItem); category->addBundleItem(bundleItem);
} }
@@ -207,10 +217,12 @@ void ContentLibraryEffectsModel::loadBundle()
for (const auto /*QJson{Const,}ValueRef*/ &file : sharedFilesArr) for (const auto /*QJson{Const,}ValueRef*/ &file : sharedFilesArr)
sharedFiles.append(file.toString()); sharedFiles.append(file.toString());
createImporter(bundleDir.path(), bundleId, sharedFiles); createImporter(bundleDir.path(), m_bundleId, sharedFiles);
m_bundlePath = bundleDir.path();
m_bundleExists = true; m_bundleExists = true;
emit bundleExistsChanged(); updateIsEmpty();
resetModel();
} }
bool ContentLibraryEffectsModel::hasRequiredQuick3DImport() const bool ContentLibraryEffectsModel::hasRequiredQuick3DImport() const

View File

@@ -86,8 +86,8 @@ private:
int m_quick3dMajorVersion = -1; int m_quick3dMajorVersion = -1;
int m_quick3dMinorVersion = -1; int m_quick3dMinorVersion = -1;
QString m_importerBundlePath; QString m_bundlePath;
QString m_importerBundleId; QString m_bundleId;
QStringList m_importerSharedFiles; QStringList m_importerSharedFiles;
}; };

View File

@@ -246,38 +246,44 @@ void ContentLibraryMaterialsModel::createImporter(const QString &bundlePath, con
updateIsEmpty(); updateIsEmpty();
} }
void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &matBundleDir) void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &bundleDir)
{ {
if (m_matBundleExists) auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
if (m_bundleExists && m_bundleId == compUtils.materialsBundleId())
return; return;
QString matBundlePath = matBundleDir.filePath("material_bundle.json"); // clean up
qDeleteAll(m_bundleCategories);
m_bundleCategories.clear();
m_bundleExists = false;
m_isEmpty = true;
m_bundleObj = {};
m_bundleId.clear();
if (m_matBundleObj.isEmpty()) { QString bundlePath = bundleDir.filePath("material_bundle.json");
QFile matPropsFile(matBundlePath);
if (!matPropsFile.open(QIODevice::ReadOnly)) { QFile bundleFile(bundlePath);
qWarning("Couldn't open material_bundle.json"); if (!bundleFile.open(QIODevice::ReadOnly)) {
return; qWarning("Couldn't open material_bundle.json");
} resetModel();
return;
QJsonDocument matBundleJsonDoc = QJsonDocument::fromJson(matPropsFile.readAll());
if (matBundleJsonDoc.isNull()) {
qWarning("Invalid material_bundle.json file");
return;
} else {
m_matBundleObj = matBundleJsonDoc.object();
}
} }
QString bundleType = QmlDesignerPlugin::instance()->documentManager() QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(bundleFile.readAll());
.generatedComponentUtils().materialsBundleType(); if (bundleJsonDoc.isNull()) {
qWarning("Invalid material_bundle.json file");
resetModel();
return;
}
// Substitute correct id to avoid issues with old bundles m_bundleObj = bundleJsonDoc.object();
const QString bundleId = bundleType.split('.').last();
m_matBundleObj["id"] = bundleId;
const QJsonObject catsObj = m_matBundleObj.value("categories").toObject(); QString bundleType = compUtils.materialsBundleType();
m_bundleId = compUtils.materialsBundleId();
m_bundleObj["id"] = m_bundleId;
const QJsonObject catsObj = m_bundleObj.value("categories").toObject();
const QStringList categories = catsObj.keys(); const QStringList categories = catsObj.keys();
for (const QString &cat : categories) { for (const QString &cat : categories) {
auto category = new ContentLibraryMaterialsCategory(this, cat); auto category = new ContentLibraryMaterialsCategory(this, cat);
@@ -292,7 +298,7 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &matBundleDir)
for (const auto /*QJson{Const,}ValueRef*/ &asset : assetsArr) for (const auto /*QJson{Const,}ValueRef*/ &asset : assetsArr)
files.append(asset.toString()); files.append(asset.toString());
QUrl icon = QUrl::fromLocalFile(matBundleDir.filePath(matObj.value("icon").toString())); QUrl icon = QUrl::fromLocalFile(bundleDir.filePath(matObj.value("icon").toString()));
QString qml = matObj.value("qml").toString(); QString qml = matObj.value("qml").toString();
TypeName type = QLatin1String("%1.%2") TypeName type = QLatin1String("%1.%2")
.arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml .arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
@@ -306,28 +312,28 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &matBundleDir)
} }
QStringList sharedFiles; QStringList sharedFiles;
const QJsonArray sharedFilesArr = m_matBundleObj.value("sharedFiles").toArray(); const QJsonArray sharedFilesArr = m_bundleObj.value("sharedFiles").toArray();
for (const auto /*QJson{Const,}ValueRef*/ &file : sharedFilesArr) for (const auto /*QJson{Const,}ValueRef*/ &file : sharedFilesArr)
sharedFiles.append(file.toString()); sharedFiles.append(file.toString());
QStringList missingSharedFiles; QStringList missingSharedFiles;
for (const QString &s : std::as_const(sharedFiles)) { for (const QString &s : std::as_const(sharedFiles)) {
const QString fullSharedFilePath = matBundleDir.filePath(s); const QString fullSharedFilePath = bundleDir.filePath(s);
if (!QFileInfo::exists(fullSharedFilePath)) if (!QFileInfo::exists(fullSharedFilePath))
missingSharedFiles.push_back(s); missingSharedFiles.push_back(s);
} }
if (missingSharedFiles.length() > 0) { if (missingSharedFiles.length() > 0) {
m_importerBundlePath = matBundleDir.path(); m_importerBundlePath = bundleDir.path();
m_importerBundleId = bundleId; m_importerBundleId = m_bundleId;
m_importerSharedFiles = sharedFiles; m_importerSharedFiles = sharedFiles;
downloadSharedFiles(matBundleDir, missingSharedFiles); downloadSharedFiles(bundleDir, missingSharedFiles);
} else { } else {
createImporter(matBundleDir.path(), bundleId, sharedFiles); createImporter(bundleDir.path(), m_bundleId, sharedFiles);
} }
m_matBundleExists = true; m_bundleExists = true;
emit matBundleExistsChanged(); emit matBundleExistsChanged();
} }
@@ -338,7 +344,7 @@ bool ContentLibraryMaterialsModel::hasRequiredQuick3DImport() const
bool ContentLibraryMaterialsModel::matBundleExists() const bool ContentLibraryMaterialsModel::matBundleExists() const
{ {
return m_matBundleExists; return m_bundleExists;
} }
Internal::ContentLibraryBundleImporter *ContentLibraryMaterialsModel::bundleImporter() const Internal::ContentLibraryBundleImporter *ContentLibraryMaterialsModel::bundleImporter() const

View File

@@ -87,11 +87,12 @@ private:
ContentLibraryWidget *m_widget = nullptr; ContentLibraryWidget *m_widget = nullptr;
QString m_searchText; QString m_searchText;
QList<ContentLibraryMaterialsCategory *> m_bundleCategories; QList<ContentLibraryMaterialsCategory *> m_bundleCategories;
QJsonObject m_matBundleObj;
Internal::ContentLibraryBundleImporter *m_importer = nullptr; Internal::ContentLibraryBundleImporter *m_importer = nullptr;
QJsonObject m_bundleObj;
QString m_bundleId;
bool m_isEmpty = true; bool m_isEmpty = true;
bool m_matBundleExists = false; bool m_bundleExists = false;
bool m_hasModelSelection = false; bool m_hasModelSelection = false;
bool m_importerRunning = false; bool m_importerRunning = false;

View File

@@ -210,41 +210,50 @@ QJsonObject &ContentLibraryUserModel::bundleJsonObjectRef()
void ContentLibraryUserModel::loadMaterialBundle() void ContentLibraryUserModel::loadMaterialBundle()
{ {
if (m_matBundleExists) auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
if (m_matBundleExists && m_bundleId == compUtils.userMaterialsBundleId())
return; return;
// clean up
qDeleteAll(m_userMaterials);
m_userMaterials.clear();
m_matBundleExists = false;
m_isEmpty = true;
m_bundleObj = {};
m_bundleId.clear();
int matSectionIdx = 0;
QDir bundleDir{Paths::bundlesPathSetting() + "/User/materials"}; QDir bundleDir{Paths::bundlesPathSetting() + "/User/materials"};
bundleDir.mkpath("."); bundleDir.mkpath(".");
if (m_bundleObj.isEmpty()) { auto jsonFilePath = Utils::FilePath::fromString(bundleDir.filePath("user_materials_bundle.json"));
auto jsonFilePath = Utils::FilePath::fromString(bundleDir.filePath("user_materials_bundle.json")); if (!jsonFilePath.exists()) {
if (!jsonFilePath.exists()) { QString jsonContent = "{\n";
QString jsonContent = "{\n"; jsonContent += " \"id\": \"UserMaterials\",\n";
jsonContent += " \"id\": \"UserMaterials\",\n"; jsonContent += " \"materials\": {\n";
jsonContent += " \"materials\": {\n"; jsonContent += " }\n";
jsonContent += " }\n"; jsonContent += "}";
jsonContent += "}"; jsonFilePath.writeFileContents(jsonContent.toLatin1());
jsonFilePath.writeFileContents(jsonContent.toLatin1());
}
QFile jsonFile(jsonFilePath.path());
if (!jsonFile.open(QIODevice::ReadOnly)) {
qWarning("Couldn't open user_materials_bundle.json");
return;
}
QJsonDocument matBundleJsonDoc = QJsonDocument::fromJson(jsonFile.readAll());
if (matBundleJsonDoc.isNull()) {
qWarning("Invalid user_materials_bundle.json file");
return;
} else {
m_bundleObj = matBundleJsonDoc.object();
}
} }
m_bundleId = "UserMaterials"; QFile jsonFile(jsonFilePath.path());
if (!jsonFile.open(QIODevice::ReadOnly)) {
qWarning("Couldn't open user_materials_bundle.json");
emit dataChanged(index(matSectionIdx), index(matSectionIdx));
return;
}
// Substitute correct id to avoid issues with old bundles QJsonDocument matBundleJsonDoc = QJsonDocument::fromJson(jsonFile.readAll());
if (matBundleJsonDoc.isNull()) {
qWarning("Invalid user_materials_bundle.json file");
emit dataChanged(index(matSectionIdx), index(matSectionIdx));
return;
}
m_bundleId = compUtils.userMaterialsBundleId();;
m_bundleObj = matBundleJsonDoc.object();
m_bundleObj["id"] = m_bundleId; m_bundleObj["id"] = m_bundleId;
// parse materials // parse materials
@@ -278,6 +287,7 @@ void ContentLibraryUserModel::loadMaterialBundle()
m_matBundleExists = true; m_matBundleExists = true;
emit matBundleExistsChanged(); emit matBundleExistsChanged();
emit dataChanged(index(matSectionIdx), index(matSectionIdx));
} }
void ContentLibraryUserModel::loadTextureBundle() void ContentLibraryUserModel::loadTextureBundle()

View File

@@ -186,4 +186,35 @@ QString GeneratedComponentUtils::effectsBundleType() const
return basePrefix + '.' + QLatin1String(Constants::COMPONENT_BUNDLES_EFFECT_BUNDLE_TYPE); return basePrefix + '.' + QLatin1String(Constants::COMPONENT_BUNDLES_EFFECT_BUNDLE_TYPE);
} }
QString GeneratedComponentUtils::materialsBundleId() const
{
bool isNewImportDir = generatedComponentTypePrefix().endsWith(Constants::GENERATED_COMPONENTS_FOLDER);
return QLatin1String(isNewImportDir ? Constants::COMPONENT_BUNDLES_MATERIAL_BUNDLE_TYPE
: Constants::OLD_COMPONENT_BUNDLES_MATERIAL_BUNDLE_TYPE);
}
QString GeneratedComponentUtils::effectsBundleId() const
{
bool isNewImportDir = generatedComponentTypePrefix().endsWith(Constants::GENERATED_COMPONENTS_FOLDER);
return QLatin1String(isNewImportDir ? Constants::COMPONENT_BUNDLES_EFFECT_BUNDLE_TYPE
: Constants::OLD_COMPONENT_BUNDLES_EFFECT_BUNDLE_TYPE);
}
QString GeneratedComponentUtils::userMaterialsBundleId() const
{
return QLatin1String(Constants::COMPONENT_BUNDLES_USER_MATERIAL_BUNDLE_TYPE);
}
QString GeneratedComponentUtils::userEffectsBundleId() const
{
return QLatin1String(Constants::COMPONENT_BUNDLES_USER_EFFECT_BUNDLE_TYPE);
}
QString GeneratedComponentUtils::user3DBundleId() const
{
return QLatin1String(Constants::COMPONENT_BUNDLES_USER_3D_BUNDLE_TYPE);
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -35,6 +35,12 @@ public:
QString materialsBundleType() const; QString materialsBundleType() const;
QString effectsBundleType() const; QString effectsBundleType() const;
QString materialsBundleId() const;
QString effectsBundleId() const;
QString userMaterialsBundleId() const;
QString userEffectsBundleId() const;
QString user3DBundleId() const;
private: private:
ExternalDependenciesInterface &m_externalDependencies; ExternalDependenciesInterface &m_externalDependencies;
}; };

View File

@@ -81,6 +81,9 @@ inline constexpr char QML_DESIGNER_SUBFOLDER[] = "/designer/";
inline constexpr char COMPONENT_BUNDLES_TYPE[] = "Bundles"; inline constexpr char COMPONENT_BUNDLES_TYPE[] = "Bundles";
inline constexpr char COMPONENT_BUNDLES_MATERIAL_BUNDLE_TYPE[] = "Materials"; inline constexpr char COMPONENT_BUNDLES_MATERIAL_BUNDLE_TYPE[] = "Materials";
inline constexpr char COMPONENT_BUNDLES_EFFECT_BUNDLE_TYPE[] = "Effects"; inline constexpr char COMPONENT_BUNDLES_EFFECT_BUNDLE_TYPE[] = "Effects";
inline constexpr char COMPONENT_BUNDLES_USER_MATERIAL_BUNDLE_TYPE[] = "UserMaterials";
inline constexpr char COMPONENT_BUNDLES_USER_EFFECT_BUNDLE_TYPE[] = "UserEffects";
inline constexpr char COMPONENT_BUNDLES_USER_3D_BUNDLE_TYPE[] = "User3D";
inline constexpr char GENERATED_COMPONENTS_FOLDER[] = "Generated"; inline constexpr char GENERATED_COMPONENTS_FOLDER[] = "Generated";
inline constexpr char COMPONENT_BUNDLES_ASSET_REF_FILE[] = "_asset_ref.json"; inline constexpr char COMPONENT_BUNDLES_ASSET_REF_FILE[] = "_asset_ref.json";
inline constexpr char OLD_QUICK_3D_ASSETS_FOLDER[] = "Quick3DAssets"; inline constexpr char OLD_QUICK_3D_ASSETS_FOLDER[] = "Quick3DAssets";