forked from qt-creator/qt-creator
QmlDesigner: Show metadata of assets when being hovered on
This change does not affect font files. For all other assets, the file type is now also shown in tooltips For image assets, the image size is also displayed. Task-number: QDS-8177 Change-Id: Iceb93a0ffe1cb284a87cc93f1da2060f6f4f1529 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -182,9 +182,36 @@ TreeViewDelegate {
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
id: assetTooltip
|
||||
visible: !root.isFont && mouseArea.containsMouse && !root.assetsView.contextMenu.visible
|
||||
text: model.filePath
|
||||
text: assetTooltip.__computeText()
|
||||
delay: 1000
|
||||
|
||||
function __computeText()
|
||||
{
|
||||
let filePath = model.filePath.replace(assetsModel.contentDirPath(), "")
|
||||
let fileSize = rootView.assetFileSize(model.filePath)
|
||||
let fileExtMatches = model.filePath.match(/\.(.*)$/)
|
||||
let fileExt = fileExtMatches ? "(" + fileExtMatches[1] + ")" : ""
|
||||
|
||||
if (rootView.assetIsImage(model.filePath)) {
|
||||
let size = rootView.imageSize(model.filePath)
|
||||
|
||||
return filePath + "\n"
|
||||
+ size.width + " x " + size.height
|
||||
+ "\n" + fileSize
|
||||
+ " " + fileExt
|
||||
} else {
|
||||
return filePath + "\n"
|
||||
+ fileSize
|
||||
+ " " + fileExt
|
||||
}
|
||||
}
|
||||
|
||||
function refresh()
|
||||
{
|
||||
text = assetTooltip.__computeText()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -293,5 +320,10 @@ TreeViewDelegate {
|
||||
: "image://qmldesigner_assets/" + model.filePath
|
||||
}
|
||||
|
||||
onStatusChanged: {
|
||||
if (thumbnailImage.status === Image.Ready)
|
||||
assetTooltip.refresh()
|
||||
}
|
||||
|
||||
} // Image
|
||||
} // TreeViewDelegate
|
||||
|
@@ -22,20 +22,13 @@ QPixmap AssetsLibraryIconProvider::requestPixmap(const QString &id, QSize *size,
|
||||
QPixmap pixmap;
|
||||
|
||||
if (m_thumbnails.contains(id)) {
|
||||
pixmap = m_thumbnails[id];
|
||||
pixmap = m_thumbnails[id].pixmap;
|
||||
} else {
|
||||
pixmap = fetchPixmap(id, requestedSize);
|
||||
bool haveValidImage = true;
|
||||
if (pixmap.isNull()) {
|
||||
pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/AssetsLibrary/images/assets_default.png");
|
||||
haveValidImage = false;
|
||||
}
|
||||
Thumbnail thumbnail = createThumbnail(id, requestedSize);
|
||||
pixmap = thumbnail.pixmap;
|
||||
|
||||
if (requestedSize.isValid())
|
||||
pixmap = pixmap.scaled(requestedSize, Qt::KeepAspectRatio);
|
||||
|
||||
if (haveValidImage)
|
||||
m_thumbnails[id] = pixmap;
|
||||
if (thumbnail.assetType != Asset::MissingImage)
|
||||
m_thumbnails[id] = thumbnail;
|
||||
}
|
||||
|
||||
if (size) {
|
||||
@@ -46,6 +39,25 @@ QPixmap AssetsLibraryIconProvider::requestPixmap(const QString &id, QSize *size,
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
Thumbnail AssetsLibraryIconProvider::createThumbnail(const QString &id, const QSize &requestedSize)
|
||||
{
|
||||
auto [pixmap, fileSize] = fetchPixmap(id, requestedSize);
|
||||
QSize originalSize = pixmap.size();
|
||||
Asset::Type assetType = Asset(id).type();
|
||||
|
||||
if (pixmap.isNull()) {
|
||||
pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/AssetsLibrary/images/assets_default.png");
|
||||
|
||||
if (assetType == Asset::Image)
|
||||
assetType = Asset::MissingImage;
|
||||
}
|
||||
|
||||
if (requestedSize.isValid())
|
||||
pixmap = pixmap.scaled(requestedSize, Qt::KeepAspectRatio);
|
||||
|
||||
return Thumbnail{pixmap, originalSize, assetType, fileSize};
|
||||
}
|
||||
|
||||
QPixmap AssetsLibraryIconProvider::generateFontIcons(const QString &filePath, const QSize &requestedSize) const
|
||||
{
|
||||
QSize reqSize = requestedSize.isValid() ? requestedSize : QSize{48, 48};
|
||||
@@ -55,18 +67,25 @@ QPixmap AssetsLibraryIconProvider::generateFontIcons(const QString &filePath, co
|
||||
"Abc"}).pixmap(reqSize);
|
||||
}
|
||||
|
||||
QPixmap AssetsLibraryIconProvider::fetchPixmap(const QString &id, const QSize &requestedSize) const
|
||||
QPair<QPixmap, qint64> AssetsLibraryIconProvider::fetchPixmap(const QString &id, const QSize &requestedSize) const
|
||||
{
|
||||
Asset asset(id);
|
||||
|
||||
if (id == "browse") {
|
||||
return Utils::StyleHelper::dpiSpecificImageFile(":/AssetsLibrary/images/browse.png");
|
||||
QString filePath = Utils::StyleHelper::dpiSpecificImageFile(":/AssetsLibrary/images/browse.png");
|
||||
return {QPixmap{filePath}, 0};
|
||||
} else if (asset.isFont()) {
|
||||
return generateFontIcons(id, requestedSize);
|
||||
qint64 size = QFileInfo(id).size();
|
||||
QPixmap pixmap = generateFontIcons(id, requestedSize);
|
||||
return {pixmap, size};
|
||||
} else if (asset.isImage()) {
|
||||
return Utils::StyleHelper::dpiSpecificImageFile(id);
|
||||
} else if (asset.isTexture3D()) {
|
||||
return HdrImage{id}.toPixmap();
|
||||
QString filePath = Utils::StyleHelper::dpiSpecificImageFile(id);
|
||||
qint64 size = QFileInfo(filePath).size();
|
||||
return {QPixmap{filePath}, size};
|
||||
} else if (asset.isHdrFile()) {
|
||||
qint64 size = QFileInfo(id).size();
|
||||
QPixmap pixmap = HdrImage{id}.toPixmap();
|
||||
return {pixmap, size};
|
||||
} else {
|
||||
QString type;
|
||||
if (asset.isShader())
|
||||
@@ -81,9 +100,11 @@ QPixmap AssetsLibraryIconProvider::fetchPixmap(const QString &id, const QSize &r
|
||||
QString pathTemplate = QString(":/AssetsLibrary/images/asset_%1%2.png").arg(type);
|
||||
QString path = pathTemplate.arg('_' + QString::number(requestedSize.width()));
|
||||
|
||||
return Utils::StyleHelper::dpiSpecificImageFile(QFileInfo::exists(path)
|
||||
? path
|
||||
: pathTemplate.arg(""));
|
||||
QString filePath = Utils::StyleHelper::dpiSpecificImageFile(QFileInfo::exists(path)
|
||||
? path
|
||||
: pathTemplate.arg(""));
|
||||
qint64 size = QFileInfo(filePath).size();
|
||||
return {QPixmap{filePath}, size};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,5 +118,23 @@ void AssetsLibraryIconProvider::invalidateThumbnail(const QString &id)
|
||||
m_thumbnails.remove(id);
|
||||
}
|
||||
|
||||
QSize AssetsLibraryIconProvider::imageSize(const QString &id)
|
||||
{
|
||||
static QSize invalidSize = {};
|
||||
return m_thumbnails.contains(id) ? m_thumbnails[id].originalSize : invalidSize;
|
||||
}
|
||||
|
||||
qint64 AssetsLibraryIconProvider::fileSize(const QString &id)
|
||||
{
|
||||
return m_thumbnails.contains(id) ? m_thumbnails[id].fileSize : 0;
|
||||
}
|
||||
|
||||
bool AssetsLibraryIconProvider::assetIsImage(const QString &id)
|
||||
{
|
||||
return m_thumbnails.contains(id)
|
||||
? (m_thumbnails[id].assetType == Asset::Type::Image || Asset(id).isHdrFile())
|
||||
: false;
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
|
@@ -7,8 +7,18 @@
|
||||
|
||||
#include <QQuickImageProvider>
|
||||
|
||||
#include "asset.h"
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
struct Thumbnail
|
||||
{
|
||||
QPixmap pixmap;
|
||||
QSize originalSize;
|
||||
Asset::Type assetType;
|
||||
qint64 fileSize;
|
||||
};
|
||||
|
||||
class AssetsLibraryIconProvider : public QQuickImageProvider
|
||||
{
|
||||
public:
|
||||
@@ -17,10 +27,14 @@ public:
|
||||
QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override;
|
||||
void clearCache();
|
||||
void invalidateThumbnail(const QString &id);
|
||||
QSize imageSize(const QString &id);
|
||||
qint64 fileSize(const QString &id);
|
||||
bool assetIsImage(const QString &id);
|
||||
|
||||
private:
|
||||
QPixmap generateFontIcons(const QString &filePath, const QSize &requestedSize) const;
|
||||
QPixmap fetchPixmap(const QString &id, const QSize &requestedSize) const;
|
||||
QPair<QPixmap, qint64> fetchPixmap(const QString &id, const QSize &requestedSize) const;
|
||||
Thumbnail createThumbnail(const QString &id, const QSize &requestedSize);
|
||||
|
||||
SynchronousImageCache &m_fontImageCache;
|
||||
|
||||
@@ -29,7 +43,7 @@ private:
|
||||
std::vector<QSize> iconSizes = {{128, 128}, // Drag
|
||||
{96, 96}, // list @2x
|
||||
{48, 48}}; // list
|
||||
QHash<QString, QPixmap> m_thumbnails;
|
||||
QHash<QString, Thumbnail> m_thumbnails;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -91,6 +91,11 @@ QString AssetsLibraryModel::currentProjectDirPath() const
|
||||
return DocumentManager::currentProjectDirPath().toString().append('/');
|
||||
}
|
||||
|
||||
QString AssetsLibraryModel::contentDirPath() const
|
||||
{
|
||||
return DocumentManager::currentResourcePath().toString().append('/');
|
||||
}
|
||||
|
||||
bool AssetsLibraryModel::requestDeleteFiles(const QStringList &filePaths)
|
||||
{
|
||||
bool askBeforeDelete = QmlDesignerPlugin::settings()
|
||||
|
@@ -40,6 +40,7 @@ public:
|
||||
Q_INVOKABLE QList<QModelIndex> parentIndices(const QModelIndex &index) const;
|
||||
Q_INVOKABLE bool indexIsValid(const QModelIndex &index) const;
|
||||
Q_INVOKABLE QString currentProjectDirPath() const;
|
||||
Q_INVOKABLE QString contentDirPath() const;
|
||||
Q_INVOKABLE bool requestDeleteFiles(const QStringList &filePaths);
|
||||
Q_INVOKABLE void deleteFiles(const QStringList &filePaths, bool dontAskAgain);
|
||||
Q_INVOKABLE bool renameFolder(const QString &folderPath, const QString &newName);
|
||||
|
@@ -165,6 +165,22 @@ void AssetsLibraryWidget::invalidateThumbnail(const QString &id)
|
||||
m_assetsIconProvider->invalidateThumbnail(id);
|
||||
}
|
||||
|
||||
QSize AssetsLibraryWidget::imageSize(const QString &id)
|
||||
{
|
||||
return m_assetsIconProvider->imageSize(id);
|
||||
}
|
||||
|
||||
QString AssetsLibraryWidget::assetFileSize(const QString &id)
|
||||
{
|
||||
qint64 fileSize = m_assetsIconProvider->fileSize(id);
|
||||
return QLocale::system().formattedDataSize(fileSize, 2, QLocale::DataSizeTraditionalFormat);
|
||||
}
|
||||
|
||||
bool AssetsLibraryWidget::assetIsImage(const QString &id)
|
||||
{
|
||||
return m_assetsIconProvider->assetIsImage(id);
|
||||
}
|
||||
|
||||
QList<QToolButton *> AssetsLibraryWidget::createToolBarWidgets()
|
||||
{
|
||||
return {};
|
||||
|
@@ -74,6 +74,10 @@ public:
|
||||
Q_INVOKABLE void openEffectMaker(const QString &filePath);
|
||||
Q_INVOKABLE bool qtVersionIsAtLeast6_4() const;
|
||||
Q_INVOKABLE void invalidateThumbnail(const QString &id);
|
||||
Q_INVOKABLE QSize imageSize(const QString &id);
|
||||
Q_INVOKABLE QString assetFileSize(const QString &id);
|
||||
Q_INVOKABLE bool assetIsImage(const QString &id);
|
||||
|
||||
Q_INVOKABLE void addTextures(const QStringList &filePaths);
|
||||
Q_INVOKABLE void addLightProbe(const QString &filePaths);
|
||||
|
||||
|
@@ -36,7 +36,7 @@ QQuickImageResponse *PropertyEditorImageProvider::requestImageResponse(const QSt
|
||||
response->setImage(image.scaled(requestedSize, Qt::KeepAspectRatio));
|
||||
return;
|
||||
}
|
||||
} else if (asset.isTexture3D()) {
|
||||
} else if (asset.isHdrFile()) {
|
||||
HdrImage hdr{asset.id()};
|
||||
if (!hdr.image().isNull()) {
|
||||
response->setImage(hdr.image().scaled(requestedSize, Qt::KeepAspectRatio));
|
||||
|
@@ -154,6 +154,11 @@ bool Asset::isTexture3D() const
|
||||
return type() == Asset::Type::Texture3D;
|
||||
}
|
||||
|
||||
bool Asset::isHdrFile() const
|
||||
{
|
||||
return m_suffix == "*.hdr";
|
||||
}
|
||||
|
||||
bool Asset::isEffect() const
|
||||
{
|
||||
return type() == Asset::Type::Effect;
|
||||
|
@@ -8,7 +8,7 @@ namespace QmlDesigner {
|
||||
class Asset
|
||||
{
|
||||
public:
|
||||
enum Type { Unknown, Image, FragmentShader, Font, Audio, Video, Texture3D, Effect, Shader };
|
||||
enum Type { Unknown, Image, MissingImage, FragmentShader, Font, Audio, Video, Texture3D, Effect, Shader };
|
||||
|
||||
Asset(const QString &filePath);
|
||||
|
||||
@@ -34,6 +34,7 @@ public:
|
||||
bool isAudio() const;
|
||||
bool isVideo() const;
|
||||
bool isTexture3D() const;
|
||||
bool isHdrFile() const;
|
||||
bool isEffect() const;
|
||||
bool isSupported() const;
|
||||
|
||||
|
Reference in New Issue
Block a user