QmlDesigner: Add image for broken preview

Task-number: QDS-9048
Change-Id: Ic2ce8bf4d51f72c3ddae588709820728fc7c76b5
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Marco Bubke
2023-02-27 16:13:58 +01:00
parent c2915c6963
commit 130453fe15
9 changed files with 38 additions and 17 deletions

View File

@@ -37,6 +37,7 @@ QQuickImageResponse *ItemLibraryIconImageProvider::requestImageResponse(const QS
[response, abortReason] {
switch (abortReason) {
case ImageCache::AbortReason::Failed:
case ImageCache::AbortReason::NoEntry:
if (response)
response->abort();
break;

View File

@@ -60,10 +60,14 @@ void AsynchronousExplicitImageCache::request(Utils::SmallStringView name,
};
const auto entry = requestImageFromStorage(requestType);
if (entry && !entry->isNull())
captureCallback(*entry);
else
abortCallback(ImageCache::AbortReason::Failed);
if (entry) {
if (entry->isNull())
abortCallback(ImageCache::AbortReason::Failed);
else
captureCallback(*entry);
} else {
abortCallback(ImageCache::AbortReason::NoEntry);
}
}
void AsynchronousExplicitImageCache::wait()

View File

@@ -27,16 +27,20 @@ QQuickImageResponse *ExplicitImageCacheImageProvider::requestImageResponse(const
},
Qt::QueuedConnection);
},
[response = QPointer<ImageCacheImageResponse>(response.get())](
ImageCache::AbortReason abortReason) {
[response = QPointer<ImageCacheImageResponse>(response.get()),
failedImage = m_failedImage](ImageCache::AbortReason abortReason) {
QMetaObject::invokeMethod(
response,
[response, abortReason] {
[response, abortReason, failedImage] {
switch (abortReason) {
case ImageCache::AbortReason::Failed:
case ImageCache::AbortReason::NoEntry:
if (response)
response->abort();
break;
case ImageCache::AbortReason::Failed:
if (response)
response->setImage(failedImage);
break;
case ImageCache::AbortReason::Abort:
response->cancel();
break;

View File

@@ -14,9 +14,11 @@ class ExplicitImageCacheImageProvider : public QQuickAsyncImageProvider
{
public:
ExplicitImageCacheImageProvider(AsynchronousExplicitImageCache &imageCache,
const QImage &defaultImage)
const QImage &defaultImage,
const QImage &failedImage)
: m_cache(imageCache)
, m_defaultImage(defaultImage)
, m_failedImage(failedImage)
{}
QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override;
@@ -24,6 +26,7 @@ public:
private:
AsynchronousExplicitImageCache &m_cache;
QImage m_defaultImage;
QImage m_failedImage;
};
} // namespace QmlDesigner

View File

@@ -32,6 +32,7 @@ QQuickImageResponse *MidSizeImageCacheProvider::requestImageResponse(const QStri
[response, abortReason] {
switch (abortReason) {
case ImageCache::AbortReason::Failed:
case ImageCache::AbortReason::NoEntry:
if (response)
response->abort();
break;

View File

@@ -33,6 +33,7 @@ QQuickImageResponse *SmallImageCacheProvider::requestImageResponse(const QString
[response, abortReason] {
switch (abortReason) {
case ImageCache::AbortReason::Failed:
case ImageCache::AbortReason::NoEntry:
if (response)
response->abort();
break;

View File

@@ -43,7 +43,7 @@ using AuxiliaryData = std::variant<std::monostate,
FontCollectorSizeAuxiliaryData,
FontCollectorSizesAuxiliaryData>;
enum class AbortReason : char { Abort, Failed };
enum class AbortReason : char { Abort, Failed, NoEntry };
using CaptureImageCallback = std::function<void(const QImage &)>;
using CaptureImageWithScaledImagesCallback = std::function<

View File

@@ -54,11 +54,16 @@ ProjectExplorer::Target *activeTarget(ProjectExplorer::Project *project)
return {};
}
QString defaultImagePath()
QString previewDefaultImagePath()
{
return Core::ICore::resourcePath("qmldesigner/welcomepage/images/newThumbnail.png").toString();
}
QString previewBrokenImagePath()
{
return Core::ICore::resourcePath("qmldesigner/welcomepage/images/newPreview.png").toString();
}
::QmlProjectManager::QmlBuildSystem *getQmlBuildSystem(::ProjectExplorer::Target *target)
{
return qobject_cast<::QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
@@ -147,7 +152,7 @@ public:
QSize{300, 300},
QSize{1000, 1000},
externalDependencies,
ImageCacheCollectorNullImageHandling::DontCaptureNullImage}
ImageCacheCollectorNullImageHandling::CaptureNullImage}
{
timer.setSingleShot(true);
}
@@ -260,8 +265,10 @@ QmlDesignerProjectManager::~QmlDesignerProjectManager() = default;
void QmlDesignerProjectManager::registerPreviewImageProvider(QQmlEngine *engine) const
{
auto imageProvider = std::make_unique<ExplicitImageCacheImageProvider>(m_previewImageCacheData->cache,
QImage{defaultImagePath()});
auto imageProvider = std::make_unique<ExplicitImageCacheImageProvider>(
m_previewImageCacheData->cache,
QImage{previewDefaultImagePath()},
QImage{previewBrokenImagePath()});
engine->addImageProvider("project_preview", imageProvider.release());
}

View File

@@ -74,7 +74,7 @@ TEST_F(AsynchronousExplicitImageCache, RequestImageCallsAbortCallbackWithoutEntr
ON_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml"), _))
.WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::ImageEntry{}));
EXPECT_CALL(mockAbortCallback, Call(Eq(QmlDesigner::ImageCache::AbortReason::Failed)))
EXPECT_CALL(mockAbortCallback, Call(Eq(QmlDesigner::ImageCache::AbortReason::NoEntry)))
.WillRepeatedly([&](auto) { notification.notify(); });
cache.requestImage("/path/to/Component.qml",
@@ -131,7 +131,7 @@ TEST_F(AsynchronousExplicitImageCache, RequestMidSizeImageCallsAbortCallbackWith
ON_CALL(mockStorage, fetchMidSizeImage(Eq("/path/to/Component.qml"), _))
.WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::ImageEntry{}));
EXPECT_CALL(mockAbortCallback, Call(Eq(QmlDesigner::ImageCache::AbortReason::Failed)))
EXPECT_CALL(mockAbortCallback, Call(Eq(QmlDesigner::ImageCache::AbortReason::NoEntry)))
.WillRepeatedly([&](auto) { notification.notify(); });
cache.requestMidSizeImage("/path/to/Component.qml",
@@ -188,7 +188,7 @@ TEST_F(AsynchronousExplicitImageCache, RequestSmallImageCallsAbortCallbackWithou
ON_CALL(mockStorage, fetchSmallImage(Eq("/path/to/Component.qml"), _))
.WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::ImageEntry{}));
EXPECT_CALL(mockAbortCallback, Call(Eq(QmlDesigner::ImageCache::AbortReason::Failed)))
EXPECT_CALL(mockAbortCallback, Call(Eq(QmlDesigner::ImageCache::AbortReason::NoEntry)))
.WillRepeatedly([&](auto) { notification.notify(); });
cache.requestSmallImage("/path/to/Component.qml",