diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml index 148ecd90ac6..6b2e3fe264e 100644 --- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml @@ -238,7 +238,7 @@ Item { onFinishedChanged: { mouseArea.enabled = true modelData.setDownloaded() - root.downloadState = "downloaded" + root.downloadState = modelData.isDownloaded() ? "downloaded" : "failed" root.downloadStateChanged() rootView.markNoTextureDownloading() diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp index 1f9cbe2ceda..16e646405b1 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp @@ -12,16 +12,20 @@ namespace QmlDesigner { ContentLibraryTexture::ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo, - const QString &downloadPath, const QUrl &icon, const QString &webUrl) + const QString &downloadPath, const QUrl &icon, + const QString &webUrl, const QString &fileExt, + const QSize &dimensions, const qint64 sizeInBytes) : QObject(parent) , m_iconPath(iconFileInfo.filePath()) , m_downloadPath(downloadPath) , m_webUrl(webUrl) , m_baseName{iconFileInfo.baseName()} + , m_fileExt(fileExt) , m_icon(icon) + , m_dimensions(dimensions) + , m_sizeInBytes(sizeInBytes) { - m_fileExt = resolveFileExt(); - m_toolTip = resolveToolTipText(); + doSetDownloaded(); } bool ContentLibraryTexture::filter(const QString &searchText) @@ -61,49 +65,56 @@ QString ContentLibraryTexture::resolveFileExt() }); } - return QString{"."} + textureFiles.at(0).completeSuffix(); + return '.' + textureFiles.at(0).completeSuffix(); } QString ContentLibraryTexture::resolveToolTipText() { - QString fileName; - QString imageInfo; - if (m_fileExt.isEmpty()) { - imageInfo = ImageUtils::imageInfo(m_iconPath, false); - fileName = m_baseName + m_defaultExt; - } else { - fileName = m_baseName + m_fileExt; - QString fullDownloadPath = m_downloadPath + "/" + fileName; - imageInfo = ImageUtils::imageInfo(fullDownloadPath, true); + // No supplied or resolved extension means we have just the icon and no other data + return m_baseName; } - return QLatin1String("%1\n%2").arg(fileName, imageInfo); + QString fileName = m_baseName + m_fileExt; + QString imageInfo; + + if (!m_isDownloaded && m_sizeInBytes > 0 && !m_dimensions.isNull()) { + imageInfo = ImageUtils::imageInfo(m_dimensions, m_sizeInBytes); + } else { + QString fullDownloadPath = m_downloadPath + '/' + fileName; + imageInfo = ImageUtils::imageInfo(fullDownloadPath); + } + + return QStringLiteral("%1\n%2").arg(fileName, imageInfo); } bool ContentLibraryTexture::isDownloaded() const { - if (m_fileExt.isEmpty()) - return false; - - QString fullPath = realTexturePath(); - return QFileInfo(fullPath).isFile(); + return m_isDownloaded; } -QString ContentLibraryTexture::realTexturePath() const +QString ContentLibraryTexture::downloadedTexturePath() const { - return m_downloadPath + "/" + m_baseName + m_fileExt; + return m_downloadPath + '/' + m_baseName + m_fileExt; } void ContentLibraryTexture::setDownloaded() { - m_fileExt = resolveFileExt(); - QString toolTip = resolveToolTipText(); + QString toolTip = m_toolTip; - if (toolTip != m_toolTip) { - m_toolTip = toolTip; + doSetDownloaded(); + + if (toolTip != m_toolTip) emit textureToolTipChanged(); - } +} + +void ContentLibraryTexture::doSetDownloaded() +{ + if (m_fileExt.isEmpty()) + m_fileExt = resolveFileExt(); + + m_isDownloaded = QFileInfo::exists(downloadedTexturePath()); + m_toolTip = resolveToolTipText(); } QString ContentLibraryTexture::parentDirPath() const diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h index 383aed750bc..f6b6cfddd88 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h @@ -5,6 +5,7 @@ #include #include +#include #include namespace QmlDesigner { @@ -22,7 +23,8 @@ class ContentLibraryTexture : public QObject public: ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo, - const QString &downloadPath, const QUrl &icon, const QString &webUrl); + const QString &downloadPath, const QUrl &icon, const QString &webUrl, + const QString &fileExt, const QSize &dimensions, const qint64 sizeInBytes); Q_INVOKABLE bool isDownloaded() const; Q_INVOKABLE void setDownloaded(); @@ -31,7 +33,7 @@ public: QUrl icon() const; QString iconPath() const; - QString realTexturePath() const; + QString downloadedTexturePath() const; QString parentDirPath() const; signals: @@ -39,9 +41,9 @@ signals: void textureToolTipChanged(); private: - inline static const QString m_defaultExt = ".png"; QString resolveFileExt(); QString resolveToolTipText(); + void doSetDownloaded(); QString m_iconPath; QString m_downloadPath; @@ -50,6 +52,9 @@ private: QString m_baseName; QString m_fileExt; QUrl m_icon; + QSize m_dimensions; + qint64 m_sizeInBytes = -1; + bool m_isDownloaded = false; bool m_visible = true; }; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp index 62553b753be..534395abb83 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp @@ -13,11 +13,13 @@ ContentLibraryTexturesCategory::ContentLibraryTexturesCategory(QObject *parent, : QObject(parent), m_name(name) {} void ContentLibraryTexturesCategory::addTexture(const QFileInfo &tex, const QString &downloadPath, - const QString &webUrl) + const QString &webUrl, const QString &fileExt, + const QSize &dimensions, const qint64 sizeInBytes) { QUrl icon = QUrl::fromLocalFile(tex.absoluteFilePath()); - m_categoryTextures.append(new ContentLibraryTexture(this, tex, downloadPath, icon, webUrl)); + m_categoryTextures.append(new ContentLibraryTexture(this, tex, downloadPath, icon, webUrl, + fileExt, dimensions, sizeInBytes)); } bool ContentLibraryTexturesCategory::filter(const QString &searchText) diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h index 0c4e9abb160..5883feb0015 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h @@ -7,6 +7,7 @@ QT_BEGIN_NAMESPACE class QFileInfo; +class QSize; QT_END_NAMESPACE namespace QmlDesigner { @@ -26,7 +27,8 @@ class ContentLibraryTexturesCategory : public QObject public: ContentLibraryTexturesCategory(QObject *parent, const QString &name); - void addTexture(const QFileInfo &tex, const QString &subPath, const QString &webUrl); + void addTexture(const QFileInfo &tex, const QString &subPath, const QString &webUrl, + const QString &fileExt, const QSize &dimensions, const qint64 sizeInBytes); bool filter(const QString &searchText); QString name() const; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp index 220149bfbc3..52c01065f76 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp @@ -13,15 +13,18 @@ #include #include +#include #include #include #include +#include #include namespace QmlDesigner { -ContentLibraryTexturesModel::ContentLibraryTexturesModel(const QString &bundleSubpath, QObject *parent) +ContentLibraryTexturesModel::ContentLibraryTexturesModel(const QString &bundleSubPath, QObject *parent) : QAbstractListModel(parent) + , m_bundleSubPath(bundleSubPath) { qmlRegisterType("WebFetcher", 1, 0, "FileDownloader"); qmlRegisterType("WebFetcher", 1, 0, "FileExtractor"); @@ -30,7 +33,7 @@ ContentLibraryTexturesModel::ContentLibraryTexturesModel(const QString &bundleSu QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/QtDesignStudio/bundles"; - m_downloadPath = baseDownloadPath + "/" + bundleSubpath; + m_downloadPath = baseDownloadPath + '/' + bundleSubPath; } int ContentLibraryTexturesModel::rowCount(const QModelIndex &) const @@ -96,7 +99,8 @@ QHash ContentLibraryTexturesModel::roleNames() const return roles; } -void ContentLibraryTexturesModel::loadTextureBundle(const QString &bundlePath, const QString &baseUrl) +void ContentLibraryTexturesModel::loadTextureBundle(const QString &bundlePath, const QString &baseUrl, + const QVariantMap &metaData) { QDir bundleDir = QDir(bundlePath); if (!bundleDir.exists()) { @@ -112,9 +116,22 @@ void ContentLibraryTexturesModel::loadTextureBundle(const QString &bundlePath, c auto category = new ContentLibraryTexturesCategory(this, dir.fileName()); const QFileInfoList texFiles = QDir(dir.filePath() + "/icon").entryInfoList(QDir::Files); for (const QFileInfo &tex : texFiles) { - QString urlPath = baseUrl + "/" + dir.fileName() + "/" + tex.baseName() + ".zip"; - QString downloadPath = m_downloadPath + "/" + dir.fileName(); - category->addTexture(tex, downloadPath, urlPath); + QString zipPath = '/' + dir.fileName() + '/' + tex.baseName() + ".zip"; + QString urlPath = baseUrl + zipPath; + QString downloadPath = m_downloadPath + '/' + dir.fileName(); + QString fullZipPath = m_bundleSubPath + zipPath; + QString fileExt; + QSize dimensions; + qint64 sizeInBytes = -1; + + if (metaData.contains(fullZipPath)) { + QVariantMap dataMap = metaData[fullZipPath].toMap(); + fileExt = '.' + dataMap.value("format").toString(); + dimensions = QSize(dataMap.value("width").toInt(), dataMap.value("height").toInt()); + sizeInBytes = dataMap.value("size").toLongLong(); + } + + category->addTexture(tex, downloadPath, urlPath, fileExt, dimensions, sizeInBytes); } m_bundleCategories.append(category); } diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h index 7c0691cff5d..f73d7b632a3 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h @@ -33,7 +33,8 @@ public: void setHasSceneEnv(bool b); void resetModel(); - void loadTextureBundle(const QString &bundlePath, const QString &baseUrl); + void loadTextureBundle(const QString &bundlePath, const QString &baseUrl, + const QVariantMap &metaData); signals: void isEmptyChanged(); @@ -46,6 +47,7 @@ private: QString m_searchText; QString m_downloadPath; + QString m_bundleSubPath; QList m_bundleCategories; bool m_isEmpty = true; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp index 146e2de7541..cacff6bf06e 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -69,10 +70,11 @@ bool ContentLibraryWidget::eventFilter(QObject *obj, QEvent *event) if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20 && m_textureToDrag->isDownloaded()) { QMimeData *mimeData = new QMimeData; - mimeData->setData(Constants::MIME_TYPE_BUNDLE_TEXTURE, {m_textureToDrag->realTexturePath().toUtf8()}); + mimeData->setData(Constants::MIME_TYPE_BUNDLE_TEXTURE, + {m_textureToDrag->downloadedTexturePath().toUtf8()}); // Allows standard file drag-n-drop. As of now needed to drop on Assets view - mimeData->setUrls({QUrl::fromLocalFile(m_textureToDrag->realTexturePath())}); + mimeData->setUrls({QUrl::fromLocalFile(m_textureToDrag->downloadedTexturePath())}); emit bundleTextureDragStarted(m_textureToDrag); model->startDrag(mimeData, m_textureToDrag->icon().toLocalFile()); @@ -106,8 +108,16 @@ ContentLibraryWidget::ContentLibraryWidget() QString baseUrl = QmlDesignerPlugin::settings() .value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL) .toString(); - m_texturesModel->loadTextureBundle(textureBundlePath + "/Textures", baseUrl + "/Textures"); - m_environmentsModel->loadTextureBundle(textureBundlePath + "/Environments", baseUrl + "/Environments"); + + QVariantMap metaData; + QFile jsonFile(textureBundlePath + "/texture_bundle.json"); + if (jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) + metaData = QJsonDocument::fromJson(jsonFile.readAll()).toVariant().toMap(); + + m_texturesModel->loadTextureBundle(textureBundlePath + "/Textures", + baseUrl + "/Textures", metaData); + m_environmentsModel->loadTextureBundle(textureBundlePath + "/Environments", + baseUrl + "/Environments", metaData); m_quickWidget->rootContext()->setContextProperties({ {"rootView", QVariant::fromValue(this)}, @@ -271,7 +281,7 @@ void ContentLibraryWidget::addImage(ContentLibraryTexture *tex) if (!tex->isDownloaded()) return; - emit addTextureRequested(tex->realTexturePath(), AddTextureMode::Image); + emit addTextureRequested(tex->downloadedTexturePath(), AddTextureMode::Image); } void ContentLibraryWidget::addTexture(ContentLibraryTexture *tex) @@ -279,7 +289,7 @@ void ContentLibraryWidget::addTexture(ContentLibraryTexture *tex) if (!tex->isDownloaded()) return; - emit addTextureRequested(tex->realTexturePath(), AddTextureMode::Texture); + emit addTextureRequested(tex->downloadedTexturePath(), AddTextureMode::Texture); } void ContentLibraryWidget::addLightProbe(ContentLibraryTexture *tex) @@ -287,7 +297,7 @@ void ContentLibraryWidget::addLightProbe(ContentLibraryTexture *tex) if (!tex->isDownloaded()) return; - emit addTextureRequested(tex->realTexturePath(), AddTextureMode::LightProbe); + emit addTextureRequested(tex->downloadedTexturePath(), AddTextureMode::LightProbe); } void ContentLibraryWidget::updateSceneEnvState() diff --git a/src/plugins/qmldesigner/utils/imageutils.cpp b/src/plugins/qmldesigner/utils/imageutils.cpp index 63f57d8a946..e83cb1262a7 100644 --- a/src/plugins/qmldesigner/utils/imageutils.cpp +++ b/src/plugins/qmldesigner/utils/imageutils.cpp @@ -11,15 +11,21 @@ namespace QmlDesigner { -QString QmlDesigner::ImageUtils::imageInfo(const QString &path, bool fetchSizeInfo) +QString ImageUtils::imageInfo(const QSize &dimensions, qint64 sizeInBytes) +{ + return QLatin1String("%1 x %2\n%3") + .arg(QString::number(dimensions.width()), + QString::number(dimensions.height()), + QLocale::system().formattedDataSize( + sizeInBytes, 2, QLocale::DataSizeTraditionalFormat)); +} + +QString QmlDesigner::ImageUtils::imageInfo(const QString &path) { QFileInfo info(path); if (!info.exists()) return {}; - if (!fetchSizeInfo) - return QLatin1String("(%1)").arg(info.suffix()); - int width = 0; int height = 0; const QString suffix = info.suffix(); @@ -43,14 +49,10 @@ QString QmlDesigner::ImageUtils::imageInfo(const QString &path, bool fetchSizeIn height = size.height(); } - if (width == 0 && height == 0) + if (width <= 0 || height <= 0) return {}; - return QLatin1String("%1 x %2\n%3 (%4)") - .arg(QString::number(width), - QString::number(height), - QLocale::system().formattedDataSize(info.size(), 2, QLocale::DataSizeTraditionalFormat), - info.suffix()); + return imageInfo(QSize(width, height), info.size()); } } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/utils/imageutils.h b/src/plugins/qmldesigner/utils/imageutils.h index 2cc58e8817d..a8deaeebff6 100644 --- a/src/plugins/qmldesigner/utils/imageutils.h +++ b/src/plugins/qmldesigner/utils/imageutils.h @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 #pragma once +#include #include namespace QmlDesigner { @@ -11,7 +12,8 @@ class ImageUtils public: ImageUtils(); - static QString imageInfo(const QString &path, bool sizeInfo = true); + static QString imageInfo(const QSize &dimensions, qint64 sizeInBytes); + static QString imageInfo(const QString &path); }; } // namespace QmlDesigner