diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetDelegate.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetDelegate.qml index 2bbfff5223c..3e8f346fdeb 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetDelegate.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetDelegate.qml @@ -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 diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp index 14a433e8602..0dc73120f1f 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp @@ -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 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 diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.h index b18d8e70111..b089af4c89a 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.h +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.h @@ -7,8 +7,18 @@ #include +#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 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 iconSizes = {{128, 128}, // Drag {96, 96}, // list @2x {48, 48}}; // list - QHash m_thumbnails; + QHash m_thumbnails; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp index 0953eff9eb1..940a0b85fe1 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp @@ -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() diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h index 0538bedf42b..71d5c6fa457 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h @@ -40,6 +40,7 @@ public: Q_INVOKABLE QList 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); diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp index cc9263eda46..032317eb4db 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp @@ -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 AssetsLibraryWidget::createToolBarWidgets() { return {}; diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h index 90a7038b5db..2ef59ac9584 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h @@ -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); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp index fc5a09818ca..fb17f6dee82 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp @@ -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)); diff --git a/src/plugins/qmldesigner/utils/asset.cpp b/src/plugins/qmldesigner/utils/asset.cpp index 6a0a4658429..0dc66eeb3c6 100644 --- a/src/plugins/qmldesigner/utils/asset.cpp +++ b/src/plugins/qmldesigner/utils/asset.cpp @@ -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; diff --git a/src/plugins/qmldesigner/utils/asset.h b/src/plugins/qmldesigner/utils/asset.h index 279edb93e1b..e673f102387 100644 --- a/src/plugins/qmldesigner/utils/asset.h +++ b/src/plugins/qmldesigner/utils/asset.h @@ -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;