From de5a3b696d33b6f1663e1a73910e6e9149462d64 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Tue, 11 Jun 2024 12:05:26 +0300 Subject: [PATCH] QmlDesigner: Refactor out ContentLibraryMaterial from user bundle Some tweaks and refactoring to get rid of ContentLibraryMaterial in the user section of the content library. The end goal is to unify the code for handling all Qml components in the user section (materials, 3d components, effects, 2D components. etc). Change-Id: I99d4fb64dae0b52265994ce478525e574e4bc658 Reviewed-by: Ali Kianian Reviewed-by: Miikka Heikkinen --- .../ContentLibraryItem.qml | 27 ++++- .../ContentLibraryMaterial.qml | 27 +++-- .../ContentLibraryUserView.qml | 4 +- .../contentlibraryeffectsmodel.cpp | 7 +- .../contentlibrary/contentlibraryitem.cpp | 11 +- .../contentlibrary/contentlibraryitem.h | 9 +- .../contentlibrary/contentlibrarymaterial.cpp | 23 +--- .../contentlibrary/contentlibrarymaterial.h | 12 +-- .../contentlibrarymaterialsmodel.cpp | 100 +++++++++--------- .../contentlibrarymaterialsmodel.h | 19 ++-- .../contentlibraryusermodel.cpp | 94 ++++++---------- .../contentlibrary/contentlibraryusermodel.h | 11 +- .../contentlibrary/contentlibraryview.cpp | 2 +- .../contentlibrary/contentlibrarywidget.cpp | 2 +- 14 files changed, 161 insertions(+), 187 deletions(-) diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryItem.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryItem.qml index e6e5cd05c30..4eb05141221 100644 --- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryItem.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryItem.qml @@ -2,9 +2,8 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 import QtQuick -import QtQuick.Layouts -import HelperWidgets import QtQuick.Controls +import HelperWidgets as HelperWidgets import StudioTheme as StudioTheme import ContentLibraryBackend @@ -12,18 +11,20 @@ Item { id: root signal showContextMenu() + signal addToProject() visible: modelData.bundleItemVisible MouseArea { id: mouseArea + enabled: !ContentLibraryBackend.rootView.importerRunning hoverEnabled: true anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton onPressed: (mouse) => { - if (mouse.button === Qt.LeftButton && !ContentLibraryBackend.rootView.importerRunning) + if (mouse.button === Qt.LeftButton) ContentLibraryBackend.rootView.startDragItem(modelData, mapToGlobal(mouse.x, mouse.y)) else if (mouse.button === Qt.RightButton) root.showContextMenu() @@ -67,6 +68,26 @@ Item { hoverEnabled: true } } + + HelperWidgets.IconButton { + id: addToProjectButton + + icon: StudioTheme.Constants.plus + tooltip: qsTr("Add an instance to project") + buttonSize: 22 + property color c: "white" + normalColor: Qt.hsla(c.hslHue, c.hslSaturation, c.hslLightness, .2) + hoverColor: Qt.hsla(c.hslHue, c.hslSaturation, c.hslLightness, .3) + pressColor: Qt.hsla(c.hslHue, c.hslSaturation, c.hslLightness, .4) + anchors.right: img.right + anchors.bottom: img.bottom + enabled: !ContentLibraryBackend.rootView.importerRunning + visible: containsMouse || mouseArea.containsMouse + + onClicked: { + root.addToProject() + } + } } Text { diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml index 20ba17d8041..1136f653eae 100644 --- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml @@ -3,8 +3,7 @@ import QtQuick import QtQuick.Controls -import QtQuick.Layouts -import HelperWidgets +import HelperWidgets as HelperWidgets import StudioTheme as StudioTheme import ContentLibraryBackend import WebFetcher @@ -12,9 +11,9 @@ import WebFetcher Item { id: root - // Download states: "" (ie default, not downloaded), "unavailable", "downloading", "downloaded", - // "failed" - property string downloadState: modelData.isDownloaded() ? "downloaded" : "" + // Download states: "" (exists not downloaded), "unavailable", "downloading", "downloaded", "failed" + property string downloadState: ContentLibraryBackend.materialsModel.isMaterialDownloaded(modelData) + ? "downloaded" : "" signal showContextMenu() signal addToProject() @@ -24,18 +23,16 @@ Item { MouseArea { id: mouseArea - enabled: root.downloadState !== "downloading" + enabled: !ContentLibraryBackend.rootView.importerRunning && root.downloadState == "downloaded" hoverEnabled: true anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton onPressed: (mouse) => { - if (mouse.button === Qt.LeftButton && !ContentLibraryBackend.rootView.importerRunning) { - if (root.downloadState === "downloaded") - ContentLibraryBackend.rootView.startDragMaterial(modelData, mapToGlobal(mouse.x, mouse.y)) - } else if (mouse.button === Qt.RightButton && root.downloadState === "downloaded") { + if (mouse.button === Qt.LeftButton) + ContentLibraryBackend.rootView.startDragMaterial(modelData, mapToGlobal(mouse.x, mouse.y)) + else if (mouse.button === Qt.RightButton) root.showContextMenu() - } } } @@ -87,7 +84,7 @@ Item { } } - IconButton { + HelperWidgets.IconButton { icon: StudioTheme.Constants.plus tooltip: qsTr("Add an instance to project") buttonSize: 22 @@ -106,7 +103,7 @@ Item { } } - IconButton { + HelperWidgets.IconButton { id: downloadIcon icon: root.downloadState === "unavailable" ? StudioTheme.Constants.downloadUnavailable @@ -181,10 +178,10 @@ Item { MultiFileDownloader { id: downloader - baseUrl: modelData.bundleMaterialBaseWebUrl + baseUrl: ContentLibraryBackend.materialsModel.baseWebUrl files: modelData.bundleMaterialFiles - targetDirPath: modelData.bundleMaterialDirPath + targetDirPath: ContentLibraryBackend.materialsModel.bundlePath onDownloadStarting: { root.downloadState = "downloading" diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml index cced9e5f095..dd73c27c4b8 100644 --- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml @@ -106,7 +106,7 @@ HelperWidgets.ScrollView { DelegateChoice { roleValue: "material" - ContentLibraryMaterial { + ContentLibraryItem { width: root.cellWidth height: root.cellHeight @@ -124,7 +124,7 @@ HelperWidgets.ScrollView { } } DelegateChoice { - roleValue: "item" + roleValue: "3d" delegate: ContentLibraryItem { width: root.cellWidth height: root.cellHeight diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp index e0fe2b6c54e..d8bcdf5b4a2 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp @@ -171,17 +171,14 @@ void ContentLibraryEffectsModel::loadBundle() TypeName type = QLatin1String("%1.%2") .arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml - auto bundleItem = new ContentLibraryItem(category, itemName, qml, type, icon, files); + auto bundleItem = new ContentLibraryItem(category, itemName, qml, type, icon, files, "effect"); category->addBundleItem(bundleItem); } m_bundleCategories.append(category); } - m_bundleSharedFiles.clear(); - const QJsonArray sharedFilesArr = m_bundleObj.value("sharedFiles").toArray(); - for (const QJsonValueConstRef &file : sharedFilesArr) - m_bundleSharedFiles.append(file.toString()); + m_bundleSharedFiles = m_bundleObj.value("sharedFiles").toVariant().toStringList(); m_bundlePath = bundleDir.path(); m_bundleExists = true; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.cpp index 38fb69abbc2..6ab26885d4f 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.cpp @@ -10,8 +10,10 @@ ContentLibraryItem::ContentLibraryItem(QObject *parent, const QString &qml, const TypeName &type, const QUrl &icon, - const QStringList &files) - : QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files) + const QStringList &files, + const QString &itemType) + : QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files), + m_itemType(itemType) { m_allFiles = m_files; m_allFiles.push_back(m_qml); @@ -73,4 +75,9 @@ QStringList ContentLibraryItem::allFiles() const return m_allFiles; } +QString ContentLibraryItem::itemType() const +{ + return m_itemType; +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.h index bdf87367281..b2610953ae8 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.h @@ -19,7 +19,7 @@ class ContentLibraryItem : public QObject Q_PROPERTY(QStringList bundleItemFiles READ allFiles CONSTANT) Q_PROPERTY(bool bundleItemVisible MEMBER m_visible NOTIFY itemVisibleChanged) Q_PROPERTY(bool bundleItemImported READ imported WRITE setImported NOTIFY itemImportedChanged) - Q_PROPERTY(QString itemType MEMBER m_itemType CONSTANT) + Q_PROPERTY(QString itemType READ itemType CONSTANT) public: ContentLibraryItem(QObject *parent, @@ -27,7 +27,8 @@ public: const QString &qml, const TypeName &type, const QUrl &icon, - const QStringList &files); + const QStringList &files, + const QString &itemType); bool filter(const QString &searchText); @@ -37,6 +38,8 @@ public: QStringList files() const; bool visible() const; + QString itemType() const; + bool setImported(bool imported); bool imported() const; QStringList allFiles() const; @@ -56,7 +59,7 @@ private: bool m_imported = false; QStringList m_allFiles; - const QString m_itemType = "item"; + const QString m_itemType; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.cpp index 25d15231991..8f447e374a2 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.cpp @@ -3,8 +3,6 @@ #include "contentlibrarymaterial.h" -#include - namespace QmlDesigner { ContentLibraryMaterial::ContentLibraryMaterial(QObject *parent, @@ -12,11 +10,8 @@ ContentLibraryMaterial::ContentLibraryMaterial(QObject *parent, const QString &qml, const TypeName &type, const QUrl &icon, - const QStringList &files, - const QString &downloadPath, - const QString &baseWebUrl) + const QStringList &files) : QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files) - , m_downloadPath(downloadPath), m_baseWebUrl(baseWebUrl) { m_allFiles = m_files; m_allFiles.push_back(m_qml); @@ -78,22 +73,6 @@ bool ContentLibraryMaterial::imported() const return m_imported; } -bool ContentLibraryMaterial::isDownloaded() const -{ - QString fullPath = qmlFilePath(); - return QFileInfo(fullPath).isFile(); -} - -QString ContentLibraryMaterial::qmlFilePath() const -{ - return m_downloadPath + "/" + m_qml; -} - -QString ContentLibraryMaterial::dirPath() const -{ - return m_downloadPath; -} - QStringList ContentLibraryMaterial::allFiles() const { return m_allFiles; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h index aaaf9517f99..bd7518c8775 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h @@ -18,8 +18,6 @@ class ContentLibraryMaterial : public QObject Q_PROPERTY(QUrl bundleMaterialIcon MEMBER m_icon CONSTANT) Q_PROPERTY(bool bundleMaterialVisible MEMBER m_visible NOTIFY materialVisibleChanged) Q_PROPERTY(bool bundleItemImported READ imported WRITE setImported NOTIFY materialImportedChanged) - Q_PROPERTY(QString bundleMaterialBaseWebUrl MEMBER m_baseWebUrl CONSTANT) - Q_PROPERTY(QString bundleMaterialDirPath READ dirPath CONSTANT) Q_PROPERTY(QStringList bundleMaterialFiles READ allFiles CONSTANT) Q_PROPERTY(QString itemType MEMBER m_itemType CONSTANT) @@ -29,25 +27,19 @@ public: const QString &qml, const TypeName &type, const QUrl &icon, - const QStringList &files, - const QString &downloadPath, - const QString &baseWebUrl = {}); + const QStringList &files); bool filter(const QString &searchText); - Q_INVOKABLE bool isDownloaded() const; - QString name() const; QUrl icon() const; QString qml() const; TypeName type() const; QStringList files() const; bool visible() const; - QString qmlFilePath() const; bool setImported(bool imported); bool imported() const; - QString dirPath() const; QStringList allFiles() const; signals: @@ -64,8 +56,6 @@ private: bool m_visible = true; bool m_imported = false; - QString m_downloadPath; - QString m_baseWebUrl; QStringList m_allFiles; const QString m_itemType = "material"; }; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp index adb47108a9a..10d44a2842b 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -33,7 +32,7 @@ ContentLibraryMaterialsModel::ContentLibraryMaterialsModel(ContentLibraryWidget : QAbstractListModel(parent) , m_widget(parent) { - m_downloadPath = Paths::bundlesPathSetting() + "/Materials"; + m_bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/Materials"); m_baseUrl = QmlDesignerPlugin::settings() .value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL) @@ -45,9 +44,8 @@ ContentLibraryMaterialsModel::ContentLibraryMaterialsModel(ContentLibraryWidget void ContentLibraryMaterialsModel::loadBundle() { - QDir bundleDir{m_downloadPath}; - if (fetchBundleMetadata(bundleDir) && fetchBundleIcons(bundleDir)) - loadMaterialBundle(bundleDir); + if (fetchBundleMetadata() && fetchBundleIcons()) + loadMaterialBundle(); } int ContentLibraryMaterialsModel::rowCount(const QModelIndex &) const @@ -114,13 +112,14 @@ QHash ContentLibraryMaterialsModel::roleNames() const return roles; } -bool ContentLibraryMaterialsModel::fetchBundleIcons(const QDir &bundleDir) +bool ContentLibraryMaterialsModel::fetchBundleIcons() { - QString iconsPath = bundleDir.filePath("icons"); + Utils::FilePath iconsFilePath = m_bundlePath.pathAppended("icons"); - QDir iconsDir(iconsPath); - if (iconsDir.exists() && iconsDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot).length() > 0) + if (iconsFilePath.exists() && iconsFilePath.dirEntries(QDir::Files | QDir::Dirs + | QDir::NoDotAndDotDot).length() > 0) { return true; + } QString zipFileUrl = m_baseUrl + "/icons.zip"; @@ -130,20 +129,20 @@ bool ContentLibraryMaterialsModel::fetchBundleIcons(const QDir &bundleDir) downloader->setDownloadEnabled(true); QObject::connect(downloader, &FileDownloader::finishedChanged, this, - [this, downloader, bundleDir] { + [this, downloader] { FileExtractor *extractor = new FileExtractor(this); extractor->setArchiveName(downloader->completeBaseName()); extractor->setSourceFile(downloader->outputFile()); - extractor->setTargetPath(bundleDir.absolutePath()); + extractor->setTargetPath(m_bundlePath.toFSPathString()); extractor->setAlwaysCreateDir(false); extractor->setClearTargetPathContents(false); QObject::connect(extractor, &FileExtractor::finishedChanged, this, - [this, downloader, bundleDir, extractor] { + [this, downloader, extractor] { downloader->deleteLater(); extractor->deleteLater(); - loadMaterialBundle(bundleDir); + loadMaterialBundle(); }); extractor->extract(); @@ -153,12 +152,11 @@ bool ContentLibraryMaterialsModel::fetchBundleIcons(const QDir &bundleDir) return false; } -bool ContentLibraryMaterialsModel::fetchBundleMetadata(const QDir &bundleDir) +bool ContentLibraryMaterialsModel::fetchBundleMetadata() { - QString matBundlePath = bundleDir.filePath("material_bundle.json"); + Utils::FilePath jsonFilePath = m_bundlePath.pathAppended("material_bundle.json"); - QFileInfo fi(matBundlePath); - if (fi.exists() && fi.size() > 0) + if (jsonFilePath.exists() && jsonFilePath.fileSize() > 0) return true; QString metaFileUrl = m_baseUrl + "/material_bundle.json"; @@ -166,12 +164,12 @@ bool ContentLibraryMaterialsModel::fetchBundleMetadata(const QDir &bundleDir) downloader->setUrl(metaFileUrl); downloader->setProbeUrl(false); downloader->setDownloadEnabled(true); - downloader->setTargetFilePath(matBundlePath); + downloader->setTargetFilePath(m_bundlePath.toFSPathString()); QObject::connect(downloader, &FileDownloader::finishedChanged, this, - [this, downloader, bundleDir] { - if (fetchBundleIcons(bundleDir)) - loadMaterialBundle(bundleDir); + [this, downloader] { + if (fetchBundleIcons()) + loadMaterialBundle(); downloader->deleteLater(); }); @@ -179,7 +177,7 @@ bool ContentLibraryMaterialsModel::fetchBundleMetadata(const QDir &bundleDir) return false; } -void ContentLibraryMaterialsModel::downloadSharedFiles(const QDir &targetDir, const QStringList &) +void ContentLibraryMaterialsModel::downloadSharedFiles() { QString metaFileUrl = m_baseUrl + "/shared_files.zip"; FileDownloader *downloader = new FileDownloader(this); @@ -188,11 +186,11 @@ void ContentLibraryMaterialsModel::downloadSharedFiles(const QDir &targetDir, co downloader->setDownloadEnabled(true); QObject::connect(downloader, &FileDownloader::finishedChanged, this, - [this, downloader, targetDir] { + [this, downloader] { FileExtractor *extractor = new FileExtractor(this); extractor->setArchiveName(downloader->completeBaseName()); extractor->setSourceFile(downloader->outputFile()); - extractor->setTargetPath(targetDir.absolutePath()); + extractor->setTargetPath(m_bundlePath.toFSPathString()); extractor->setAlwaysCreateDir(false); extractor->setClearTargetPathContents(false); @@ -212,7 +210,7 @@ QString ContentLibraryMaterialsModel::bundleId() const return m_bundleId; } -void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &bundleDir) +void ContentLibraryMaterialsModel::loadMaterialBundle() { auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); @@ -227,18 +225,18 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &bundleDir) m_bundleObj = {}; m_bundleId.clear(); - QString bundlePath = bundleDir.filePath("material_bundle.json"); + Utils::FilePath jsonFilePath = m_bundlePath.pathAppended("material_bundle.json"); - QFile bundleFile(bundlePath); - if (!bundleFile.open(QIODevice::ReadOnly)) { - qWarning("Couldn't open material_bundle.json"); + Utils::expected_str jsonContents = jsonFilePath.fileContents(); + if (!jsonContents.has_value()) { + qWarning() << __FUNCTION__ << jsonContents.error(); resetModel(); return; } - QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(bundleFile.readAll()); + QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(jsonContents.value()); if (bundleJsonDoc.isNull()) { - qWarning("Invalid material_bundle.json file"); + qWarning() << __FUNCTION__ << "Invalid json file" << jsonFilePath; resetModel(); return; } @@ -263,33 +261,25 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &bundleDir) for (const QJsonValueConstRef &asset : assetsArr) files.append(asset.toString()); - QUrl icon = QUrl::fromLocalFile(bundleDir.filePath(matObj.value("icon").toString())); + QUrl icon = m_bundlePath.pathAppended(matObj.value("icon").toString()).toUrl(); QString qml = matObj.value("qml").toString(); - TypeName type = QLatin1String("%1.%2") - .arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml + TypeName type = QLatin1String("%1.%2").arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml - auto bundleMat = new ContentLibraryMaterial(category, matName, qml, type, icon, files, - m_downloadPath, m_baseUrl); + auto bundleMat = new ContentLibraryMaterial(category, matName, qml, type, icon, files); category->addBundleMaterial(bundleMat); } m_bundleCategories.append(category); } - m_bundleSharedFiles.clear(); - const QJsonArray sharedFilesArr = m_bundleObj.value("sharedFiles").toArray(); - for (const QJsonValueConstRef &file : sharedFilesArr) - m_bundleSharedFiles.append(file.toString()); - - QStringList missingSharedFiles; - for (const QString &s : std::as_const(m_bundleSharedFiles)) { - if (!QFileInfo::exists(bundleDir.filePath(s))) - missingSharedFiles.push_back(s); + m_bundleSharedFiles = m_bundleObj.value("sharedFiles").toVariant().toStringList(); + for (const QString &file : std::as_const(m_bundleSharedFiles)) { + if (!m_bundlePath.pathAppended(file).exists()) { + downloadSharedFiles(); + break; + } } - if (missingSharedFiles.length() > 0) - downloadSharedFiles(bundleDir, missingSharedFiles); - m_bundleExists = true; updateIsEmpty(); resetModel(); @@ -305,6 +295,11 @@ bool ContentLibraryMaterialsModel::matBundleExists() const return m_bundleExists; } +QString ContentLibraryMaterialsModel::bundlePath() const +{ + return m_bundlePath.toFSPathString(); +} + void ContentLibraryMaterialsModel::setSearchText(const QString &searchText) { QString lowerSearchText = searchText.toLower(); @@ -364,8 +359,8 @@ void ContentLibraryMaterialsModel::applyToSelected(ContentLibraryMaterial *mat, void ContentLibraryMaterialsModel::addToProject(ContentLibraryMaterial *mat) { - QString err = m_widget->importer()->importComponent(mat->dirPath(), mat->type(), mat->qml(), - mat->files() + m_bundleSharedFiles); + QString err = m_widget->importer()->importComponent(m_bundlePath.toFSPathString(), mat->type(), + mat->qml(), mat->files() + m_bundleSharedFiles); if (err.isEmpty()) m_widget->setImporterRunning(true); @@ -383,4 +378,9 @@ void ContentLibraryMaterialsModel::removeFromProject(ContentLibraryMaterial *mat qWarning() << __FUNCTION__ << err; } +bool ContentLibraryMaterialsModel::isMaterialDownloaded(ContentLibraryMaterial *mat) const +{ + return m_bundlePath.pathAppended(mat->qml()).exists(); +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h index c0840dc3cc7..5472c14f365 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h @@ -3,11 +3,11 @@ #pragma once +#include + #include #include -QT_FORWARD_DECLARE_CLASS(QDir) - namespace QmlDesigner { class ContentLibraryMaterial; @@ -21,6 +21,8 @@ class ContentLibraryMaterialsModel : public QAbstractListModel Q_PROPERTY(bool matBundleExists READ matBundleExists NOTIFY matBundleExistsChanged) Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged) Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged) + Q_PROPERTY(QString baseWebUrl MEMBER m_baseUrl CONSTANT) + Q_PROPERTY(QString bundlePath READ bundlePath CONSTANT) public: ContentLibraryMaterialsModel(ContentLibraryWidget *parent = nullptr); @@ -37,6 +39,8 @@ public: bool hasRequiredQuick3DImport() const; bool matBundleExists() const; + QString bundlePath() const; + void resetModel(); void updateIsEmpty(); void loadBundle(); @@ -44,6 +48,7 @@ public: Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); Q_INVOKABLE void addToProject(QmlDesigner::ContentLibraryMaterial *mat); Q_INVOKABLE void removeFromProject(QmlDesigner::ContentLibraryMaterial *mat); + Q_INVOKABLE bool isMaterialDownloaded(QmlDesigner::ContentLibraryMaterial *mat) const; QString bundleId() const; @@ -55,11 +60,11 @@ signals: void matBundleExistsChanged(); private: - void loadMaterialBundle(const QDir &matBundleDir); - bool fetchBundleIcons(const QDir &bundleDir); - bool fetchBundleMetadata(const QDir &bundleDir); + void loadMaterialBundle(); + bool fetchBundleIcons(); + bool fetchBundleMetadata(); bool isValidIndex(int idx) const; - void downloadSharedFiles(const QDir &targetDir, const QStringList &files); + void downloadSharedFiles(); ContentLibraryWidget *m_widget = nullptr; QString m_searchText; @@ -74,7 +79,7 @@ private: int m_quick3dMajorVersion = -1; int m_quick3dMinorVersion = -1; - QString m_downloadPath; + Utils::FilePath m_bundlePath; QString m_baseUrl; }; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp index b521e0c702f..33e1cf4231e 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp @@ -5,8 +5,6 @@ #include "contentlibrarybundleimporter.h" #include "contentlibraryitem.h" -#include "contentlibrarymaterial.h" -#include "contentlibrarymaterialscategory.h" #include "contentlibrarytexture.h" #include "contentlibrarywidget.h" @@ -84,7 +82,7 @@ QVariant ContentLibraryUserModel::data(const QModelIndex &index, int role) const void ContentLibraryUserModel::updateNoMatchMaterials() { - m_noMatchMaterials = Utils::allOf(m_userMaterials, [&](ContentLibraryMaterial *item) { + m_noMatchMaterials = Utils::allOf(m_userMaterials, [&](ContentLibraryItem *item) { return !item->visible(); }); } @@ -111,8 +109,7 @@ void ContentLibraryUserModel::addMaterial(const QString &name, const QString &qm QString typePrefix = compUtils.userMaterialsBundleType(); TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1(); - auto libMat = new ContentLibraryMaterial(this, name, qml, type, icon, files, - Paths::bundlesPathSetting().append("/User/materials")); + auto libMat = new ContentLibraryItem(this, name, qml, type, icon, files, "material"); m_userMaterials.append(libMat); emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx)); @@ -126,7 +123,7 @@ void ContentLibraryUserModel::add3DItem(const QString &name, const QString &qml, QString typePrefix = compUtils.user3DBundleType(); TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1(); - m_user3DItems.append(new ContentLibraryItem(this, name, qml, type, icon, files)); + m_user3DItems.append(new ContentLibraryItem(this, name, qml, type, icon, files, "3d")); } void ContentLibraryUserModel::refreshSection(SectionIndex sectionIndex) @@ -184,20 +181,20 @@ void ContentLibraryUserModel::removeTexture(ContentLibraryTexture *tex) void ContentLibraryUserModel::removeFromContentLib(QObject *item) { - if (auto mat = qobject_cast(item)) - removeMaterialFromContentLib(mat); - else if (auto itm = qobject_cast(item)) - remove3DFromContentLib(itm); + auto castedItem = qobject_cast(item); + + if (castedItem->itemType() == "material") + removeMaterialFromContentLib(castedItem); + else if (castedItem->itemType() == "3d") + remove3DFromContentLib(castedItem); } -void ContentLibraryUserModel::removeMaterialFromContentLib(ContentLibraryMaterial *item) +void ContentLibraryUserModel::removeMaterialFromContentLib(ContentLibraryItem *item) { - auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/materials/"); - QJsonArray itemsArr = m_bundleObjMaterial.value("items").toArray(); // remove qml and icon files - Utils::FilePath::fromString(item->qmlFilePath()).removeFile(); + m_bundlePathMaterial.pathAppended(item->qml()).removeFile(); Utils::FilePath::fromUrl(item->icon()).removeFile(); // remove from the bundle json file @@ -209,7 +206,7 @@ void ContentLibraryUserModel::removeMaterialFromContentLib(ContentLibraryMateria } m_bundleObjMaterial.insert("items", itemsArr); - auto result = bundlePath.pathAppended(Constants::BUNDLE_JSON_FILENAME) + auto result = m_bundlePathMaterial.pathAppended(Constants::BUNDLE_JSON_FILENAME) .writeFileContents(QJsonDocument(m_bundleObjMaterial).toJson()); if (!result) qWarning() << __FUNCTION__ << result.error(); @@ -222,7 +219,7 @@ void ContentLibraryUserModel::removeMaterialFromContentLib(ContentLibraryMateria const QStringList itemFiles = item->files(); for (const QString &file : itemFiles) { if (allFiles.count(file) == 0) // only used by the deleted item - bundlePath.pathAppended(file).removeFile(); + m_bundlePathMaterial.pathAppended(file).removeFile(); } // remove from model @@ -246,8 +243,8 @@ void ContentLibraryUserModel::remove3DFromContentLibByName(const QString &qmlFil void ContentLibraryUserModel::removeMaterialFromContentLibByName(const QString &qmlFileName) { - ContentLibraryMaterial *itemToRemove = Utils::findOr(m_userMaterials, nullptr, - [&qmlFileName](ContentLibraryMaterial *item) { + ContentLibraryItem *itemToRemove = Utils::findOr(m_userMaterials, nullptr, + [&qmlFileName](ContentLibraryItem *item) { return item->qml() == qmlFileName; }); @@ -435,13 +432,9 @@ void ContentLibraryUserModel::loadMaterialBundle() QString qml = itemObj.value("qml").toString(); TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1(); QUrl icon = m_bundlePathMaterial.pathAppended(itemObj.value("icon").toString()).toUrl(); - QStringList files; - const QJsonArray assetsArr = itemObj.value("files").toArray(); - for (const QJsonValueConstRef &asset : assetsArr) - files.append(asset.toString()); + QStringList files = itemObj.value("files").toVariant().toStringList(); - m_userMaterials.append(new ContentLibraryMaterial(this, name, qml, type, icon, files, - m_bundlePathMaterial.path(), "")); + m_userMaterials.append(new ContentLibraryItem(this, name, qml, type, icon, files, "material")); } m_bundleMaterialSharedFiles.clear(); @@ -515,12 +508,9 @@ void ContentLibraryUserModel::load3DBundle() QString qml = itemObj.value("qml").toString(); TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1(); QUrl icon = m_bundlePath3D.pathAppended(itemObj.value("icon").toString()).toUrl(); - QStringList files; - const QJsonArray assetsArr = itemObj.value("files").toArray(); - for (const QJsonValueConstRef &asset : assetsArr) - files.append(asset.toString()); + QStringList files = itemObj.value("files").toVariant().toStringList(); - m_user3DItems.append(new ContentLibraryItem(nullptr, name, qml, type, icon, files)); + m_user3DItems.append(new ContentLibraryItem(nullptr, name, qml, type, icon, files, "3d")); } m_bundle3DSharedFiles.clear(); @@ -578,7 +568,7 @@ void ContentLibraryUserModel::setSearchText(const QString &searchText) m_searchText = lowerSearchText; - for (ContentLibraryMaterial *item : std::as_const(m_userMaterials)) + for (ContentLibraryItem *item : std::as_const(m_userMaterials)) item->filter(m_searchText); for (ContentLibraryTexture *item : std::as_const(m_userTextures)) @@ -596,7 +586,7 @@ void ContentLibraryUserModel::setSearchText(const QString &searchText) void ContentLibraryUserModel::updateMaterialsImportedState(const QStringList &importedItems) { bool changed = false; - for (ContentLibraryMaterial *mat : std::as_const(m_userMaterials)) + for (ContentLibraryItem *mat : std::as_const(m_userMaterials)) changed |= mat->setImported(importedItems.contains(mat->qml().chopped(4))); if (changed) @@ -634,27 +624,25 @@ void ContentLibraryUserModel::resetModel() endResetModel(); } -void ContentLibraryUserModel::applyToSelected(ContentLibraryMaterial *mat, bool add) +void ContentLibraryUserModel::applyToSelected(ContentLibraryItem *mat, bool add) { emit applyToSelectedTriggered(mat, add); } void ContentLibraryUserModel::addToProject(QObject *item) { + auto castedItem = qobject_cast(item); QString bundleDir; - TypeName type; - QString qmlFile; - QStringList files; - if (auto mat = qobject_cast(item)) { - bundleDir = mat->dirPath(); - type = mat->type(); - qmlFile = mat->qml(); - files = mat->files() + m_bundleMaterialSharedFiles; - } else if (auto itm = qobject_cast(item)) { - bundleDir = m_bundlePath3D.toString(); - type = itm->type(); - qmlFile = itm->qml(); - files = itm->files() + m_bundle3DSharedFiles; + TypeName type = castedItem->type(); + QString qmlFile = castedItem->qml(); + QStringList files = castedItem->files(); + + if (castedItem->itemType() == "material") { + bundleDir = m_bundlePathMaterial.toFSPathString(); + files << m_bundleMaterialSharedFiles; + } else if (castedItem->itemType() == "3d") { + bundleDir = m_bundlePath3D.toFSPathString(); + files << m_bundle3DSharedFiles; } else { qWarning() << __FUNCTION__ << "Unsupported Item"; return; @@ -670,20 +658,8 @@ void ContentLibraryUserModel::addToProject(QObject *item) void ContentLibraryUserModel::removeFromProject(QObject *item) { - TypeName type; - QString qml; - if (auto mat = qobject_cast(item)) { - type = mat->type(); - qml = mat->qml(); - } else if (auto itm = qobject_cast(item)) { - type = itm->type(); - qml = itm->qml(); - } else { - qWarning() << __FUNCTION__ << "Unsupported Item"; - return; - } - - QString err = m_widget->importer()->unimportComponent(type, qml); + auto castedItem = qobject_cast(item); + QString err = m_widget->importer()->unimportComponent(castedItem->type(), castedItem->qml()); if (err.isEmpty()) m_widget->setImporterRunning(true); diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h index 0295bb86cfe..9e63f37a490 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h @@ -13,7 +13,6 @@ QT_FORWARD_DECLARE_CLASS(QUrl) namespace QmlDesigner { class ContentLibraryItem; -class ContentLibraryMaterial; class ContentLibraryTexture; class ContentLibraryWidget; class NodeMetaInfo; @@ -25,7 +24,7 @@ class ContentLibraryUserModel : public QAbstractListModel Q_PROPERTY(bool matBundleExists READ matBundleExists NOTIFY matBundleExistsChanged) Q_PROPERTY(bool bundle3DExists MEMBER m_bundle3DExists NOTIFY bundle3DExistsChanged) Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged) - Q_PROPERTY(QList userMaterials MEMBER m_userMaterials NOTIFY userMaterialsChanged) + 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) Q_PROPERTY(QList userEffects MEMBER m_userEffects NOTIFY userEffectsChanged) @@ -78,7 +77,7 @@ public: void loadBundles(); - Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); + Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryItem *mat, bool add = false); Q_INVOKABLE void addToProject(QObject *item); Q_INVOKABLE void removeFromProject(QObject *item); Q_INVOKABLE void removeTexture(QmlDesigner::ContentLibraryTexture *tex); @@ -90,7 +89,7 @@ signals: void userTexturesChanged(); void user3DItemsChanged(); void userEffectsChanged(); - void applyToSelectedTriggered(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); + void applyToSelectedTriggered(QmlDesigner::ContentLibraryItem *mat, bool add = false); void matBundleExistsChanged(); void bundle3DExistsChanged(); @@ -98,7 +97,7 @@ private: void loadMaterialBundle(); void load3DBundle(); void loadTextureBundle(); - void removeMaterialFromContentLib(ContentLibraryMaterial *mat); + void removeMaterialFromContentLib(ContentLibraryItem *mat); void remove3DFromContentLib(ContentLibraryItem *item); ContentLibraryWidget *m_widget = nullptr; @@ -110,7 +109,7 @@ private: Utils::FilePath m_bundlePathMaterial; Utils::FilePath m_bundlePath3D; - QList m_userMaterials; + QList m_userMaterials; QList m_userTextures; QList m_userEffects; QList m_user3DItems; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp index 53a8178bf9f..721869f0b96 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp @@ -120,7 +120,7 @@ WidgetInfo ContentLibraryView::widgetInfo() connect(m_widget->userModel(), &ContentLibraryUserModel::applyToSelectedTriggered, this, - [&](ContentLibraryMaterial *bundleMat, bool add) { + [&](ContentLibraryItem *bundleMat, bool add) { if (m_selectedModels.isEmpty()) return; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp index 72bece4c98b..e4346f7a991 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp @@ -84,7 +84,7 @@ bool ContentLibraryWidget::eventFilter(QObject *obj, QEvent *event) } else if (m_materialToDrag) { QMouseEvent *me = static_cast(event); if ((me->globalPosition().toPoint() - m_dragStartPoint).manhattanLength() > 20 - && m_materialToDrag->isDownloaded()) { + && m_materialsModel->isMaterialDownloaded(m_materialToDrag)) { QByteArray data; QMimeData *mimeData = new QMimeData; QDataStream stream(&data, QIODevice::WriteOnly);