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);