forked from qt-creator/qt-creator
QmlDesigner: Take content library texture metadata file in use
Metadata file texture_bundle.json will be included with bundle icons, and it contains details about the texture (format, dimensions, and size) that are useful to know before downloading the texture. Metadata is used to generate proper tooltip for non-downloaded textures in content library. Also removed default suffix from displayed filename in case metadata is missing, as it was misleading. Fixes: QDS-9230 Change-Id: Icbe0bbb7f1e663e0adc41d379231b7f41dc79e31 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
@@ -238,7 +238,7 @@ Item {
|
||||
onFinishedChanged: {
|
||||
mouseArea.enabled = true
|
||||
modelData.setDownloaded()
|
||||
root.downloadState = "downloaded"
|
||||
root.downloadState = modelData.isDownloaded() ? "downloaded" : "failed"
|
||||
root.downloadStateChanged()
|
||||
|
||||
rootView.markNoTextureDownloading()
|
||||
|
@@ -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
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QObject>
|
||||
#include <QSize>
|
||||
#include <QUrl>
|
||||
|
||||
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;
|
||||
};
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
|
@@ -13,15 +13,18 @@
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QUrl>
|
||||
#include <QQmlEngine>
|
||||
#include <QSize>
|
||||
#include <QStandardPaths>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
ContentLibraryTexturesModel::ContentLibraryTexturesModel(const QString &bundleSubpath, QObject *parent)
|
||||
ContentLibraryTexturesModel::ContentLibraryTexturesModel(const QString &bundleSubPath, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_bundleSubPath(bundleSubPath)
|
||||
{
|
||||
qmlRegisterType<QmlDesigner::FileDownloader>("WebFetcher", 1, 0, "FileDownloader");
|
||||
qmlRegisterType<QmlDesigner::FileExtractor>("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<int, QByteArray> 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);
|
||||
}
|
||||
|
@@ -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<ContentLibraryTexturesCategory *> m_bundleCategories;
|
||||
|
||||
bool m_isEmpty = true;
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QMimeData>
|
||||
#include <QMouseEvent>
|
||||
#include <QQmlContext>
|
||||
@@ -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()
|
||||
|
@@ -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
|
||||
|
@@ -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 <QSize>
|
||||
#include <QString>
|
||||
|
||||
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
|
||||
|
Reference in New Issue
Block a user