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 {
source: "image://materialBrowserTex/" + textureSource
asynchronous: true
sourceSize.width: root.width - 10
sourceSize.height: root.height - 10
width: root.width - 10
height: root.height - 10
anchors.centerIn: parent
smooth: true
fillMode: Image.PreserveAspectFit
}
}

View File

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

View File

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

View File

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

View File

@@ -7,10 +7,10 @@
#include "materialbrowsertexturesmodel.h"
#include "materialbrowserview.h"
#include <assetimageprovider.h>
#include <designeractionmanager.h>
#include <designermcumanager.h>
#include <documentmanager.h>
#include <propertyeditorimageprovider.h>
#include <qmldesignerconstants.h>
#include <qmldesignerplugin.h>
#include <variantproperty.h>
@@ -152,7 +152,7 @@ MaterialBrowserWidget::MaterialBrowserWidget(AsynchronousImageCache &imageCache,
{
QImage defaultImage;
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"));
setMinimumWidth(120);

View File

@@ -24,11 +24,11 @@ QT_END_NAMESPACE
namespace QmlDesigner {
class AssetImageProvider;
class MaterialBrowserView;
class MaterialBrowserModel;
class MaterialBrowserTexturesModel;
class PreviewImageProvider;
class PropertyEditorImageProvider;
class MaterialBrowserWidget : public QFrame
{
@@ -80,7 +80,7 @@ private:
QShortcut *m_qmlSourceUpdateShortcut = nullptr;
PreviewImageProvider *m_previewImageProvider = nullptr;
PropertyEditorImageProvider *m_textureImageProvider = nullptr;
AssetImageProvider *m_textureImageProvider = nullptr;
Core::IContext *m_context = nullptr;
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
#pragma once
#include "imagecache/smallimagecacheprovider.h"
#include "imagecache/midsizeimagecacheprovider.h"
#include <QQuickAsyncImageProvider>
namespace QmlDesigner {
class PropertyEditorImageProvider : public QQuickAsyncImageProvider
class AssetImageProvider : public QQuickAsyncImageProvider
{
public:
PropertyEditorImageProvider(AsynchronousImageCache &imageCache, const QImage &defaultImage = {})
: m_smallImageCacheProvider(imageCache, defaultImage)
AssetImageProvider(AsynchronousImageCache &imageCache, const QImage &defaultImage = {})
: m_imageCacheProvider(imageCache, defaultImage)
{}
QQuickImageResponse *requestImageResponse(const QString &id,
const QSize &requestedSize) override;
private:
SmallImageCacheProvider m_smallImageCacheProvider;
MidSizeImageCacheProvider m_imageCacheProvider;
};
} // 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 "aligndistribute.h"
#include "assetimageprovider.h"
#include "annotationeditor/annotationeditor.h"
#include "bindingeditor/actioneditor.h"
#include "bindingeditor/bindingeditor.h"
@@ -16,7 +17,6 @@
#include "itemfiltermodel.h"
#include "propertychangesmodel.h"
#include "propertyeditorcontextobject.h"
#include "propertyeditorimageprovider.h"
#include "propertyeditorqmlbackend.h"
#include "propertyeditorvalue.h"
#include "propertymodel.h"
@@ -33,7 +33,7 @@ Quick2PropertyEditorView::Quick2PropertyEditorView(AsynchronousImageCache &image
setResizeMode(QQuickWidget::SizeRootObjectToView);
Theme::setupTheme(engine());
engine()->addImageProvider("qmldesigner_thumbnails",
new PropertyEditorImageProvider(imageCache));
new AssetImageProvider(imageCache));
}
void Quick2PropertyEditorView::registerQmlTypes()

View File

@@ -3,10 +3,10 @@
#include "textureeditorqmlbackend.h"
#include "assetimageprovider.h"
#include "bindingproperty.h"
#include "documentmanager.h"
#include "nodemetainfo.h"
#include "propertyeditorimageprovider.h"
#include "propertyeditorvalue.h"
#include "qmldesignerconstants.h"
#include "qmlobjectnode.h"
@@ -49,7 +49,7 @@ TextureEditorQmlBackend::TextureEditorQmlBackend(TextureEditorView *textureEdito
{
QImage defaultImage;
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->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_view->engine()->addImageProvider("qmldesigner_thumbnails", m_textureEditorImageProvider);

View File

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

View File

@@ -84,9 +84,10 @@ private:
Utils::SmallStringView,
const ImageCache::AuxiliaryData &,
CaptureCallback,
AbortCallback)
AbortCallback abortCallback)
{
qWarning() << "ImageCacheDispatchCollector: cannot handle file type.";
abortCallback(ImageCache::AbortReason::Failed);
}
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/imagecachestorage.h>
#include <imagecache/meshimagecachecollector.h>
#include <imagecache/textureimagecachecollector.h>
#include <imagecache/timestampprovider.h>
#include <utils/asset.h>
#include <coreplugin/icore.h>
#include <QQmlEngine>
@@ -76,8 +79,9 @@ public:
}
};
auto makeCollecterDispatcherChain(ImageCacheCollector &nodeInstanceCollector,
MeshImageCacheCollector &meshImageCollector)
auto makeCollectorDispatcherChain(ImageCacheCollector &nodeInstanceCollector,
MeshImageCacheCollector &meshImageCollector,
TextureImageCacheCollector &textureImageCollector)
{
return std::make_tuple(
std::make_pair([](Utils::SmallStringView filePath,
@@ -91,8 +95,17 @@ auto makeCollecterDispatcherChain(ImageCacheCollector &nodeInstanceCollector,
[[maybe_unused]] const QmlDesigner::ImageCache::AuxiliaryData &auxiliaryData) {
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
class QmlDesignerProjectManager::ImageCacheData
@@ -111,10 +124,14 @@ public:
ImageCacheStorage<Sqlite::Database> storage{database};
ImageCacheConnectionManager connectionManager;
MeshImageCacheCollector meshImageCollector;
TextureImageCacheCollector textureImageCollector;
ImageCacheCollector nodeInstanceCollector;
ImageCacheDispatchCollector<decltype(makeCollecterDispatcherChain(nodeInstanceCollector,
meshImageCollector))>
dispatchCollector{makeCollecterDispatcherChain(nodeInstanceCollector, meshImageCollector)};
ImageCacheDispatchCollector<decltype(makeCollectorDispatcherChain(nodeInstanceCollector,
meshImageCollector,
textureImageCollector))>
dispatchCollector{makeCollectorDispatcherChain(nodeInstanceCollector,
meshImageCollector,
textureImageCollector)};
ImageCacheGenerator generator{dispatchCollector, storage};
TimeStampProvider timeStampProvider;
AsynchronousImageCache asynchronousImageCache{storage, generator, timeStampProvider};

View File

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