From 78dc251cc458207ce2ca4c621b5074c4f2dd1fea Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Tue, 30 Apr 2024 23:49:58 +0300 Subject: [PATCH] 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 Reviewed-by: Tim Jenssen --- .../contentlibraryeffectsmodel.cpp | 68 ++++++++++-------- .../contentlibraryeffectsmodel.h | 4 +- .../contentlibrarymaterialsmodel.cpp | 70 ++++++++++--------- .../contentlibrarymaterialsmodel.h | 5 +- .../contentlibraryusermodel.cpp | 64 ++++++++++------- .../designercore/generatedcomponentutils.cpp | 31 ++++++++ .../designercore/generatedcomponentutils.h | 6 ++ .../qmldesigner/qmldesignerconstants.h | 3 + 8 files changed, 160 insertions(+), 91 deletions(-) diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp index 882150db7e7..5a0c67b9ec4 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp @@ -128,9 +128,21 @@ void ContentLibraryEffectsModel::createImporter(const QString &bundlePath, const void ContentLibraryEffectsModel::loadBundle() { - if (m_bundleExists || m_probeBundleDir) + auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); + + if (m_probeBundleDir || (m_bundleExists && m_bundleId == compUtils.effectsBundleId())) 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; if (!qEnvironmentVariable("EFFECT_BUNDLE_PATH").isEmpty()) @@ -145,35 +157,33 @@ void ContentLibraryEffectsModel::loadBundle() while (!bundleDir.cd("effect_bundle") && bundleDir.cdUp()) ; // do nothing - if (bundleDir.dirName() != "effect_bundle") // bundlePathDir not found + if (bundleDir.dirName() != "effect_bundle") { // bundlePathDir not found + resetModel(); return; + } } QString bundlePath = bundleDir.filePath("effect_bundle.json"); - if (m_bundleObj.isEmpty()) { - QFile propsFile(bundlePath); - - if (!propsFile.open(QIODevice::ReadOnly)) { - qWarning("Couldn't open effect_bundle.json"); - return; - } - - QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(propsFile.readAll()); - if (bundleJsonDoc.isNull()) { - qWarning("Invalid effect_bundle.json file"); - return; - } else { - m_bundleObj = bundleJsonDoc.object(); - } + QFile bundleFile(bundlePath); + if (!bundleFile.open(QIODevice::ReadOnly)) { + qWarning("Couldn't open effect_bundle.json"); + resetModel(); + return; } - QString bundleType = QmlDesignerPlugin::instance()->documentManager() - .generatedComponentUtils().effectsBundleType(); + QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(bundleFile.readAll()); + if (bundleJsonDoc.isNull()) { + qWarning("Invalid effect_bundle.json file"); + resetModel(); + return; + } - // Substitute correct id to avoid issues with old bundles - const QString bundleId = bundleType.split('.').last(); - m_bundleObj["id"] = bundleId; + m_bundleId = compUtils.effectsBundleId(); + m_bundleObj = bundleJsonDoc.object(); + m_bundleObj["id"] = m_bundleId; + + QString bundleType = compUtils.effectsBundleType(); const QJsonObject catsObj = m_bundleObj.value("categories").toObject(); const QStringList categories = catsObj.keys(); @@ -181,9 +191,9 @@ void ContentLibraryEffectsModel::loadBundle() auto category = new ContentLibraryEffectsCategory(this, cat); const QJsonObject itemsObj = catsObj.value(cat).toObject(); - const QStringList items = itemsObj.keys(); - for (const QString &item : items) { - const QJsonObject itemObj = itemsObj.value(item).toObject(); + const QStringList itemsNames = itemsObj.keys(); + for (const QString &itemName : itemsNames) { + const QJsonObject itemObj = itemsObj.value(itemName).toObject(); QStringList files; const QJsonArray assetsArr = itemObj.value("files").toArray(); @@ -195,7 +205,7 @@ void ContentLibraryEffectsModel::loadBundle() TypeName type = QLatin1String("%1.%2") .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); } @@ -207,10 +217,12 @@ void ContentLibraryEffectsModel::loadBundle() for (const auto /*QJson{Const,}ValueRef*/ &file : sharedFilesArr) sharedFiles.append(file.toString()); - createImporter(bundleDir.path(), bundleId, sharedFiles); + createImporter(bundleDir.path(), m_bundleId, sharedFiles); + m_bundlePath = bundleDir.path(); m_bundleExists = true; - emit bundleExistsChanged(); + updateIsEmpty(); + resetModel(); } bool ContentLibraryEffectsModel::hasRequiredQuick3DImport() const diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h index 5d67ac3da8b..31adae8e7b8 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h @@ -86,8 +86,8 @@ private: int m_quick3dMajorVersion = -1; int m_quick3dMinorVersion = -1; - QString m_importerBundlePath; - QString m_importerBundleId; + QString m_bundlePath; + QString m_bundleId; QStringList m_importerSharedFiles; }; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp index 6331cf753ba..d525277be8a 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp @@ -246,38 +246,44 @@ void ContentLibraryMaterialsModel::createImporter(const QString &bundlePath, con 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; - 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()) { - QFile matPropsFile(matBundlePath); + QString bundlePath = bundleDir.filePath("material_bundle.json"); - if (!matPropsFile.open(QIODevice::ReadOnly)) { - qWarning("Couldn't open material_bundle.json"); - return; - } - - QJsonDocument matBundleJsonDoc = QJsonDocument::fromJson(matPropsFile.readAll()); - if (matBundleJsonDoc.isNull()) { - qWarning("Invalid material_bundle.json file"); - return; - } else { - m_matBundleObj = matBundleJsonDoc.object(); - } + QFile bundleFile(bundlePath); + if (!bundleFile.open(QIODevice::ReadOnly)) { + qWarning("Couldn't open material_bundle.json"); + resetModel(); + return; } - QString bundleType = QmlDesignerPlugin::instance()->documentManager() - .generatedComponentUtils().materialsBundleType(); + QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(bundleFile.readAll()); + if (bundleJsonDoc.isNull()) { + qWarning("Invalid material_bundle.json file"); + resetModel(); + return; + } - // Substitute correct id to avoid issues with old bundles - const QString bundleId = bundleType.split('.').last(); - m_matBundleObj["id"] = bundleId; + m_bundleObj = bundleJsonDoc.object(); - 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(); for (const QString &cat : categories) { auto category = new ContentLibraryMaterialsCategory(this, cat); @@ -292,7 +298,7 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &matBundleDir) for (const auto /*QJson{Const,}ValueRef*/ &asset : assetsArr) 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(); TypeName type = QLatin1String("%1.%2") .arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml @@ -306,28 +312,28 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &matBundleDir) } 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) sharedFiles.append(file.toString()); QStringList missingSharedFiles; for (const QString &s : std::as_const(sharedFiles)) { - const QString fullSharedFilePath = matBundleDir.filePath(s); + const QString fullSharedFilePath = bundleDir.filePath(s); if (!QFileInfo::exists(fullSharedFilePath)) missingSharedFiles.push_back(s); } if (missingSharedFiles.length() > 0) { - m_importerBundlePath = matBundleDir.path(); - m_importerBundleId = bundleId; + m_importerBundlePath = bundleDir.path(); + m_importerBundleId = m_bundleId; m_importerSharedFiles = sharedFiles; - downloadSharedFiles(matBundleDir, missingSharedFiles); + downloadSharedFiles(bundleDir, missingSharedFiles); } else { - createImporter(matBundleDir.path(), bundleId, sharedFiles); + createImporter(bundleDir.path(), m_bundleId, sharedFiles); } - m_matBundleExists = true; + m_bundleExists = true; emit matBundleExistsChanged(); } @@ -338,7 +344,7 @@ bool ContentLibraryMaterialsModel::hasRequiredQuick3DImport() const bool ContentLibraryMaterialsModel::matBundleExists() const { - return m_matBundleExists; + return m_bundleExists; } Internal::ContentLibraryBundleImporter *ContentLibraryMaterialsModel::bundleImporter() const diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h index a2c2e90ce1e..e4b135daea6 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h @@ -87,11 +87,12 @@ private: ContentLibraryWidget *m_widget = nullptr; QString m_searchText; QList m_bundleCategories; - QJsonObject m_matBundleObj; Internal::ContentLibraryBundleImporter *m_importer = nullptr; + QJsonObject m_bundleObj; + QString m_bundleId; bool m_isEmpty = true; - bool m_matBundleExists = false; + bool m_bundleExists = false; bool m_hasModelSelection = false; bool m_importerRunning = false; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp index e448d6e7571..5a887ee2ffb 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp @@ -210,41 +210,50 @@ QJsonObject &ContentLibraryUserModel::bundleJsonObjectRef() void ContentLibraryUserModel::loadMaterialBundle() { - if (m_matBundleExists) + auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); + + if (m_matBundleExists && m_bundleId == compUtils.userMaterialsBundleId()) 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"}; bundleDir.mkpath("."); - if (m_bundleObj.isEmpty()) { - auto jsonFilePath = Utils::FilePath::fromString(bundleDir.filePath("user_materials_bundle.json")); - if (!jsonFilePath.exists()) { - QString jsonContent = "{\n"; - jsonContent += " \"id\": \"UserMaterials\",\n"; - jsonContent += " \"materials\": {\n"; - jsonContent += " }\n"; - jsonContent += "}"; - 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(); - } + auto jsonFilePath = Utils::FilePath::fromString(bundleDir.filePath("user_materials_bundle.json")); + if (!jsonFilePath.exists()) { + QString jsonContent = "{\n"; + jsonContent += " \"id\": \"UserMaterials\",\n"; + jsonContent += " \"materials\": {\n"; + jsonContent += " }\n"; + jsonContent += "}"; + jsonFilePath.writeFileContents(jsonContent.toLatin1()); } - 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; // parse materials @@ -278,6 +287,7 @@ void ContentLibraryUserModel::loadMaterialBundle() m_matBundleExists = true; emit matBundleExistsChanged(); + emit dataChanged(index(matSectionIdx), index(matSectionIdx)); } void ContentLibraryUserModel::loadTextureBundle() diff --git a/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp b/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp index a2faa68d9e6..a1fe4d47632 100644 --- a/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp +++ b/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp @@ -186,4 +186,35 @@ QString GeneratedComponentUtils::effectsBundleType() const 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 diff --git a/src/plugins/qmldesigner/designercore/generatedcomponentutils.h b/src/plugins/qmldesigner/designercore/generatedcomponentutils.h index d9c04352a9e..ea4149b551c 100644 --- a/src/plugins/qmldesigner/designercore/generatedcomponentutils.h +++ b/src/plugins/qmldesigner/designercore/generatedcomponentutils.h @@ -35,6 +35,12 @@ public: QString materialsBundleType() const; QString effectsBundleType() const; + QString materialsBundleId() const; + QString effectsBundleId() const; + QString userMaterialsBundleId() const; + QString userEffectsBundleId() const; + QString user3DBundleId() const; + private: ExternalDependenciesInterface &m_externalDependencies; }; diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h index 286a1633c7d..ff85f6d25a9 100644 --- a/src/plugins/qmldesigner/qmldesignerconstants.h +++ b/src/plugins/qmldesigner/qmldesignerconstants.h @@ -81,6 +81,9 @@ inline constexpr char QML_DESIGNER_SUBFOLDER[] = "/designer/"; inline constexpr char COMPONENT_BUNDLES_TYPE[] = "Bundles"; inline constexpr char COMPONENT_BUNDLES_MATERIAL_BUNDLE_TYPE[] = "Materials"; 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 COMPONENT_BUNDLES_ASSET_REF_FILE[] = "_asset_ref.json"; inline constexpr char OLD_QUICK_3D_ASSETS_FOLDER[] = "Quick3DAssets";