From 7525ef79dea1cba831275ef687f7edd97106e5f1 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Tue, 30 Apr 2024 12:56:02 +0300 Subject: [PATCH] QmlDesigner: Use only 1 content library importer for all bundles Change-Id: I59e8efda2e5704caf72297b8dee5178eb8ecfc71 Reviewed-by: Miikka Heikkinen Reviewed-by: Qt CI Patch Build Bot --- .../ContentLibraryEffect.qml | 2 +- .../ContentLibraryEffectContextMenu.qml | 2 +- .../ContentLibraryMaterialsView.qml | 4 +- .../ContentLibraryUserView.qml | 4 +- .../contentlibrarybundleimporter.cpp | 43 +-- .../contentlibrarybundleimporter.h | 12 +- .../contentlibraryeffectsmodel.cpp | 106 ++------ .../contentlibraryeffectsmodel.h | 25 +- .../contentlibrarymaterialsmodel.cpp | 106 ++------ .../contentlibrarymaterialsmodel.h | 28 +- .../contentlibraryusermodel.cpp | 101 +------ .../contentlibrary/contentlibraryusermodel.h | 22 +- .../contentlibrary/contentlibraryview.cpp | 247 ++++++++---------- .../contentlibrary/contentlibraryview.h | 10 +- .../contentlibrary/contentlibrarywidget.cpp | 76 +++++- .../contentlibrary/contentlibrarywidget.h | 16 +- .../designercore/generatedcomponentutils.cpp | 31 +++ .../designercore/generatedcomponentutils.h | 6 + .../qmldesigner/qmldesignerconstants.h | 3 + 19 files changed, 355 insertions(+), 489 deletions(-) diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffect.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffect.qml index b20cc71e156..bf60ef66115 100644 --- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffect.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffect.qml @@ -23,7 +23,7 @@ Item { acceptedButtons: Qt.LeftButton | Qt.RightButton onPressed: (mouse) => { - if (mouse.button === Qt.LeftButton && !ContentLibraryBackend.effectsModel.importerRunning) + if (mouse.button === Qt.LeftButton && !ContentLibraryBackend.rootView.importerRunning) ContentLibraryBackend.rootView.startDragEffect(modelData, mapToGlobal(mouse.x, mouse.y)) else if (mouse.button === Qt.RightButton) root.showContextMenu() diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffectContextMenu.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffectContextMenu.qml index 1e0bcf1eb40..008f99d4fa7 100644 --- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffectContextMenu.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffectContextMenu.qml @@ -12,7 +12,7 @@ StudioControls.Menu { property var targetItem: null - readonly property bool targetAvailable: targetItem && !ContentLibraryBackend.effectsModel.importerRunning + readonly property bool targetAvailable: targetItem && !ContentLibraryBackend.rootView.importerRunning signal unimport(var bundleEff); diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml index 9a0e33b8e5e..3e58dd4306e 100644 --- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml @@ -50,7 +50,7 @@ HelperWidgets.ScrollView { id: ctxMenu hasModelSelection: root.materialsModel.hasModelSelection - importerRunning: root.materialsModel.importerRunning + importerRunning: ContentLibraryBackend.rootView.importerRunning onApplyToSelected: (add) => root.materialsModel.applyToSelected(ctxMenu.targetMaterial, add) @@ -103,7 +103,7 @@ HelperWidgets.ScrollView { width: root.cellWidth height: root.cellHeight - importerRunning: root.materialsModel.importerRunning + importerRunning: ContentLibraryBackend.rootView.importerRunning onShowContextMenu: ctxMenu.popupMenu(modelData) onAddToProject: root.materialsModel.addToProject(modelData) diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml index 8fd196dbcde..8528c75e739 100644 --- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml @@ -52,7 +52,7 @@ HelperWidgets.ScrollView { enableRemove: true hasModelSelection: ContentLibraryBackend.userModel.hasModelSelection - importerRunning: ContentLibraryBackend.userModel.importerRunning + importerRunning: ContentLibraryBackend.rootView.importerRunning onApplyToSelected: (add) => ContentLibraryBackend.userModel.applyToSelected(ctxMenuMaterial.targetMaterial, add) @@ -114,7 +114,7 @@ HelperWidgets.ScrollView { width: root.cellWidth height: root.cellHeight - importerRunning: ContentLibraryBackend.userModel.importerRunning + importerRunning: ContentLibraryBackend.rootView.importerRunning onShowContextMenu: ctxMenuMaterial.popupMenu(modelData) onAddToProject: ContentLibraryBackend.userModel.addToProject(modelData) diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp index d4859305538..6388c93fa96 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp @@ -3,12 +3,13 @@ #include "contentlibrarybundleimporter.h" -#include "documentmanager.h" -#include "import.h" -#include "model.h" -#include "qmldesignerconstants.h" -#include "qmldesignerplugin.h" -#include "rewritingexception.h" +#include +#include +#include +#include +#include +#include +#include #include @@ -37,10 +38,10 @@ QString ContentLibraryBundleImporter::importComponent(const QString &bundleDir, const QStringList &files) { QString module = QString::fromLatin1(type.left(type.lastIndexOf('.'))); - QString bundleId = module.mid(module.lastIndexOf('.') + 1); + m_bundleId = module.mid(module.lastIndexOf('.') + 1); FilePath bundleDirPath = FilePath::fromString(bundleDir); // source dir - FilePath bundleImportPath = resolveBundleImportPath(bundleId); // target dir + FilePath bundleImportPath = resolveBundleImportPath(m_bundleId); // target dir if (bundleImportPath.isEmpty()) return "Failed to resolve bundle import folder"; @@ -145,9 +146,11 @@ void ContentLibraryBundleImporter::handleImportTimer() for (const TypeName &pendingType : pendingTypes) { m_pendingTypes.remove(pendingType); if (m_pendingTypes.value(pendingType)) - emit importFinished({}); + emit importFinished({}, m_bundleId); else - emit unimportFinished({}); + emit unimportFinished({}, m_bundleId); + + m_bundleId.clear(); } }; @@ -193,12 +196,14 @@ void ContentLibraryBundleImporter::handleImportTimer() m_pendingTypes.remove(pendingType); if (isImport) #ifdef QDS_USE_PROJECTSTORAGE - emit importFinished(pendingType); + emit importFinished(pendingType, m_bundleId); #else - emit importFinished(metaInfo); + emit importFinished(metaInfo, m_bundleId); #endif else - emit unimportFinished(metaInfo); + emit unimportFinished(metaInfo, m_bundleId); + + m_bundleId.clear(); } } @@ -208,10 +213,10 @@ void ContentLibraryBundleImporter::handleImportTimer() } } -QVariantHash ContentLibraryBundleImporter::loadAssetRefMap(const Utils::FilePath &bundlePath) +QVariantHash ContentLibraryBundleImporter::loadAssetRefMap(const FilePath &bundlePath) { FilePath assetRefPath = bundlePath.resolvePath(QLatin1String(Constants::COMPONENT_BUNDLES_ASSET_REF_FILE)); - const Utils::expected_str content = assetRefPath.fileContents(); + const expected_str content = assetRefPath.fileContents(); if (content) { QJsonParseError error; QJsonDocument bundleDataJsonDoc = QJsonDocument::fromJson(*content, &error); @@ -225,7 +230,7 @@ QVariantHash ContentLibraryBundleImporter::loadAssetRefMap(const Utils::FilePath return {}; } -void ContentLibraryBundleImporter::writeAssetRefMap(const Utils::FilePath &bundlePath, +void ContentLibraryBundleImporter::writeAssetRefMap(const FilePath &bundlePath, const QVariantHash &assetRefMap) { FilePath assetRefPath = bundlePath.resolvePath(QLatin1String(Constants::COMPONENT_BUNDLES_ASSET_REF_FILE)); @@ -239,9 +244,11 @@ void ContentLibraryBundleImporter::writeAssetRefMap(const Utils::FilePath &bundl QString ContentLibraryBundleImporter::unimportComponent(const TypeName &type, const QString &qmlFile) { QString module = QString::fromLatin1(type.left(type.lastIndexOf('.'))); - QString bundleId = module.mid(module.lastIndexOf('.') + 1); + m_bundleId = module.mid(module.lastIndexOf('.') + 1); - FilePath bundleImportPath = resolveBundleImportPath(bundleId); + emit aboutToUnimport(type, m_bundleId); + + FilePath bundleImportPath = resolveBundleImportPath(m_bundleId); if (bundleImportPath.isEmpty()) return QStringLiteral("Failed to resolve bundle import folder for: '%1'").arg(qmlFile); diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h index 10786ead995..8155311e3e4 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h @@ -3,7 +3,7 @@ #pragma once -#include +#include #include @@ -12,6 +12,8 @@ namespace QmlDesigner { +class NodeMetaInfo; + class ContentLibraryBundleImporter : public QObject { Q_OBJECT @@ -30,11 +32,12 @@ signals: // asynchronous part of the import. In this case all remaining pending imports have been // terminated, and will not receive separate importFinished notifications. #ifdef QDS_USE_PROJECTSTORAGE - void importFinished(const QmlDesigner::TypeName &typeName); + void importFinished(const QmlDesigner::TypeName &typeName, const QString &bundleId); #else - void importFinished(const QmlDesigner::NodeMetaInfo &metaInfo); + void importFinished(const QmlDesigner::NodeMetaInfo &metaInfo, const QString &bundleId); #endif - void unimportFinished(const QmlDesigner::NodeMetaInfo &metaInfo); + void unimportFinished(const QmlDesigner::NodeMetaInfo &metaInfo, const QString &bundleId); + void aboutToUnimport(const TypeName &type, const QString &bundleId); private: void handleImportTimer(); @@ -44,6 +47,7 @@ private: QTimer m_importTimer; int m_importTimerCount = 0; QString m_pendingImport; + QString m_bundleId; bool m_fullReset = false; QHash m_pendingTypes; // }; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp index b0ce0b235a2..7704c164fcd 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp @@ -63,6 +63,11 @@ bool ContentLibraryEffectsModel::isValidIndex(int idx) const return idx > -1 && idx < rowCount(); } +QString ContentLibraryEffectsModel::bundleId() const +{ + return m_bundleId; +} + void ContentLibraryEffectsModel::updateIsEmpty() { bool anyCatVisible = Utils::anyOf(m_bundleCategories, [&](ContentLibraryEffectsCategory *cat) { @@ -88,48 +93,6 @@ QHash ContentLibraryEffectsModel::roleNames() const return roles; } -void ContentLibraryEffectsModel::createImporter() -{ - m_importer = new ContentLibraryBundleImporter(); -#ifdef QDS_USE_PROJECTSTORAGE - connect(m_importer, - &ContentLibraryBundleImporter::importFinished, - this, - [&](const QmlDesigner::TypeName &typeName) { - m_importerRunning = false; - emit importerRunningChanged(); - if (typeName.size()) { - emit bundleItemImported(typeName); - updateImportedState(); - } - }); -#else - connect(m_importer, - &ContentLibraryBundleImporter::importFinished, - this, - [&](const QmlDesigner::NodeMetaInfo &metaInfo) { - m_importerRunning = false; - emit importerRunningChanged(); - if (metaInfo.isValid()) { - emit bundleItemImported(metaInfo); - updateImportedState(); - } - }); -#endif - - connect(m_importer, &ContentLibraryBundleImporter::unimportFinished, this, - [&](const QmlDesigner::NodeMetaInfo &metaInfo) { - Q_UNUSED(metaInfo) - m_importerRunning = false; - emit importerRunningChanged(); - emit bundleItemUnimported(metaInfo); - updateImportedState(); - }); - - resetModel(); - updateIsEmpty(); -} - void ContentLibraryEffectsModel::loadBundle() { if (m_bundleExists || m_probeBundleDir) @@ -172,11 +135,9 @@ void ContentLibraryEffectsModel::loadBundle() } } - QString bundleType = QmlDesignerPlugin::instance()->documentManager() - .generatedComponentUtils().effectsBundleType(); - - // Substitute correct id to avoid issues with old bundles - m_bundleObj["id"] = bundleType.split('.').last(); + auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); + QString bundleType = compUtils.effectsBundleType(); + m_bundleId = compUtils.effectsBundleId(); const QJsonObject catsObj = m_bundleObj.value("categories").toObject(); const QStringList categories = catsObj.keys(); @@ -205,12 +166,13 @@ void ContentLibraryEffectsModel::loadBundle() m_bundleCategories.append(category); } - m_importerSharedFiles.clear(); + m_bundleSharedFiles.clear(); const QJsonArray sharedFilesArr = m_bundleObj.value("sharedFiles").toArray(); for (const QJsonValueConstRef &file : sharedFilesArr) - m_importerSharedFiles.append(file.toString()); + m_bundleSharedFiles.append(file.toString()); - createImporter(); + resetModel(); + updateIsEmpty(); m_bundlePath = bundleDir.path(); m_bundleExists = true; emit bundleExistsChanged(); @@ -226,11 +188,6 @@ bool ContentLibraryEffectsModel::bundleExists() const return m_bundleExists; } -ContentLibraryBundleImporter *ContentLibraryEffectsModel::bundleImporter() const -{ - return m_importer; -} - void ContentLibraryEffectsModel::setSearchText(const QString &searchText) { QString lowerSearchText = searchText.toLower(); @@ -250,20 +207,8 @@ void ContentLibraryEffectsModel::setSearchText(const QString &searchText) updateIsEmpty(); } -void ContentLibraryEffectsModel::updateImportedState() +void ContentLibraryEffectsModel::updateImportedState(const QStringList &importedItems) { - if (!m_importer) - return; - - QString bundleId = m_bundleObj.value("id").toString(); - Utils::FilePath bundlePath = m_importer->resolveBundleImportPath(bundleId); - - QStringList importedItems; - if (bundlePath.exists()) { - importedItems = transform(bundlePath.dirEntries({{"*.qml"}, QDir::Files}), - [](const Utils::FilePath &f) { return f.baseName(); }); - } - bool changed = false; for (ContentLibraryEffectsCategory *cat : std::as_const(m_bundleCategories)) changed |= cat->updateImportedState(importedItems); @@ -297,29 +242,24 @@ void ContentLibraryEffectsModel::resetModel() void ContentLibraryEffectsModel::addInstance(ContentLibraryEffect *bundleItem) { - QString err = m_importer->importComponent(m_bundlePath, bundleItem->type(), bundleItem->qml(), - bundleItem->files() + m_importerSharedFiles); + QString err = m_widget->importer()->importComponent(m_bundlePath, bundleItem->type(), + bundleItem->qml(), + bundleItem->files() + m_bundleSharedFiles); - if (err.isEmpty()) { - m_importerRunning = true; - emit importerRunningChanged(); - } else { + if (err.isEmpty()) + m_widget->setImporterRunning(true); + else qWarning() << __FUNCTION__ << err; - } } void ContentLibraryEffectsModel::removeFromProject(ContentLibraryEffect *bundleItem) { - emit bundleItemAboutToUnimport(bundleItem->type()); + QString err = m_widget->importer()->unimportComponent(bundleItem->type(), bundleItem->qml()); - QString err = m_importer->unimportComponent(bundleItem->type(), bundleItem->qml()); - - if (err.isEmpty()) { - m_importerRunning = true; - emit importerRunningChanged(); - } else { + if (err.isEmpty()) + m_widget->setImporterRunning(true); + else qWarning() << __FUNCTION__ << err; - } } } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h index 8accec8819e..88f60f06b60 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h @@ -3,15 +3,11 @@ #pragma once -#include "nodemetainfo.h" - #include -#include #include namespace QmlDesigner { -class ContentLibraryBundleImporter; class ContentLibraryEffect; class ContentLibraryEffectsCategory; class ContentLibraryWidget; @@ -23,7 +19,6 @@ class ContentLibraryEffectsModel : public QAbstractListModel Q_PROPERTY(bool bundleExists READ bundleExists NOTIFY bundleExistsChanged) Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged) Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged) - Q_PROPERTY(bool importerRunning MEMBER m_importerRunning NOTIFY importerRunningChanged) public: ContentLibraryEffectsModel(ContentLibraryWidget *parent = nullptr); @@ -35,7 +30,7 @@ public: void loadBundle(); void setSearchText(const QString &searchText); - void updateImportedState(); + void updateImportedState(const QStringList &importedItems); void setQuick3DImportVersion(int major, int minor); @@ -46,40 +41,30 @@ public: void resetModel(); void updateIsEmpty(); - ContentLibraryBundleImporter *bundleImporter() const; - Q_INVOKABLE void addInstance(QmlDesigner::ContentLibraryEffect *bundleItem); Q_INVOKABLE void removeFromProject(QmlDesigner::ContentLibraryEffect *bundleItem); + QString bundleId() const; + signals: void isEmptyChanged(); void hasRequiredQuick3DImportChanged(); -#ifdef QDS_USE_PROJECTSTORAGE - void bundleItemImported(const QmlDesigner::TypeName &typeName); -#else - void bundleItemImported(const QmlDesigner::NodeMetaInfo &metaInfo); -#endif - void bundleItemAboutToUnimport(const QmlDesigner::TypeName &type); - void bundleItemUnimported(const QmlDesigner::NodeMetaInfo &metaInfo); - void importerRunningChanged(); void bundleExistsChanged(); private: bool isValidIndex(int idx) const; - void createImporter(); ContentLibraryWidget *m_widget = nullptr; QString m_searchText; QString m_bundlePath; - QStringList m_importerSharedFiles; + QString m_bundleId; + QStringList m_bundleSharedFiles; QList m_bundleCategories; QJsonObject m_bundleObj; - ContentLibraryBundleImporter *m_importer = nullptr; bool m_isEmpty = true; bool m_bundleExists = false; bool m_probeBundleDir = false; - bool m_importerRunning = false; int m_quick3dMajorVersion = -1; int m_quick3dMinorVersion = -1; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp index c6d0f04a14e..7f68ad379d0 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -195,10 +196,9 @@ void ContentLibraryMaterialsModel::downloadSharedFiles(const QDir &targetDir, co extractor->setAlwaysCreateDir(false); extractor->setClearTargetPathContents(false); - QObject::connect(extractor, &FileExtractor::finishedChanged, this, [this, downloader, extractor]() { + QObject::connect(extractor, &FileExtractor::finishedChanged, this, [downloader, extractor]() { downloader->deleteLater(); extractor->deleteLater(); - createImporter(); }); extractor->extract(); @@ -207,46 +207,9 @@ void ContentLibraryMaterialsModel::downloadSharedFiles(const QDir &targetDir, co downloader->start(); } -void ContentLibraryMaterialsModel::createImporter() +QString ContentLibraryMaterialsModel::bundleId() const { - m_importer = new ContentLibraryBundleImporter(); -#ifdef QDS_USE_PROJECTSTORAGE - connect(m_importer, - &ContentLibraryBundleImporter::importFinished, - this, - [&](const QmlDesigner::TypeName &typeName) { - m_importerRunning = false; - emit importerRunningChanged(); - if (typeName.size()) { - emit bundleMaterialImported(typeName); - updateImportedState(); - } - }); -#else - connect(m_importer, - &ContentLibraryBundleImporter::importFinished, - this, - [&](const QmlDesigner::NodeMetaInfo &metaInfo) { - m_importerRunning = false; - emit importerRunningChanged(); - if (metaInfo.isValid()) { - emit bundleMaterialImported(metaInfo); - updateImportedState(); - } - }); -#endif - - connect(m_importer, &ContentLibraryBundleImporter::unimportFinished, this, - [&](const QmlDesigner::NodeMetaInfo &metaInfo) { - Q_UNUSED(metaInfo) - m_importerRunning = false; - emit importerRunningChanged(); - emit bundleMaterialUnimported(metaInfo); - updateImportedState(); - }); - - resetModel(); - updateIsEmpty(); + return m_bundleId; } void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &matBundleDir) @@ -273,11 +236,9 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &matBundleDir) } } - QString bundleType = QmlDesignerPlugin::instance()->documentManager() - .generatedComponentUtils().materialsBundleType(); - - // Substitute correct id to avoid issues with old bundles - m_matBundleObj["id"] = bundleType.split('.').last(); + auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); + QString bundleType = compUtils.materialsBundleType(); + m_bundleId = compUtils.materialsBundleId(); const QJsonObject catsObj = m_matBundleObj.value("categories").toObject(); const QStringList categories = catsObj.keys(); @@ -307,22 +268,22 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &matBundleDir) m_bundleCategories.append(category); } - m_importerSharedFiles.clear(); + m_bundleSharedFiles.clear(); const QJsonArray sharedFilesArr = m_matBundleObj.value("sharedFiles").toArray(); for (const QJsonValueConstRef &file : sharedFilesArr) - m_importerSharedFiles.append(file.toString()); + m_bundleSharedFiles.append(file.toString()); QStringList missingSharedFiles; - for (const QString &s : std::as_const(m_importerSharedFiles)) { + for (const QString &s : std::as_const(m_bundleSharedFiles)) { if (!QFileInfo::exists(matBundleDir.filePath(s))) missingSharedFiles.push_back(s); } if (missingSharedFiles.length() > 0) downloadSharedFiles(matBundleDir, missingSharedFiles); - else - createImporter(); + resetModel(); + updateIsEmpty(); m_matBundleExists = true; emit matBundleExistsChanged(); } @@ -337,11 +298,6 @@ bool ContentLibraryMaterialsModel::matBundleExists() const return m_matBundleExists; } -ContentLibraryBundleImporter *ContentLibraryMaterialsModel::bundleImporter() const -{ - return m_importer; -} - void ContentLibraryMaterialsModel::setSearchText(const QString &searchText) { QString lowerSearchText = searchText.toLower(); @@ -361,20 +317,8 @@ void ContentLibraryMaterialsModel::setSearchText(const QString &searchText) updateIsEmpty(); } -void ContentLibraryMaterialsModel::updateImportedState() +void ContentLibraryMaterialsModel::updateImportedState(const QStringList &importedItems) { - if (!m_importer) - return; - - QString bundleId = m_matBundleObj.value("id").toString(); - Utils::FilePath bundlePath = m_importer->resolveBundleImportPath(bundleId); - - QStringList importedItems; - if (bundlePath.exists()) { - importedItems = transform(bundlePath.dirEntries({{"*.qml"}, QDir::Files}), - [](const Utils::FilePath &f) { return f.baseName(); }); - } - bool changed = false; for (ContentLibraryMaterialsCategory *cat : std::as_const(m_bundleCategories)) changed |= cat->updateImportedState(importedItems); @@ -413,29 +357,23 @@ void ContentLibraryMaterialsModel::applyToSelected(ContentLibraryMaterial *mat, void ContentLibraryMaterialsModel::addToProject(ContentLibraryMaterial *mat) { - QString err = m_importer->importComponent(mat->dirPath(), mat->type(), - mat->qml(), mat->files() + m_importerSharedFiles); + QString err = m_widget->importer()->importComponent(mat->dirPath(), mat->type(), mat->qml(), + mat->files() + m_bundleSharedFiles); - if (err.isEmpty()) { - m_importerRunning = true; - emit importerRunningChanged(); - } else { + if (err.isEmpty()) + m_widget->setImporterRunning(true); + else qWarning() << __FUNCTION__ << err; - } } void ContentLibraryMaterialsModel::removeFromProject(ContentLibraryMaterial *mat) { - emit bundleMaterialAboutToUnimport(mat->type()); + QString err = m_widget->importer()->unimportComponent(mat->type(), mat->qml()); - QString err = m_importer->unimportComponent(mat->type(), mat->qml()); - - if (err.isEmpty()) { - m_importerRunning = true; - emit importerRunningChanged(); - } else { + if (err.isEmpty()) + m_widget->setImporterRunning(true); + else qWarning() << __FUNCTION__ << err; - } } bool ContentLibraryMaterialsModel::hasModelSelection() const diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h index 93a353b6f04..7c7e8809940 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h @@ -3,15 +3,13 @@ #pragma once -#include "nodemetainfo.h" - #include -#include #include +QT_FORWARD_DECLARE_CLASS(QDir) + namespace QmlDesigner { -class ContentLibraryBundleImporter; class ContentLibraryMaterial; class ContentLibraryMaterialsCategory; class ContentLibraryWidget; @@ -24,7 +22,6 @@ class ContentLibraryMaterialsModel : public QAbstractListModel Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged) Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged) Q_PROPERTY(bool hasModelSelection READ hasModelSelection NOTIFY hasModelSelectionChanged) - Q_PROPERTY(bool importerRunning MEMBER m_importerRunning NOTIFY importerRunningChanged) public: ContentLibraryMaterialsModel(ContentLibraryWidget *parent = nullptr); @@ -35,7 +32,7 @@ public: QHash roleNames() const override; void setSearchText(const QString &searchText); - void updateImportedState(); + void updateImportedState(const QStringList &importedItems); void setQuick3DImportVersion(int major, int minor); @@ -50,26 +47,18 @@ public: void updateIsEmpty(); void loadBundle(); - ContentLibraryBundleImporter *bundleImporter() const; - Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); Q_INVOKABLE void addToProject(QmlDesigner::ContentLibraryMaterial *mat); Q_INVOKABLE void removeFromProject(QmlDesigner::ContentLibraryMaterial *mat); + QString bundleId() const; + signals: void isEmptyChanged(); void hasRequiredQuick3DImportChanged(); void hasModelSelectionChanged(); void materialVisibleChanged(); void applyToSelectedTriggered(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); -#ifdef QDS_USE_PROJECTSTORAGE - void bundleMaterialImported(const QmlDesigner::TypeName &typeName); -#else - void bundleMaterialImported(const QmlDesigner::NodeMetaInfo &metaInfo); -#endif - void bundleMaterialAboutToUnimport(const QmlDesigner::TypeName &type); - void bundleMaterialUnimported(const QmlDesigner::NodeMetaInfo &metaInfo); - void importerRunningChanged(); void matBundleExistsChanged(); private: @@ -78,26 +67,23 @@ private: bool fetchBundleMetadata(const QDir &bundleDir); bool isValidIndex(int idx) const; void downloadSharedFiles(const QDir &targetDir, const QStringList &files); - void createImporter(); ContentLibraryWidget *m_widget = nullptr; QString m_searchText; + QString m_bundleId; + QStringList m_bundleSharedFiles; QList m_bundleCategories; QJsonObject m_matBundleObj; - ContentLibraryBundleImporter *m_importer = nullptr; bool m_isEmpty = true; bool m_matBundleExists = false; bool m_hasModelSelection = false; - bool m_importerRunning = false; int m_quick3dMajorVersion = -1; int m_quick3dMinorVersion = -1; QString m_downloadPath; QString m_baseUrl; - - QStringList m_importerSharedFiles; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp index fcd1096ac11..db4817ebb67 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp @@ -14,15 +14,11 @@ #include #include -#include #include -#include #include #include #include -#include -#include #include namespace QmlDesigner { @@ -223,48 +219,6 @@ QHash ContentLibraryUserModel::roleNames() const return roles; } -void ContentLibraryUserModel::createImporter() -{ - m_importer = new ContentLibraryBundleImporter(); -#ifdef QDS_USE_PROJECTSTORAGE - connect(m_importer, - &ContentLibraryBundleImporter::importFinished, - this, - [&](const QmlDesigner::TypeName &typeName) { - m_importerRunning = false; - emit importerRunningChanged(); - if (typeName.size()) { - emit bundleMaterialImported(typeName); - updateImportedState(); - } - }); -#else - connect(m_importer, - &ContentLibraryBundleImporter::importFinished, - this, - [&](const QmlDesigner::NodeMetaInfo &metaInfo) { - m_importerRunning = false; - emit importerRunningChanged(); - if (metaInfo.isValid()) { - emit bundleMaterialImported(metaInfo); - updateImportedState(); - } - }); -#endif - - connect(m_importer, &ContentLibraryBundleImporter::unimportFinished, this, - [&](const QmlDesigner::NodeMetaInfo &metaInfo) { - Q_UNUSED(metaInfo) - m_importerRunning = false; - emit importerRunningChanged(); - emit bundleMaterialUnimported(metaInfo); - updateImportedState(); - }); - - resetModel(); - updateIsEmpty(); -} - QJsonObject &ContentLibraryUserModel::bundleJsonObjectRef() { return m_bundleObj; @@ -304,10 +258,8 @@ void ContentLibraryUserModel::loadMaterialBundle() } } - m_bundleIdMaterial = "UserMaterials"; - - // Substitute correct id to avoid issues with old bundles - m_bundleObj["id"] = m_bundleIdMaterial; + auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); + m_bundleObj["id"] = compUtils.userMaterialsBundleId(); // parse materials const QJsonObject matsObj = m_bundleObj.value("materials").toObject(); @@ -331,12 +283,10 @@ void ContentLibraryUserModel::loadMaterialBundle() m_userMaterials.append(userMat); } - m_importerSharedFiles.clear(); + m_bundleSharedFiles.clear(); const QJsonArray sharedFilesArr = m_bundleObj.value("sharedFiles").toArray(); for (const QJsonValueConstRef &file : sharedFilesArr) - m_importerSharedFiles.append(file.toString()); - - createImporter(); + m_bundleSharedFiles.append(file.toString()); m_matBundleExists = true; emit matBundleExistsChanged(); @@ -378,11 +328,6 @@ bool ContentLibraryUserModel::matBundleExists() const return m_matBundleExists; } -ContentLibraryBundleImporter *ContentLibraryUserModel::bundleImporter() const -{ - return m_importer; -} - void ContentLibraryUserModel::setSearchText(const QString &searchText) { QString lowerSearchText = searchText.toLower(); @@ -398,20 +343,8 @@ void ContentLibraryUserModel::setSearchText(const QString &searchText) updateIsEmpty(); } -void ContentLibraryUserModel::updateImportedState() +void ContentLibraryUserModel::updateImportedState(const QStringList &importedItems) { - if (!m_importer) - return; - - QString bundleId = m_bundleObj.value("id").toString(); - Utils::FilePath bundlePath = m_importer->resolveBundleImportPath(bundleId); - - QStringList importedItems; - if (bundlePath.exists()) { - importedItems = transform(bundlePath.dirEntries({{"*.qml"}, QDir::Files}), - [](const Utils::FilePath &f) { return f.baseName(); }); - } - bool changed = false; for (ContentLibraryMaterial *mat : std::as_const(m_userMaterials)) changed |= mat->setImported(importedItems.contains(mat->qml().chopped(4))); @@ -452,29 +385,23 @@ void ContentLibraryUserModel::applyToSelected(ContentLibraryMaterial *mat, bool void ContentLibraryUserModel::addToProject(ContentLibraryMaterial *mat) { - QString err = m_importer->importComponent(mat->dirPath(), mat->type(), mat->qml(), - mat->files() + m_importerSharedFiles); + QString err = m_widget->importer()->importComponent(mat->dirPath(), mat->type(), mat->qml(), + mat->files() + m_bundleSharedFiles); - if (err.isEmpty()) { - m_importerRunning = true; - emit importerRunningChanged(); - } else { + if (err.isEmpty()) + m_widget->setImporterRunning(true); + else qWarning() << __FUNCTION__ << err; - } } void ContentLibraryUserModel::removeFromProject(ContentLibraryMaterial *mat) { - emit bundleMaterialAboutToUnimport(mat->type()); + QString err = m_widget->importer()->unimportComponent(mat->type(), mat->qml()); - QString err = m_importer->unimportComponent(mat->type(), mat->qml()); - - if (err.isEmpty()) { - m_importerRunning = true; - emit importerRunningChanged(); - } else { + if (err.isEmpty()) + m_widget->setImporterRunning(true); + else qWarning() << __FUNCTION__ << err; - } } bool ContentLibraryUserModel::hasModelSelection() const diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h index e4bf030c57c..b11cd343c88 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h @@ -12,7 +12,6 @@ QT_FORWARD_DECLARE_CLASS(QUrl) namespace QmlDesigner { -class ContentLibraryBundleImporter; class ContentLibraryEffect; class ContentLibraryMaterial; class ContentLibraryTexture; @@ -27,7 +26,6 @@ class ContentLibraryUserModel : public QAbstractListModel Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged) Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged) Q_PROPERTY(bool hasModelSelection READ hasModelSelection NOTIFY hasModelSelectionChanged) - Q_PROPERTY(bool importerRunning MEMBER m_importerRunning NOTIFY importerRunningChanged) Q_PROPERTY(QList userMaterials MEMBER m_userMaterials NOTIFY userMaterialsChanged) Q_PROPERTY(QList userTextures MEMBER m_userTextures NOTIFY userTexturesChanged) Q_PROPERTY(QList user3DItems MEMBER m_user3DItems NOTIFY user3DItemsChanged) @@ -41,7 +39,7 @@ public: QHash roleNames() const override; void setSearchText(const QString &searchText); - void updateImportedState(); + void updateImportedState(const QStringList &importedItems); QPair getUniqueLibMaterialNameAndQml(const QString &matName) const; TypeName qmlToModule(const QString &qmlName) const; @@ -67,8 +65,6 @@ public: void loadMaterialBundle(); void loadTextureBundle(); - ContentLibraryBundleImporter *bundleImporter() const; - Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); Q_INVOKABLE void addToProject(QmlDesigner::ContentLibraryMaterial *mat); Q_INVOKABLE void removeFromProject(QmlDesigner::ContentLibraryMaterial *mat); @@ -86,23 +82,16 @@ signals: void applyToSelectedTriggered(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); -#ifdef QDS_USE_PROJECTSTORAGE - void bundleMaterialImported(const QmlDesigner::TypeName &typeName); -#else - void bundleMaterialImported(const QmlDesigner::NodeMetaInfo &metaInfo); -#endif - void bundleMaterialAboutToUnimport(const QmlDesigner::TypeName &type); - void bundleMaterialUnimported(const QmlDesigner::NodeMetaInfo &metaInfo); - void importerRunningChanged(); + void matBundleExistsChanged(); private: bool isValidIndex(int idx) const; - void createImporter(); ContentLibraryWidget *m_widget = nullptr; QString m_searchText; QString m_bundleIdMaterial; + QStringList m_bundleSharedFiles; QList m_userMaterials; QList m_userTextures; @@ -111,19 +100,14 @@ private: QStringList m_userCategories; QJsonObject m_bundleObj; - ContentLibraryBundleImporter *m_importer = nullptr; bool m_isEmpty = true; bool m_matBundleExists = false; bool m_hasModelSelection = false; - bool m_importerRunning = false; int m_quick3dMajorVersion = -1; int m_quick3dMinorVersion = -1; - QString m_importerBundlePath; - QString m_importerBundleId; - QStringList m_importerSharedFiles; enum Roles { NameRole = Qt::UserRole + 1, VisibleRole, ItemsRole }; }; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp index 52c28f41b64..49b1a7c6a02 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp @@ -3,8 +3,6 @@ #include "contentlibraryview.h" -#include "asset.h" -#include "bindingproperty.h" #include "contentlibrarybundleimporter.h" #include "contentlibraryeffect.h" #include "contentlibraryeffectsmodel.h" @@ -14,19 +12,20 @@ #include "contentlibrarytexturesmodel.h" #include "contentlibraryusermodel.h" #include "contentlibrarywidget.h" -#include "documentmanager.h" -#include "externaldependenciesinterface.h" -#include "nodelistproperty.h" -#include "qmldesignerconstants.h" -#include "qmlobjectnode.h" -#include "variantproperty.h" -#include "utils3d.h" +#include +#include #include -#include - -#include +#include #include +#include +#include +#include +#include +#include +#include +#include + #include #ifndef QMLDESIGNER_TEST @@ -90,65 +89,61 @@ WidgetInfo ContentLibraryView::widgetInfo() m_widget->environmentsModel()->setHasSceneEnv(sceneEnvExists); }); - ContentLibraryMaterialsModel *materialsModel = m_widget->materialsModel().data(); - - connect(materialsModel, + connect(m_widget->materialsModel(), &ContentLibraryMaterialsModel::applyToSelectedTriggered, this, [&](ContentLibraryMaterial *bundleMat, bool add) { - if (m_selectedModels.isEmpty()) - return; + if (m_selectedModels.isEmpty()) + return; - m_bundleMaterialTargets = m_selectedModels; - m_bundleMaterialAddToSelected = add; + m_bundleMaterialTargets = m_selectedModels; + m_bundleMaterialAddToSelected = add; - ModelNode defaultMat = getBundleMaterialDefaultInstance(bundleMat->type()); - if (defaultMat.isValid()) - applyBundleMaterialToDropTarget(defaultMat); - else - m_widget->materialsModel()->addToProject(bundleMat); - }); - -#ifdef QDS_USE_PROJECTSTORAGE - connect(materialsModel, - &ContentLibraryMaterialsModel::bundleMaterialImported, - this, - [&](const QmlDesigner::TypeName &typeName) { - applyBundleMaterialToDropTarget({}, typeName); - }); -#else - connect(materialsModel, - &ContentLibraryMaterialsModel::bundleMaterialImported, - this, - [&](const QmlDesigner::NodeMetaInfo &metaInfo) { - applyBundleMaterialToDropTarget({}, metaInfo); - }); -#endif - - connect(materialsModel, &ContentLibraryMaterialsModel::bundleMaterialAboutToUnimport, this, - [&] (const QmlDesigner::TypeName &type) { - // delete instances of the bundle material that is about to be unimported - executeInTransaction("ContentLibraryView::widgetInfo", [&] { - ModelNode matLib = Utils3D::materialLibraryNode(this); - if (!matLib.isValid()) - return; - - Utils::reverseForeach(matLib.directSubModelNodes(), [&](const ModelNode &mat) { - if (mat.isValid() && mat.type() == type) - QmlObjectNode(mat).destroy(); - }); - }); + ModelNode defaultMat = getBundleMaterialDefaultInstance(bundleMat->type()); + if (defaultMat.isValid()) + applyBundleMaterialToDropTarget(defaultMat); + else + m_widget->materialsModel()->addToProject(bundleMat); }); - ContentLibraryEffectsModel *effectsModel = m_widget->effectsModel().data(); - -#ifdef QDS_USE_PROJECTSTORAGE - connect(effectsModel, - &ContentLibraryEffectsModel::bundleItemImported, + connect(m_widget->userModel(), + &ContentLibraryUserModel::applyToSelectedTriggered, this, - [&](const QmlDesigner::TypeName &typeName) { - QTC_ASSERT(typeName.size(), return); + [&](ContentLibraryMaterial *bundleMat, bool add) { + if (m_selectedModels.isEmpty()) + return; + m_bundleMaterialTargets = m_selectedModels; + m_bundleMaterialAddToSelected = add; + + ModelNode defaultMat = getBundleMaterialDefaultInstance(bundleMat->type()); + if (defaultMat.isValid()) + applyBundleMaterialToDropTarget(defaultMat); + else + m_widget->userModel()->addToProject(bundleMat); + }); + + connectImporter(); + } + + return createWidgetInfo(m_widget.data(), + "ContentLibrary", + WidgetInfo::LeftPane, + 0, + tr("Content Library")); +} + +void ContentLibraryView::connectImporter() +{ +#ifdef QDS_USE_PROJECTSTORAGE + connect(m_widget->importer(), + &ContentLibraryBundleImporter::importFinished, + this, + [&](const QmlDesigner::TypeName &typeName, const QString &bundleId) { + QTC_ASSERT(typeName.size(), return); + if (isMaterialBundle(bundleId)) { + applyBundleMaterialToDropTarget({}, typeName); + } else if (isEffectBundle(bundleId)) { if (!m_bundleEffectTarget) m_bundleEffectTarget = Utils3D::active3DSceneNode(this); @@ -165,20 +160,23 @@ WidgetInfo ContentLibraryView::widgetInfo() m_bundleEffectTarget = {}; m_bundleEffectPos = {}; - }); + } + }); #else - connect(effectsModel, - &ContentLibraryEffectsModel::bundleItemImported, - this, - [&](const QmlDesigner::NodeMetaInfo &metaInfo) { - QTC_ASSERT(metaInfo.isValid(), return); - + connect(m_widget->importer(), + &ContentLibraryBundleImporter::importFinished, + this, + [&](const QmlDesigner::NodeMetaInfo &metaInfo, const QString &bundleId) { + QTC_ASSERT(metaInfo.isValid(), return); + if (isMaterialBundle(bundleId)) { + applyBundleMaterialToDropTarget({}, metaInfo); + } else if (isEffectBundle(bundleId)) { if (!m_bundleEffectTarget) m_bundleEffectTarget = Utils3D::active3DSceneNode(this); QTC_ASSERT(m_bundleEffectTarget, return); - executeInTransaction("ContentLibraryView::widgetInfo", [&] { + executeInTransaction("ContentLibraryView::connectImporter", [&] { QVector3D pos = m_bundleEffectPos.value(); ModelNode newEffNode = createModelNode(metaInfo.typeName(), metaInfo.majorVersion(), @@ -193,80 +191,46 @@ WidgetInfo ContentLibraryView::widgetInfo() m_bundleEffectTarget = {}; m_bundleEffectPos = {}; - }); + } + }); #endif - connect(effectsModel, &ContentLibraryEffectsModel::bundleItemAboutToUnimport, this, - [&] (const QmlDesigner::TypeName &type) { - // delete instances of the bundle effect that is about to be unimported - executeInTransaction("ContentLibraryView::widgetInfo", [&] { - NodeMetaInfo metaInfo = model()->metaInfo(type); - QList effects = allModelNodesOfType(metaInfo); - for (ModelNode &eff : effects) - eff.destroy(); - }); - }); - connectUserBundle(); - } - - return createWidgetInfo(m_widget.data(), - "ContentLibrary", - WidgetInfo::LeftPane, - 0, - tr("Content Library")); -} - -void ContentLibraryView::connectUserBundle() -{ - ContentLibraryUserModel *userModel = m_widget->userModel().data(); - - connect(userModel, - &ContentLibraryUserModel::applyToSelectedTriggered, - this, - [&](ContentLibraryMaterial *bundleMat, bool add) { - if (m_selectedModels.isEmpty()) + connect(m_widget->importer(), &ContentLibraryBundleImporter::aboutToUnimport, this, + [&] (const QmlDesigner::TypeName &type, const QString &bundleId) { + if (isMaterialBundle(bundleId)) { + // delete instances of the bundle material that is about to be unimported + executeInTransaction("ContentLibraryView::connectImporter", [&] { + ModelNode matLib = Utils3D::materialLibraryNode(this); + if (!matLib.isValid()) return; - m_bundleMaterialTargets = m_selectedModels; - m_bundleMaterialAddToSelected = add; - - ModelNode defaultMat = getBundleMaterialDefaultInstance(bundleMat->type()); - if (defaultMat.isValid()) - applyBundleMaterialToDropTarget(defaultMat); - else - m_widget->userModel()->addToProject(bundleMat); - }); - -#ifdef QDS_USE_PROJECTSTORAGE - connect(userModel, - &ContentLibraryUserModel::bundleMaterialImported, - this, - [&](const QmlDesigner::TypeName &typeName) { - applyBundleMaterialToDropTarget({}, typeName); - }); -#else - connect(userModel, - &ContentLibraryUserModel::bundleMaterialImported, - this, - [&](const QmlDesigner::NodeMetaInfo &metaInfo) { - applyBundleMaterialToDropTarget({}, metaInfo); - }); -#endif - - connect(userModel, &ContentLibraryUserModel::bundleMaterialAboutToUnimport, this, - [&] (const QmlDesigner::TypeName &type) { - // delete instances of the bundle material that is about to be unimported - executeInTransaction("ContentLibraryView::connectUserModel", [&] { - ModelNode matLib = Utils3D::materialLibraryNode(this); - if (!matLib.isValid()) - return; - - Utils::reverseForeach(matLib.directSubModelNodes(), [&](const ModelNode &mat) { - if (mat.isValid() && mat.type() == type) - QmlObjectNode(mat).destroy(); - }); + Utils::reverseForeach(matLib.directSubModelNodes(), [&](const ModelNode &mat) { + if (mat.isValid() && mat.type() == type) + QmlObjectNode(mat).destroy(); }); }); + } else if (isEffectBundle(bundleId)) { + // delete instances of the bundle effect that is about to be unimported + executeInTransaction("ContentLibraryView::connectImporter", [&] { + NodeMetaInfo metaInfo = model()->metaInfo(type); + QList effects = allModelNodesOfType(metaInfo); + for (ModelNode &eff : effects) + eff.destroy(); + }); + } + }); +} + +bool ContentLibraryView::isMaterialBundle(const QString &bundleId) const +{ + auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); + return bundleId == compUtils.materialsBundleId() || bundleId == compUtils.userMaterialsBundleId(); +} + +bool ContentLibraryView::isEffectBundle(const QString &bundleId) const +{ + auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); + return bundleId == compUtils.effectsBundleId() || bundleId == compUtils.userEffectsBundleId(); } void ContentLibraryView::modelAttached(Model *model) @@ -294,9 +258,10 @@ void ContentLibraryView::modelAttached(Model *model) m_widget->userModel()->loadMaterialBundle(); m_widget->userModel()->loadTextureBundle(); - m_widget->materialsModel()->updateImportedState(); - m_widget->effectsModel()->updateImportedState(); - m_widget->userModel()->updateImportedState(); + auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); + m_widget->updateImportedState(compUtils.materialsBundleId()); + m_widget->updateImportedState(compUtils.effectsBundleId()); + m_widget->updateImportedState(compUtils.userMaterialsBundleId()); } void ContentLibraryView::modelAboutToBeDetached(Model *model) diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h index 4ff2a5db8fd..3c80193478f 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h @@ -3,9 +3,9 @@ #pragma once -#include "abstractview.h" -#include "createtexture.h" -#include "nodemetainfo.h" +#include +#include +#include #include #include @@ -48,7 +48,9 @@ public: const QVariant &data) override; private: - void connectUserBundle(); + void connectImporter(); + bool isMaterialBundle(const QString &bundleId) const; + bool isEffectBundle(const QString &bundleId) const; void active3DSceneChanged(qint32 sceneId); void updateBundlesQuick3DVersion(); void addLibMaterial(const ModelNode &mat, const QPixmap &icon); diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp index 9375d43fd4f..0c680afa76f 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp @@ -3,6 +3,7 @@ #include "contentlibrarywidget.h" +#include "contentlibrarybundleimporter.h" #include "contentlibraryeffect.h" #include "contentlibraryeffectsmodel.h" #include "contentlibrarymaterial.h" @@ -18,6 +19,7 @@ #include #include +#include #include #include @@ -40,7 +42,6 @@ #include #include #include -#include #include namespace QmlDesigner { @@ -177,6 +178,65 @@ ContentLibraryWidget::ContentLibraryWidget() {"userModel", QVariant::fromValue(m_userModel.data())}}); reloadQmlSource(); + createImporter(); +} + +void ContentLibraryWidget::createImporter() +{ + m_importer = new ContentLibraryBundleImporter(); +#ifdef QDS_USE_PROJECTSTORAGE + connect(m_importer, + &ContentLibraryBundleImporter::importFinished, + this, + [&](const QmlDesigner::TypeName &typeName, const QString &bundleId) { + setImporterRunning(false); + if (typeName.size()) + updateImportedState(bundleId); + }); +#else + connect(m_importer, + &ContentLibraryBundleImporter::importFinished, + this, + [&](const QmlDesigner::NodeMetaInfo &metaInfo, const QString &bundleId) { + setImporterRunning(false); + if (metaInfo.isValid()) + updateImportedState(bundleId); + }); +#endif + + connect(m_importer, &ContentLibraryBundleImporter::unimportFinished, this, + [&](const QmlDesigner::NodeMetaInfo &metaInfo, const QString &bundleId) { + Q_UNUSED(metaInfo) + setImporterRunning(false); + updateImportedState(bundleId); + }); +} + +void ContentLibraryWidget::updateImportedState(const QString &bundleId) +{ + if (!m_importer) + return; + + Utils::FilePath bundlePath = m_importer->resolveBundleImportPath(bundleId); + + QStringList importedItems; + if (bundlePath.exists()) { + importedItems = transform(bundlePath.dirEntries({{"*.qml"}, QDir::Files}), + [](const Utils::FilePath &f) { return f.baseName(); }); + } + + auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); + if (bundleId == compUtils.materialsBundleId()) + m_materialsModel->updateImportedState(importedItems); + else if (bundleId == compUtils.effectsBundleId()) + m_effectsModel->updateImportedState(importedItems); + else if (bundleId == compUtils.userMaterialsBundleId()) + m_userModel->updateImportedState(importedItems); +} + +ContentLibraryBundleImporter *ContentLibraryWidget::importer() const +{ + return m_importer; } QVariantMap ContentLibraryWidget::readTextureBundleJson() @@ -683,6 +743,20 @@ void ContentLibraryWidget::setIsQt6Project(bool b) emit isQt6ProjectChanged(); } +bool ContentLibraryWidget::importerRunning() const +{ + return m_importerRunning; +} + +void ContentLibraryWidget::setImporterRunning(bool b) +{ + if (m_importerRunning == b) + return; + + m_importerRunning = b; + emit importerRunningChanged(); +} + void ContentLibraryWidget::reloadQmlSource() { const QString materialBrowserQmlPath = qmlSourcesPath() + "/ContentLibrary.qml"; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h index c4d51d0362b..75339f02491 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h @@ -4,7 +4,7 @@ #pragma once #include "createtexture.h" - +#include #include #include @@ -18,6 +18,7 @@ class StudioQuickWidget; namespace QmlDesigner { +class ContentLibraryBundleImporter; class ContentLibraryEffect; class ContentLibraryEffectsModel; class ContentLibraryMaterial; @@ -25,6 +26,7 @@ class ContentLibraryMaterialsModel; class ContentLibraryTexture; class ContentLibraryTexturesModel; class ContentLibraryUserModel; +class NodeMetaInfo; class ContentLibraryWidget : public QFrame { @@ -34,6 +36,7 @@ class ContentLibraryWidget : public QFrame Q_PROPERTY(bool hasMaterialLibrary READ hasMaterialLibrary NOTIFY hasMaterialLibraryChanged) Q_PROPERTY(bool hasActive3DScene READ hasActive3DScene WRITE setHasActive3DScene NOTIFY hasActive3DSceneChanged) Q_PROPERTY(bool isQt6Project READ isQt6Project NOTIFY isQt6ProjectChanged) + Q_PROPERTY(bool importerRunning READ importerRunning WRITE setImporterRunning NOTIFY importerRunningChanged) // Needed for a workaround for a bug where after drag-n-dropping an item, the ScrollView scrolls to a random position Q_PROPERTY(bool isDragging MEMBER m_isDragging NOTIFY isDraggingChanged) @@ -58,9 +61,13 @@ public: bool isQt6Project() const; void setIsQt6Project(bool b); + bool importerRunning() const; + void setImporterRunning(bool b); + Q_INVOKABLE void handleSearchFilterChanged(const QString &filterText); void setMaterialsModel(QPointer newMaterialsModel); + void updateImportedState(const QString &bundleId); QPointer materialsModel() const; QPointer texturesModel() const; @@ -80,6 +87,8 @@ public: QSize sizeHint() const override; + ContentLibraryBundleImporter *importer() const; + signals: void bundleEffectDragStarted(QmlDesigner::ContentLibraryEffect *bundleEff); void bundleMaterialDragStarted(QmlDesigner::ContentLibraryMaterial *bundleMat); @@ -91,6 +100,7 @@ signals: void hasActive3DSceneChanged(); void isDraggingChanged(); void isQt6ProjectChanged(); + void importerRunningChanged(); protected: bool eventFilter(QObject *obj, QEvent *event) override; @@ -110,6 +120,7 @@ private: const QString &existingMetaFile, const QString downloadedMetaFile); QStringList saveNewTextures(const QDir &bundleDir, const QStringList &newFiles); void populateTextureBundleModels(); + void createImporter(); QScopedPointer m_quickWidget; QPointer m_materialsModel; @@ -118,6 +129,8 @@ private: QPointer m_effectsModel; QPointer m_userModel; + ContentLibraryBundleImporter *m_importer = nullptr; + QShortcut *m_qmlSourceUpdateShortcut = nullptr; QString m_filterText; @@ -132,6 +145,7 @@ private: bool m_hasQuick3DImport = false; bool m_isDragging = false; bool m_isQt6Project = false; + bool m_importerRunning = false; QString m_textureBundleUrl; QString m_bundlePath; }; 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";