Use imagecache for all AssetImageProvider images

TextureImageCacheCollector is added to the existing async image cache
to generate thumbnails for image files.

Fixes: QDS-8581
Change-Id: I4a334b3241688d7a61a0560463bff32763a216a5
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Miikka Heikkinen
2023-01-16 13:55:02 +02:00
parent 88e75709d4
commit 15d92cf1e5
17 changed files with 171 additions and 88 deletions

View File

@@ -61,9 +61,10 @@ Rectangle {
Image { Image {
source: "image://materialBrowserTex/" + textureSource source: "image://materialBrowserTex/" + textureSource
asynchronous: true asynchronous: true
sourceSize.width: root.width - 10 width: root.width - 10
sourceSize.height: root.height - 10 height: root.height - 10
anchors.centerIn: parent anchors.centerIn: parent
smooth: true smooth: true
fillMode: Image.PreserveAspectFit
} }
} }

View File

@@ -116,8 +116,6 @@ Row {
Image { Image {
id: thumbnail id: thumbnail
asynchronous: true asynchronous: true
sourceSize.height: 96
sourceSize.width: 96
height: 96 height: 96
width: 96 width: 96
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit

View File

@@ -35,8 +35,9 @@ Column {
Image { Image {
id: texturePreview id: texturePreview
asynchronous: true asynchronous: true
sourceSize.width: 150 width: 150
sourceSize.height: 150 height: 150
fillMode: Image.PreserveAspectFit
anchors.centerIn: parent anchors.centerIn: parent
source: "image://qmldesigner_thumbnails/" + resolveResourcePath(backendValues.source.valueToString) source: "image://qmldesigner_thumbnails/" + resolveResourcePath(backendValues.source.valueToString)
} }

View File

@@ -161,6 +161,8 @@ extend_qtc_library(QmlDesignerCore
meshimagecachecollector.cpp meshimagecachecollector.cpp
meshimagecachecollector.h meshimagecachecollector.h
synchronousimagecache.cpp synchronousimagecache.cpp
textureimagecachecollector.cpp
textureimagecachecollector.h
timestampprovider.cpp timestampprovider.cpp
timestampprovider.h timestampprovider.h
timestampproviderinterface.h timestampproviderinterface.h
@@ -774,6 +776,7 @@ extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components/propertyeditor SOURCES_PREFIX components/propertyeditor
SOURCES SOURCES
aligndistribute.cpp aligndistribute.h aligndistribute.cpp aligndistribute.h
assetimageprovider.cpp assetimageprovider.h
colorpalettebackend.cpp colorpalettebackend.h colorpalettebackend.cpp colorpalettebackend.h
designerpropertymap.cpp designerpropertymap.h designerpropertymap.cpp designerpropertymap.h
fileresourcesmodel.cpp fileresourcesmodel.h fileresourcesmodel.cpp fileresourcesmodel.h
@@ -785,7 +788,6 @@ extend_qtc_plugin(QmlDesigner
gradientpresetitem.cpp gradientpresetitem.h gradientpresetitem.cpp gradientpresetitem.h
gradientpresetlistmodel.cpp gradientpresetlistmodel.h gradientpresetlistmodel.cpp gradientpresetlistmodel.h
propertyeditorcontextobject.cpp propertyeditorcontextobject.h propertyeditorcontextobject.cpp propertyeditorcontextobject.h
propertyeditorimageprovider.cpp propertyeditorimageprovider.h
propertyeditorqmlbackend.cpp propertyeditorqmlbackend.h propertyeditorqmlbackend.cpp propertyeditorqmlbackend.h
propertyeditortransaction.cpp propertyeditortransaction.h propertyeditortransaction.cpp propertyeditortransaction.h
propertyeditorvalue.cpp propertyeditorvalue.h propertyeditorvalue.cpp propertyeditorvalue.h

View File

@@ -7,10 +7,10 @@
#include "materialbrowsertexturesmodel.h" #include "materialbrowsertexturesmodel.h"
#include "materialbrowserview.h" #include "materialbrowserview.h"
#include <assetimageprovider.h>
#include <designeractionmanager.h> #include <designeractionmanager.h>
#include <designermcumanager.h> #include <designermcumanager.h>
#include <documentmanager.h> #include <documentmanager.h>
#include <propertyeditorimageprovider.h>
#include <qmldesignerconstants.h> #include <qmldesignerconstants.h>
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <variantproperty.h> #include <variantproperty.h>
@@ -152,7 +152,7 @@ MaterialBrowserWidget::MaterialBrowserWidget(AsynchronousImageCache &imageCache,
{ {
QImage defaultImage; QImage defaultImage;
defaultImage.load(Utils::StyleHelper::dpiSpecificImageFile(":/textureeditor/images/texture_default.png")); defaultImage.load(Utils::StyleHelper::dpiSpecificImageFile(":/textureeditor/images/texture_default.png"));
m_textureImageProvider = new PropertyEditorImageProvider(imageCache, defaultImage); m_textureImageProvider = new AssetImageProvider(imageCache, defaultImage);
setWindowTitle(tr("Material Browser", "Title of material browser widget")); setWindowTitle(tr("Material Browser", "Title of material browser widget"));
setMinimumWidth(120); setMinimumWidth(120);

View File

@@ -24,11 +24,11 @@ QT_END_NAMESPACE
namespace QmlDesigner { namespace QmlDesigner {
class AssetImageProvider;
class MaterialBrowserView; class MaterialBrowserView;
class MaterialBrowserModel; class MaterialBrowserModel;
class MaterialBrowserTexturesModel; class MaterialBrowserTexturesModel;
class PreviewImageProvider; class PreviewImageProvider;
class PropertyEditorImageProvider;
class MaterialBrowserWidget : public QFrame class MaterialBrowserWidget : public QFrame
{ {
@@ -80,7 +80,7 @@ private:
QShortcut *m_qmlSourceUpdateShortcut = nullptr; QShortcut *m_qmlSourceUpdateShortcut = nullptr;
PreviewImageProvider *m_previewImageProvider = nullptr; PreviewImageProvider *m_previewImageProvider = nullptr;
PropertyEditorImageProvider *m_textureImageProvider = nullptr; AssetImageProvider *m_textureImageProvider = nullptr;
Core::IContext *m_context = nullptr; Core::IContext *m_context = nullptr;
QString m_filterText; QString m_filterText;

View File

@@ -0,0 +1,32 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "assetimageprovider.h"
#include <asset.h>
#include <imagecacheimageresponse.h>
#include <projectexplorer/target.h>
#include <utils/hdrimage.h>
#include <utils/stylehelper.h>
#include <QMetaObject>
#include <QQuickImageResponse>
namespace QmlDesigner {
QQuickImageResponse *AssetImageProvider::requestImageResponse(const QString &id,
const QSize &requestedSize)
{
Asset asset(id);
if (asset.suffix() == "*.mesh")
return m_imageCacheProvider.requestImageResponse(id, {});
if (asset.suffix() == "*.builtin")
return m_imageCacheProvider.requestImageResponse("#" + id.split('.').first(), {});
return m_imageCacheProvider.requestImageResponse(id, requestedSize);
}
} // namespace QmlDesigner

View File

@@ -1,26 +1,26 @@
// Copyright (C) 2022 The Qt Company Ltd. // Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#pragma once #pragma once
#include "imagecache/smallimagecacheprovider.h" #include "imagecache/midsizeimagecacheprovider.h"
#include <QQuickAsyncImageProvider> #include <QQuickAsyncImageProvider>
namespace QmlDesigner { namespace QmlDesigner {
class PropertyEditorImageProvider : public QQuickAsyncImageProvider class AssetImageProvider : public QQuickAsyncImageProvider
{ {
public: public:
PropertyEditorImageProvider(AsynchronousImageCache &imageCache, const QImage &defaultImage = {}) AssetImageProvider(AsynchronousImageCache &imageCache, const QImage &defaultImage = {})
: m_smallImageCacheProvider(imageCache, defaultImage) : m_imageCacheProvider(imageCache, defaultImage)
{} {}
QQuickImageResponse *requestImageResponse(const QString &id, QQuickImageResponse *requestImageResponse(const QString &id,
const QSize &requestedSize) override; const QSize &requestedSize) override;
private: private:
SmallImageCacheProvider m_smallImageCacheProvider; MidSizeImageCacheProvider m_imageCacheProvider;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -1,55 +0,0 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "propertyeditorimageprovider.h"
#include <asset.h>
#include <imagecacheimageresponse.h>
#include <projectexplorer/target.h>
#include <utils/hdrimage.h>
#include <utils/stylehelper.h>
#include <QMetaObject>
#include <QQuickImageResponse>
namespace QmlDesigner {
QQuickImageResponse *PropertyEditorImageProvider::requestImageResponse(const QString &id,
const QSize &requestedSize)
{
Asset asset(id);
if (asset.suffix() == "*.mesh")
return m_smallImageCacheProvider.requestImageResponse(id, requestedSize);
if (asset.suffix() == "*.builtin")
return m_smallImageCacheProvider.requestImageResponse("#" + id.split('.').first(),
requestedSize);
auto response = std::make_unique<ImageCacheImageResponse>(m_smallImageCacheProvider.defaultImage());
QMetaObject::invokeMethod(
response.get(),
[response = QPointer<ImageCacheImageResponse>(response.get()), asset, requestedSize] {
if (asset.isImage()) {
QImage image = QImage(Utils::StyleHelper::dpiSpecificImageFile(asset.id()));
if (!image.isNull()) {
response->setImage(image.scaled(requestedSize, Qt::KeepAspectRatio));
return;
}
} else if (asset.isHdrFile()) {
HdrImage hdr{asset.id()};
if (!hdr.image().isNull()) {
response->setImage(hdr.image().scaled(requestedSize, Qt::KeepAspectRatio));
return;
}
}
response->setImage(response->image().scaled(requestedSize, Qt::KeepAspectRatio));
},
Qt::QueuedConnection);
return response.release();
}
} // namespace QmlDesigner

View File

@@ -4,6 +4,7 @@
#include "quick2propertyeditorview.h" #include "quick2propertyeditorview.h"
#include "aligndistribute.h" #include "aligndistribute.h"
#include "assetimageprovider.h"
#include "annotationeditor/annotationeditor.h" #include "annotationeditor/annotationeditor.h"
#include "bindingeditor/actioneditor.h" #include "bindingeditor/actioneditor.h"
#include "bindingeditor/bindingeditor.h" #include "bindingeditor/bindingeditor.h"
@@ -16,7 +17,6 @@
#include "itemfiltermodel.h" #include "itemfiltermodel.h"
#include "propertychangesmodel.h" #include "propertychangesmodel.h"
#include "propertyeditorcontextobject.h" #include "propertyeditorcontextobject.h"
#include "propertyeditorimageprovider.h"
#include "propertyeditorqmlbackend.h" #include "propertyeditorqmlbackend.h"
#include "propertyeditorvalue.h" #include "propertyeditorvalue.h"
#include "propertymodel.h" #include "propertymodel.h"
@@ -33,7 +33,7 @@ Quick2PropertyEditorView::Quick2PropertyEditorView(AsynchronousImageCache &image
setResizeMode(QQuickWidget::SizeRootObjectToView); setResizeMode(QQuickWidget::SizeRootObjectToView);
Theme::setupTheme(engine()); Theme::setupTheme(engine());
engine()->addImageProvider("qmldesigner_thumbnails", engine()->addImageProvider("qmldesigner_thumbnails",
new PropertyEditorImageProvider(imageCache)); new AssetImageProvider(imageCache));
} }
void Quick2PropertyEditorView::registerQmlTypes() void Quick2PropertyEditorView::registerQmlTypes()

View File

@@ -3,10 +3,10 @@
#include "textureeditorqmlbackend.h" #include "textureeditorqmlbackend.h"
#include "assetimageprovider.h"
#include "bindingproperty.h" #include "bindingproperty.h"
#include "documentmanager.h" #include "documentmanager.h"
#include "nodemetainfo.h" #include "nodemetainfo.h"
#include "propertyeditorimageprovider.h"
#include "propertyeditorvalue.h" #include "propertyeditorvalue.h"
#include "qmldesignerconstants.h" #include "qmldesignerconstants.h"
#include "qmlobjectnode.h" #include "qmlobjectnode.h"
@@ -49,7 +49,7 @@ TextureEditorQmlBackend::TextureEditorQmlBackend(TextureEditorView *textureEdito
{ {
QImage defaultImage; QImage defaultImage;
defaultImage.load(Utils::StyleHelper::dpiSpecificImageFile(":/textureeditor/images/texture_default.png")); defaultImage.load(Utils::StyleHelper::dpiSpecificImageFile(":/textureeditor/images/texture_default.png"));
m_textureEditorImageProvider = new PropertyEditorImageProvider(imageCache, defaultImage); m_textureEditorImageProvider = new AssetImageProvider(imageCache, defaultImage);
m_view->setResizeMode(QQuickWidget::SizeRootObjectToView); m_view->setResizeMode(QQuickWidget::SizeRootObjectToView);
m_view->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); m_view->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_view->engine()->addImageProvider("qmldesigner_thumbnails", m_textureEditorImageProvider); m_view->engine()->addImageProvider("qmldesigner_thumbnails", m_textureEditorImageProvider);

View File

@@ -17,9 +17,8 @@ QT_END_NAMESPACE
namespace QmlDesigner { namespace QmlDesigner {
class PropertyEditorImageProvider; class AssetImageProvider;
class TextureEditorContextObject; class TextureEditorContextObject;
class TextureEditorImageProvider;
class TextureEditorTransaction; class TextureEditorTransaction;
class TextureEditorView; class TextureEditorView;
@@ -65,7 +64,7 @@ private:
DesignerPropertyMap m_backendValuesPropertyMap; DesignerPropertyMap m_backendValuesPropertyMap;
QScopedPointer<TextureEditorTransaction> m_textureEditorTransaction; QScopedPointer<TextureEditorTransaction> m_textureEditorTransaction;
QScopedPointer<TextureEditorContextObject> m_contextObject; QScopedPointer<TextureEditorContextObject> m_contextObject;
PropertyEditorImageProvider *m_textureEditorImageProvider = nullptr; AssetImageProvider *m_textureEditorImageProvider = nullptr;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -84,9 +84,10 @@ private:
Utils::SmallStringView, Utils::SmallStringView,
const ImageCache::AuxiliaryData &, const ImageCache::AuxiliaryData &,
CaptureCallback, CaptureCallback,
AbortCallback) AbortCallback abortCallback)
{ {
qWarning() << "ImageCacheDispatchCollector: cannot handle file type."; qWarning() << "ImageCacheDispatchCollector: cannot handle file type.";
abortCallback(ImageCache::AbortReason::Failed);
} }
template<typename Collector, typename... Collectors> template<typename Collector, typename... Collectors>

View File

@@ -0,0 +1,54 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "textureimagecachecollector.h"
#include <utils/asset.h>
#include <utils/hdrimage.h>
#include <utils/smallstring.h>
#include <utils/stylehelper.h>
namespace QmlDesigner {
TextureImageCacheCollector::TextureImageCacheCollector() = default;
TextureImageCacheCollector::~TextureImageCacheCollector() = default;
void TextureImageCacheCollector::start(Utils::SmallStringView name,
Utils::SmallStringView,
const ImageCache::AuxiliaryData &auxiliaryData,
CaptureCallback captureCallback,
AbortCallback abortCallback)
{
Asset asset {QString(name)};
QImage image;
if (asset.isImage()) {
image = QImage(Utils::StyleHelper::dpiSpecificImageFile(asset.id()));
} else if (asset.isHdrFile()) {
HdrImage hdr{asset.id()};
if (!hdr.image().isNull())
image = hdr.image().copy(); // Copy to ensure image data survives HdrImage destruction
}
if (image.isNull())
abortCallback(ImageCache::AbortReason::Failed);
else
image = image.scaled(QSize{300, 300}, Qt::KeepAspectRatio);
captureCallback({}, image, {});
}
ImageCacheCollectorInterface::ImageTuple TextureImageCacheCollector::createImage(
Utils::SmallStringView, Utils::SmallStringView, const ImageCache::AuxiliaryData &)
{
return {};
}
QIcon TextureImageCacheCollector::createIcon(Utils::SmallStringView,
Utils::SmallStringView,
const ImageCache::AuxiliaryData &)
{
return {};
}
} // namespace QmlDesigner

View File

@@ -0,0 +1,31 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#pragma once
#include "imagecachecollectorinterface.h"
namespace QmlDesigner {
class TextureImageCacheCollector final : public ImageCacheCollectorInterface
{
public:
TextureImageCacheCollector();
~TextureImageCacheCollector();
void start(Utils::SmallStringView filePath,
Utils::SmallStringView state,
const ImageCache::AuxiliaryData &auxiliaryData,
CaptureCallback captureCallback,
AbortCallback abortCallback) override;
ImageTuple createImage(Utils::SmallStringView filePath,
Utils::SmallStringView state,
const ImageCache::AuxiliaryData &auxiliaryData) override;
QIcon createIcon(Utils::SmallStringView filePath,
Utils::SmallStringView state,
const ImageCache::AuxiliaryData &auxiliaryData) override;
};
} // namespace QmlDesigner

View File

@@ -31,8 +31,11 @@
#include <imagecache/imagecachegenerator.h> #include <imagecache/imagecachegenerator.h>
#include <imagecache/imagecachestorage.h> #include <imagecache/imagecachestorage.h>
#include <imagecache/meshimagecachecollector.h> #include <imagecache/meshimagecachecollector.h>
#include <imagecache/textureimagecachecollector.h>
#include <imagecache/timestampprovider.h> #include <imagecache/timestampprovider.h>
#include <utils/asset.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <QQmlEngine> #include <QQmlEngine>
@@ -76,8 +79,9 @@ public:
} }
}; };
auto makeCollecterDispatcherChain(ImageCacheCollector &nodeInstanceCollector, auto makeCollectorDispatcherChain(ImageCacheCollector &nodeInstanceCollector,
MeshImageCacheCollector &meshImageCollector) MeshImageCacheCollector &meshImageCollector,
TextureImageCacheCollector &textureImageCollector)
{ {
return std::make_tuple( return std::make_tuple(
std::make_pair([](Utils::SmallStringView filePath, std::make_pair([](Utils::SmallStringView filePath,
@@ -91,7 +95,16 @@ auto makeCollecterDispatcherChain(ImageCacheCollector &nodeInstanceCollector,
[[maybe_unused]] const QmlDesigner::ImageCache::AuxiliaryData &auxiliaryData) { [[maybe_unused]] const QmlDesigner::ImageCache::AuxiliaryData &auxiliaryData) {
return filePath.endsWith(".mesh") || filePath.startsWith("#"); return filePath.endsWith(".mesh") || filePath.startsWith("#");
}, },
&meshImageCollector)); &meshImageCollector),
std::make_pair(
[](Utils::SmallStringView filePath,
[[maybe_unused]] Utils::SmallStringView state,
[[maybe_unused]] const QmlDesigner::ImageCache::AuxiliaryData &auxiliaryData) {
Asset asset {QString(filePath)};
Asset::Type type = asset.type();
return type == Asset::Type::Image || type == Asset::Type::Texture3D;
},
&textureImageCollector));
} }
} // namespace } // namespace
@@ -111,10 +124,14 @@ public:
ImageCacheStorage<Sqlite::Database> storage{database}; ImageCacheStorage<Sqlite::Database> storage{database};
ImageCacheConnectionManager connectionManager; ImageCacheConnectionManager connectionManager;
MeshImageCacheCollector meshImageCollector; MeshImageCacheCollector meshImageCollector;
TextureImageCacheCollector textureImageCollector;
ImageCacheCollector nodeInstanceCollector; ImageCacheCollector nodeInstanceCollector;
ImageCacheDispatchCollector<decltype(makeCollecterDispatcherChain(nodeInstanceCollector, ImageCacheDispatchCollector<decltype(makeCollectorDispatcherChain(nodeInstanceCollector,
meshImageCollector))> meshImageCollector,
dispatchCollector{makeCollecterDispatcherChain(nodeInstanceCollector, meshImageCollector)}; textureImageCollector))>
dispatchCollector{makeCollectorDispatcherChain(nodeInstanceCollector,
meshImageCollector,
textureImageCollector)};
ImageCacheGenerator generator{dispatchCollector, storage}; ImageCacheGenerator generator{dispatchCollector, storage};
TimeStampProvider timeStampProvider; TimeStampProvider timeStampProvider;
AsynchronousImageCache asynchronousImageCache{storage, generator, timeStampProvider}; AsynchronousImageCache asynchronousImageCache{storage, generator, timeStampProvider};

View File

@@ -10,7 +10,9 @@ namespace QmlDesigner {
Asset::Asset(const QString &filePath) Asset::Asset(const QString &filePath)
: m_filePath(filePath) : m_filePath(filePath)
{ {
m_suffix = "*." + filePath.split('.').last().toLower(); const QStringList split = filePath.split('.');
if (split.size() > 1)
m_suffix = "*." + split.last().toLower();
} }