QmlDesigner: Add an reason parameter to the image cache abort callback

Sometimes we abort the request, sometimes it failed. In the first case
we maybe want the cancel the imageprovider request, in the second we
return an empty image.

Fixes: QDS-3388
Change-Id: Iaef76aa09ac734795f86447e1a7cf6a5c7b5ae81
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
This commit is contained in:
Marco Bubke
2021-01-28 12:11:51 +01:00
parent 62582877f6
commit e34eb170dc
16 changed files with 127 additions and 90 deletions

View File

@@ -77,12 +77,19 @@ QQuickImageResponse *ItemLibraryIconImageProvider::requestImageResponse(const QS
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
}, },
[response = QPointer<ImageRespose>(response.get())] { [response = QPointer<ImageRespose>(response.get())](ImageCache::AbortReason abortReason) {
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
response, response,
[response] { [response, abortReason] {
if (response) switch (abortReason) {
response->abort(); case ImageCache::AbortReason::Failed:
if (response)
response->abort();
break;
case ImageCache::AbortReason::Abort:
response->cancel();
break;
}
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
}); });

View File

@@ -63,7 +63,7 @@ void PreviewTooltipBackend::showTooltip()
} }
}); });
}, },
[] {}, [](auto) {},
m_extraId, m_extraId,
m_auxiliaryData); m_auxiliaryData);

View File

@@ -68,8 +68,8 @@ AsynchronousImageCache::~AsynchronousImageCache()
void AsynchronousImageCache::request(Utils::SmallStringView name, void AsynchronousImageCache::request(Utils::SmallStringView name,
Utils::SmallStringView extraId, Utils::SmallStringView extraId,
AsynchronousImageCache::RequestType requestType, AsynchronousImageCache::RequestType requestType,
AsynchronousImageCache::CaptureImageCallback captureCallback, ImageCache::CaptureImageCallback captureCallback,
AsynchronousImageCache::AbortCallback abortCallback, ImageCache::AbortCallback abortCallback,
ImageCache::AuxiliaryData auxiliaryData, ImageCache::AuxiliaryData auxiliaryData,
ImageCacheStorageInterface &storage, ImageCacheStorageInterface &storage,
ImageCacheGeneratorInterface &generator, ImageCacheGeneratorInterface &generator,
@@ -83,7 +83,7 @@ void AsynchronousImageCache::request(Utils::SmallStringView name,
if (entry.hasEntry) { if (entry.hasEntry) {
if (entry.image.isNull()) if (entry.image.isNull())
abortCallback(); abortCallback(ImageCache::AbortReason::Failed);
else else
captureCallback(entry.image); captureCallback(entry.image);
} else { } else {
@@ -109,8 +109,8 @@ void AsynchronousImageCache::wait()
} }
void AsynchronousImageCache::requestImage(Utils::PathString name, void AsynchronousImageCache::requestImage(Utils::PathString name,
AsynchronousImageCache::CaptureImageCallback captureCallback, ImageCache::CaptureImageCallback captureCallback,
AbortCallback abortCallback, ImageCache::AbortCallback abortCallback,
Utils::SmallString extraId, Utils::SmallString extraId,
ImageCache::AuxiliaryData auxiliaryData) ImageCache::AuxiliaryData auxiliaryData)
{ {
@@ -124,8 +124,8 @@ void AsynchronousImageCache::requestImage(Utils::PathString name,
} }
void AsynchronousImageCache::requestSmallImage(Utils::PathString name, void AsynchronousImageCache::requestSmallImage(Utils::PathString name,
AsynchronousImageCache::CaptureImageCallback captureCallback, ImageCache::CaptureImageCallback captureCallback,
AsynchronousImageCache::AbortCallback abortCallback, ImageCache::AbortCallback abortCallback,
Utils::SmallString extraId, Utils::SmallString extraId,
ImageCache::AuxiliaryData auxiliaryData) ImageCache::AuxiliaryData auxiliaryData)
{ {
@@ -166,8 +166,8 @@ std::tuple<bool, AsynchronousImageCache::Entry> AsynchronousImageCache::getEntry
void AsynchronousImageCache::addEntry(Utils::PathString &&name, void AsynchronousImageCache::addEntry(Utils::PathString &&name,
Utils::SmallString &&extraId, Utils::SmallString &&extraId,
AsynchronousImageCache::CaptureImageCallback &&captureCallback, ImageCache::CaptureImageCallback &&captureCallback,
AbortCallback &&abortCallback, ImageCache::AbortCallback &&abortCallback,
ImageCache::AuxiliaryData &&auxiliaryData, ImageCache::AuxiliaryData &&auxiliaryData,
RequestType requestType) RequestType requestType)
{ {
@@ -185,7 +185,7 @@ void AsynchronousImageCache::clearEntries()
{ {
std::unique_lock lock{m_mutex}; std::unique_lock lock{m_mutex};
for (Entry &entry : m_entries) for (Entry &entry : m_entries)
entry.abortCallback(); entry.abortCallback(ImageCache::AbortReason::Abort);
m_entries.clear(); m_entries.clear();
} }

View File

@@ -68,12 +68,10 @@ ImageCacheCollector::~ImageCacheCollector() = default;
void ImageCacheCollector::start(Utils::SmallStringView name, void ImageCacheCollector::start(Utils::SmallStringView name,
Utils::SmallStringView state, Utils::SmallStringView state,
const ImageCache::AuxiliaryData &auxiliaryData, const ImageCache::AuxiliaryData &,
CaptureCallback captureCallback, CaptureCallback captureCallback,
AbortCallback abortCallback) AbortCallback abortCallback)
{ {
Q_UNUSED(auxiliaryData)
RewriterView rewriterView{RewriterView::Amend, nullptr}; RewriterView rewriterView{RewriterView::Amend, nullptr};
NodeInstanceView nodeInstanceView{m_connectionManager}; NodeInstanceView nodeInstanceView{m_connectionManager};
@@ -91,7 +89,7 @@ void ImageCacheCollector::start(Utils::SmallStringView name,
model->setRewriterView(&rewriterView); model->setRewriterView(&rewriterView);
if (rewriterView.inErrorState() || !rewriterView.rootModelNode().metaInfo().isGraphicalItem()) { if (rewriterView.inErrorState() || !rewriterView.rootModelNode().metaInfo().isGraphicalItem()) {
abortCallback(); abortCallback(ImageCache::AbortReason::Failed);
return; return;
} }
@@ -100,18 +98,18 @@ void ImageCacheCollector::start(Utils::SmallStringView name,
if (stateNode.isValid()) if (stateNode.isValid())
rewriterView.setCurrentStateNode(stateNode); rewriterView.setCurrentStateNode(stateNode);
auto callback = [captureCallback = std::move(captureCallback)](QImage &&image) { auto callback = [captureCallback = std::move(captureCallback)](const QImage &image) {
QSize smallImageSize = image.size().scaled(QSize{96, 96}.boundedTo(image.size()), QSize smallImageSize = image.size().scaled(QSize{96, 96}.boundedTo(image.size()),
Qt::KeepAspectRatio); Qt::KeepAspectRatio);
QImage smallImage = image.isNull() ? QImage{} : image.scaled(smallImageSize); QImage smallImage = image.isNull() ? QImage{} : image.scaled(smallImageSize);
captureCallback(std::move(image), std::move(smallImage)); captureCallback(image, smallImage);
}; };
m_connectionManager.setCallback(std::move(callback)); m_connectionManager.setCallback(std::move(callback));
nodeInstanceView.setTarget(m_target.data()); nodeInstanceView.setTarget(m_target.data());
nodeInstanceView.setCrashCallback(abortCallback); nodeInstanceView.setCrashCallback([=] { abortCallback(ImageCache::AbortReason::Failed); });
model->setNodeInstanceView(&nodeInstanceView); model->setNodeInstanceView(&nodeInstanceView);
bool capturedDataArrived = m_connectionManager.waitForCapturedData(); bool capturedDataArrived = m_connectionManager.waitForCapturedData();
@@ -123,7 +121,7 @@ void ImageCacheCollector::start(Utils::SmallStringView name,
model->setRewriterView({}); model->setRewriterView({});
if (!capturedDataArrived) if (!capturedDataArrived)
abortCallback(); abortCallback(ImageCache::AbortReason::Failed);
} }
std::pair<QImage, QImage> ImageCacheCollector::createImage(Utils::SmallStringView filePath, std::pair<QImage, QImage> ImageCacheCollector::createImage(Utils::SmallStringView filePath,

View File

@@ -36,8 +36,8 @@ namespace QmlDesigner {
class ImageCacheCollectorInterface class ImageCacheCollectorInterface
{ {
public: public:
using CaptureCallback = std::function<void(QImage &&image, QImage &&smallImage)>; using CaptureCallback = ImageCache::CaptureImageWithSmallImageCallback;
using AbortCallback = std::function<void()>; using AbortCallback = ImageCache::AbortCallback;
using ImagePair = std::pair<QImage, QImage>; using ImagePair = std::pair<QImage, QImage>;
virtual void start(Utils::SmallStringView filePath, virtual void start(Utils::SmallStringView filePath,

View File

@@ -26,7 +26,7 @@ class CapturedDataCommand;
class ImageCacheConnectionManager : public ConnectionManager class ImageCacheConnectionManager : public ConnectionManager
{ {
public: public:
using Callback = std::function<void(QImage &&)>; using Callback = std::function<void(const QImage &)>;
ImageCacheConnectionManager(); ImageCacheConnectionManager();

View File

@@ -140,7 +140,7 @@ void ImageCacheFontCollector::start(Utils::SmallStringView name,
return; return;
} }
} }
abortCallback(); abortCallback(ImageCache::AbortReason::Failed);
} }
std::pair<QImage, QImage> ImageCacheFontCollector::createImage( std::pair<QImage, QImage> ImageCacheFontCollector::createImage(

View File

@@ -50,8 +50,8 @@ ImageCacheGenerator::~ImageCacheGenerator()
void ImageCacheGenerator::generateImage(Utils::SmallStringView name, void ImageCacheGenerator::generateImage(Utils::SmallStringView name,
Utils::SmallStringView extraId, Utils::SmallStringView extraId,
Sqlite::TimeStamp timeStamp, Sqlite::TimeStamp timeStamp,
ImageCacheGeneratorInterface::CaptureCallback &&captureCallback, ImageCache::CaptureImageWithSmallImageCallback &&captureCallback,
AbortCallback &&abortCallback, ImageCache::AbortCallback &&abortCallback,
ImageCache::AuxiliaryData &&auxiliaryData) ImageCache::AuxiliaryData &&auxiliaryData)
{ {
{ {
@@ -96,7 +96,7 @@ void ImageCacheGenerator::clean()
{ {
std::lock_guard lock{m_mutex}; std::lock_guard lock{m_mutex};
for (Task &task : m_tasks) for (Task &task : m_tasks)
callCallbacks(task.abortCallbacks); callCallbacks(task.abortCallbacks, ImageCache::AbortReason::Abort);
m_tasks.clear(); m_tasks.clear();
} }
@@ -133,9 +133,9 @@ void ImageCacheGenerator::startGeneration()
task.filePath, task.filePath,
task.extraId, task.extraId,
std::move(task.auxiliaryData), std::move(task.auxiliaryData),
[this, task](QImage &&image, QImage &&smallImage) { [this, task](const QImage &image, const QImage &smallImage) {
if (image.isNull()) if (image.isNull())
callCallbacks(task.abortCallbacks); callCallbacks(task.abortCallbacks, ImageCache::AbortReason::Failed);
else else
callCallbacks(task.captureCallbacks, image, smallImage); callCallbacks(task.captureCallbacks, image, smallImage);
@@ -144,9 +144,10 @@ void ImageCacheGenerator::startGeneration()
image, image,
smallImage); smallImage);
}, },
[this, task] { [this, task](ImageCache::AbortReason abortReason) {
callCallbacks(task.abortCallbacks); callCallbacks(task.abortCallbacks, abortReason);
m_storage.storeImage(createId(task.filePath, task.extraId), task.timeStamp, {}, {}); if (abortReason != ImageCache::AbortReason::Abort)
m_storage.storeImage(createId(task.filePath, task.extraId), task.timeStamp, {}, {});
}); });
std::lock_guard lock{m_mutex}; std::lock_guard lock{m_mutex};

View File

@@ -55,8 +55,8 @@ public:
void generateImage(Utils::SmallStringView filePath, void generateImage(Utils::SmallStringView filePath,
Utils::SmallStringView extraId, Utils::SmallStringView extraId,
Sqlite::TimeStamp timeStamp, Sqlite::TimeStamp timeStamp,
CaptureCallback &&captureCallback, ImageCache::CaptureImageWithSmallImageCallback &&captureCallback,
AbortCallback &&abortCallback, ImageCache::AbortCallback &&abortCallback,
ImageCache::AuxiliaryData &&auxiliaryData) override; ImageCache::AuxiliaryData &&auxiliaryData) override;
void clean() override; void clean() override;
@@ -70,8 +70,8 @@ private:
Utils::SmallStringView extraId, Utils::SmallStringView extraId,
ImageCache::AuxiliaryData &&auxiliaryData, ImageCache::AuxiliaryData &&auxiliaryData,
Sqlite::TimeStamp timeStamp, Sqlite::TimeStamp timeStamp,
CaptureCallback &&captureCallback, ImageCache::CaptureImageWithSmallImageCallback &&captureCallback,
AbortCallback &&abortCallback) ImageCache::AbortCallback &&abortCallback)
: filePath(filePath) : filePath(filePath)
, extraId(std::move(extraId)) , extraId(std::move(extraId))
, auxiliaryData(std::move(auxiliaryData)) , auxiliaryData(std::move(auxiliaryData))
@@ -83,8 +83,8 @@ private:
Utils::PathString filePath; Utils::PathString filePath;
Utils::SmallString extraId; Utils::SmallString extraId;
ImageCache::AuxiliaryData auxiliaryData; ImageCache::AuxiliaryData auxiliaryData;
std::vector<CaptureCallback> captureCallbacks; std::vector<ImageCache::CaptureImageWithSmallImageCallback> captureCallbacks;
std::vector<AbortCallback> abortCallbacks; std::vector<ImageCache::AbortCallback> abortCallbacks;
Sqlite::TimeStamp timeStamp; Sqlite::TimeStamp timeStamp;
}; };

View File

@@ -36,14 +36,11 @@ namespace QmlDesigner {
class ImageCacheGeneratorInterface class ImageCacheGeneratorInterface
{ {
public: public:
using CaptureCallback = std::function<void(const QImage &image, const QImage &smallImage)>;
using AbortCallback = std::function<void()>;
virtual void generateImage(Utils::SmallStringView name, virtual void generateImage(Utils::SmallStringView name,
Utils::SmallStringView extraId, Utils::SmallStringView extraId,
Sqlite::TimeStamp timeStamp, Sqlite::TimeStamp timeStamp,
CaptureCallback &&captureCallback, ImageCache::CaptureImageWithSmallImageCallback &&captureCallback,
AbortCallback &&abortCallback, ImageCache::AbortCallback &&abortCallback,
ImageCache::AuxiliaryData &&auxiliaryData) ImageCache::AuxiliaryData &&auxiliaryData)
= 0; = 0;

View File

@@ -43,8 +43,6 @@ class ImageCacheCollectorInterface;
class AsynchronousImageCache final : public AsynchronousImageCacheInterface class AsynchronousImageCache final : public AsynchronousImageCacheInterface
{ {
public: public:
using CaptureImageCallback = std::function<void(const QImage &)>;
using AbortCallback = std::function<void()>;
~AsynchronousImageCache(); ~AsynchronousImageCache();
@@ -53,13 +51,13 @@ public:
TimeStampProviderInterface &timeStampProvider); TimeStampProviderInterface &timeStampProvider);
void requestImage(Utils::PathString name, void requestImage(Utils::PathString name,
CaptureImageCallback captureCallback, ImageCache::CaptureImageCallback captureCallback,
AbortCallback abortCallback, ImageCache::AbortCallback abortCallback,
Utils::SmallString extraId = {}, Utils::SmallString extraId = {},
ImageCache::AuxiliaryData auxiliaryData = {}) override; ImageCache::AuxiliaryData auxiliaryData = {}) override;
void requestSmallImage(Utils::PathString name, void requestSmallImage(Utils::PathString name,
CaptureImageCallback captureCallback, ImageCache::CaptureImageCallback captureCallback,
AbortCallback abortCallback, ImageCache::AbortCallback abortCallback,
Utils::SmallString extraId = {}, Utils::SmallString extraId = {},
ImageCache::AuxiliaryData auxiliaryData = {}) override; ImageCache::AuxiliaryData auxiliaryData = {}) override;
@@ -73,8 +71,8 @@ private:
Entry() = default; Entry() = default;
Entry(Utils::PathString name, Entry(Utils::PathString name,
Utils::SmallString extraId, Utils::SmallString extraId,
CaptureImageCallback &&captureCallback, ImageCache::CaptureImageCallback &&captureCallback,
AbortCallback &&abortCallback, ImageCache::AbortCallback &&abortCallback,
ImageCache::AuxiliaryData &&auxiliaryData, ImageCache::AuxiliaryData &&auxiliaryData,
RequestType requestType) RequestType requestType)
: name{std::move(name)} : name{std::move(name)}
@@ -87,8 +85,8 @@ private:
Utils::PathString name; Utils::PathString name;
Utils::SmallString extraId; Utils::SmallString extraId;
CaptureImageCallback captureCallback; ImageCache::CaptureImageCallback captureCallback;
AbortCallback abortCallback; ImageCache::AbortCallback abortCallback;
ImageCache::AuxiliaryData auxiliaryData; ImageCache::AuxiliaryData auxiliaryData;
RequestType requestType = RequestType::Image; RequestType requestType = RequestType::Image;
}; };
@@ -96,8 +94,8 @@ private:
std::tuple<bool, Entry> getEntry(); std::tuple<bool, Entry> getEntry();
void addEntry(Utils::PathString &&name, void addEntry(Utils::PathString &&name,
Utils::SmallString &&extraId, Utils::SmallString &&extraId,
CaptureImageCallback &&captureCallback, ImageCache::CaptureImageCallback &&captureCallback,
AbortCallback &&abortCallback, ImageCache::AbortCallback &&abortCallback,
ImageCache::AuxiliaryData &&auxiliaryData, ImageCache::AuxiliaryData &&auxiliaryData,
RequestType requestType); RequestType requestType);
void clearEntries(); void clearEntries();
@@ -107,8 +105,8 @@ private:
static void request(Utils::SmallStringView name, static void request(Utils::SmallStringView name,
Utils::SmallStringView extraId, Utils::SmallStringView extraId,
AsynchronousImageCache::RequestType requestType, AsynchronousImageCache::RequestType requestType,
AsynchronousImageCache::CaptureImageCallback captureCallback, ImageCache::CaptureImageCallback captureCallback,
AsynchronousImageCache::AbortCallback abortCallback, ImageCache::AbortCallback abortCallback,
ImageCache::AuxiliaryData auxiliaryData, ImageCache::AuxiliaryData auxiliaryData,
ImageCacheStorageInterface &storage, ImageCacheStorageInterface &storage,
ImageCacheGeneratorInterface &generator, ImageCacheGeneratorInterface &generator,

View File

@@ -36,18 +36,15 @@ namespace QmlDesigner {
class AsynchronousImageCacheInterface class AsynchronousImageCacheInterface
{ {
public: public:
using CaptureCallback = std::function<void(const QImage &)>;
using AbortCallback = std::function<void()>;
virtual void requestImage(Utils::PathString name, virtual void requestImage(Utils::PathString name,
CaptureCallback captureCallback, ImageCache::CaptureImageCallback captureCallback,
AbortCallback abortCallback, ImageCache::AbortCallback abortCallback,
Utils::SmallString extraId = {}, Utils::SmallString extraId = {},
ImageCache::AuxiliaryData auxiliaryData = {}) ImageCache::AuxiliaryData auxiliaryData = {})
= 0; = 0;
virtual void requestSmallImage(Utils::PathString name, virtual void requestSmallImage(Utils::PathString name,
CaptureCallback captureCallback, ImageCache::CaptureImageCallback captureCallback,
AbortCallback abortCallback, ImageCache::AbortCallback abortCallback,
Utils::SmallString extraId = {}, Utils::SmallString extraId = {},
ImageCache::AuxiliaryData auxiliaryData = {}) ImageCache::AuxiliaryData auxiliaryData = {})
= 0; = 0;

View File

@@ -28,9 +28,12 @@
#include <utils/span.h> #include <utils/span.h>
#include <utils/variant.h> #include <utils/variant.h>
#include <QImage>
#include <QSize> #include <QSize>
#include <QString> #include <QString>
#include <functional>
namespace QmlDesigner { namespace QmlDesigner {
namespace ImageCache { namespace ImageCache {
@@ -56,6 +59,11 @@ public:
using AuxiliaryData = Utils::variant<NullAuxiliaryData, FontCollectorSizeAuxiliaryData, FontCollectorSizesAuxiliaryData>; using AuxiliaryData = Utils::variant<NullAuxiliaryData, FontCollectorSizeAuxiliaryData, FontCollectorSizesAuxiliaryData>;
enum class AbortReason : char { Abort, Failed };
using CaptureImageCallback = std::function<void(const QImage &)>;
using CaptureImageWithSmallImageCallback = std::function<void(const QImage &image, const QImage &smallImage)>;
using AbortCallback = std::function<void(ImageCache::AbortReason)>;
} // namespace ImageCache } // namespace ImageCache
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -39,7 +39,7 @@ class AsynchronousImageCache : public testing::Test
protected: protected:
Notification notification; Notification notification;
Notification waitInThread; Notification waitInThread;
NiceMock<MockFunction<void()>> mockAbortCallback; NiceMock<MockFunction<void(QmlDesigner::ImageCache::AbortReason)>> mockAbortCallback;
NiceMock<MockFunction<void(const QImage &image)>> mockCaptureCallback; NiceMock<MockFunction<void(const QImage &image)>> mockCaptureCallback;
NiceMock<MockImageCacheStorage> mockStorage; NiceMock<MockImageCacheStorage> mockStorage;
NiceMock<MockImageCacheGenerator> mockGenerator; NiceMock<MockImageCacheGenerator> mockGenerator;
@@ -99,7 +99,8 @@ TEST_F(AsynchronousImageCache, RequestImageCallsAbortCallbackWithoutImage)
ON_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml"), _)) ON_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml"), _))
.WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::ImageEntry{QImage{}, true})); .WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::ImageEntry{QImage{}, true}));
EXPECT_CALL(mockAbortCallback, Call()).WillRepeatedly([&] { notification.notify(); }); EXPECT_CALL(mockAbortCallback, Call(Eq(QmlDesigner::ImageCache::AbortReason::Failed)))
.WillRepeatedly([&](auto) { notification.notify(); });
cache.requestImage("/path/to/Component.qml", cache.requestImage("/path/to/Component.qml",
mockCaptureCallback.AsStdFunction(), mockCaptureCallback.AsStdFunction(),
@@ -142,11 +143,11 @@ TEST_F(AsynchronousImageCache, RequestImageCallsAbortCallbackFromGenerator)
{ {
ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _, _, _)) ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _, _, _))
.WillByDefault([&](auto, auto, auto, auto &&, auto &&abortCallback, auto) { .WillByDefault([&](auto, auto, auto, auto &&, auto &&abortCallback, auto) {
abortCallback(); abortCallback(QmlDesigner::ImageCache::AbortReason::Failed);
notification.notify(); notification.notify();
}); });
EXPECT_CALL(mockAbortCallback, Call()); EXPECT_CALL(mockAbortCallback, Call(Eq(QmlDesigner::ImageCache::AbortReason::Failed)));
cache.requestImage("/path/to/Component.qml", cache.requestImage("/path/to/Component.qml",
mockCaptureCallback.AsStdFunction(), mockCaptureCallback.AsStdFunction(),
@@ -204,7 +205,8 @@ TEST_F(AsynchronousImageCache, RequestSmallImageCallsAbortCallbackWithoutSmallIm
ON_CALL(mockStorage, fetchSmallImage(Eq("/path/to/Component.qml"), _)) ON_CALL(mockStorage, fetchSmallImage(Eq("/path/to/Component.qml"), _))
.WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::ImageEntry{QImage{}, true})); .WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::ImageEntry{QImage{}, true}));
EXPECT_CALL(mockAbortCallback, Call()).WillRepeatedly([&] { notification.notify(); }); EXPECT_CALL(mockAbortCallback, Call(Eq(QmlDesigner::ImageCache::AbortReason::Failed)))
.WillRepeatedly([&](auto) { notification.notify(); });
cache.requestSmallImage("/path/to/Component.qml", cache.requestSmallImage("/path/to/Component.qml",
mockCaptureCallback.AsStdFunction(), mockCaptureCallback.AsStdFunction(),
@@ -247,11 +249,11 @@ TEST_F(AsynchronousImageCache, RequestSmallImageCallsAbortCallbackFromGenerator)
{ {
ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _, _, _)) ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _, _, _))
.WillByDefault([&](auto, auto, auto, auto &&, auto &&abortCallback, auto) { .WillByDefault([&](auto, auto, auto, auto &&, auto &&abortCallback, auto) {
abortCallback(); abortCallback(QmlDesigner::ImageCache::AbortReason::Failed);
notification.notify(); notification.notify();
}); });
EXPECT_CALL(mockAbortCallback, Call()); EXPECT_CALL(mockAbortCallback, Call(Eq(QmlDesigner::ImageCache::AbortReason::Failed)));
cache.requestSmallImage("/path/to/Component.qml", cache.requestSmallImage("/path/to/Component.qml",
mockCaptureCallback.AsStdFunction(), mockCaptureCallback.AsStdFunction(),
@@ -292,7 +294,8 @@ TEST_F(AsynchronousImageCache, CleanCallsAbort)
mockCaptureCallback.AsStdFunction(), mockCaptureCallback.AsStdFunction(),
mockAbortCallback.AsStdFunction()); mockAbortCallback.AsStdFunction());
EXPECT_CALL(mockAbortCallback, Call()).Times(AtLeast(2)); EXPECT_CALL(mockAbortCallback, Call(Eq(QmlDesigner::ImageCache::AbortReason::Abort)))
.Times(AtLeast(2));
cache.requestSmallImage("/path/to/Component3.qml", cache.requestSmallImage("/path/to/Component3.qml",
mockCaptureCallback.AsStdFunction(), mockCaptureCallback.AsStdFunction(),

View File

@@ -56,7 +56,7 @@ protected:
QImage image1{10, 10, QImage::Format_ARGB32}; QImage image1{10, 10, QImage::Format_ARGB32};
QImage smallImage1{1, 1, QImage::Format_ARGB32}; QImage smallImage1{1, 1, QImage::Format_ARGB32};
NiceMock<MockFunction<void(const QImage &, const QImage &)>> imageCallbackMock; NiceMock<MockFunction<void(const QImage &, const QImage &)>> imageCallbackMock;
NiceMock<MockFunction<void()>> abortCallbackMock; NiceMock<MockFunction<void(QmlDesigner::ImageCache::AbortReason)>> abortCallbackMock;
NiceMock<ImageCacheCollectorMock> collectorMock; NiceMock<ImageCacheCollectorMock> collectorMock;
NiceMock<MockImageCacheStorage> storageMock; NiceMock<MockImageCacheStorage> storageMock;
QmlDesigner::ImageCacheGenerator generator{collectorMock, storageMock}; QmlDesigner::ImageCacheGenerator generator{collectorMock, storageMock};
@@ -196,12 +196,15 @@ TEST_F(ImageCacheGenerator, AbortCallback)
captureCallback(QImage{image1}, QImage{smallImage1}); captureCallback(QImage{image1}, QImage{smallImage1});
}); });
ON_CALL(collectorMock, start(Eq("name2"), _, _, _, _)) ON_CALL(collectorMock, start(Eq("name2"), _, _, _, _))
.WillByDefault([&](auto, auto, auto, auto, auto abortCallback) { abortCallback(); }); .WillByDefault([&](auto, auto, auto, auto, auto abortCallback) {
abortCallback(QmlDesigner::ImageCache::AbortReason::Failed);
});
EXPECT_CALL(imageCallbackMock, Call(_, _)).WillOnce([&](const QImage &, const QImage &) { EXPECT_CALL(imageCallbackMock, Call(_, _)).WillOnce([&](const QImage &, const QImage &) {
notification.notify(); notification.notify();
}); });
EXPECT_CALL(abortCallbackMock, Call()).WillOnce([&]() { notification.notify(); }); EXPECT_CALL(abortCallbackMock, Call(Eq(QmlDesigner::ImageCache::AbortReason::Failed)))
.WillOnce([&](auto) { notification.notify(); });
generator.generateImage( generator.generateImage(
"name", {}, {}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction(), {}); "name", {}, {}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction(), {});
@@ -210,10 +213,29 @@ TEST_F(ImageCacheGenerator, AbortCallback)
notification.wait(2); notification.wait(2);
} }
TEST_F(ImageCacheGenerator, StoreNullImageForAbortCallback) TEST_F(ImageCacheGenerator, StoreNullImageForAbortCallbackAbort)
{
ON_CALL(collectorMock, start(Eq("name"), _, _, _, _))
.WillByDefault([&](auto, auto, auto, auto, auto abortCallback) {
abortCallback(QmlDesigner::ImageCache::AbortReason::Abort);
});
ON_CALL(collectorMock, start(Eq("dummyNotify"), _, _, _, _))
.WillByDefault([&](auto, auto, auto, auto, auto) { notification.notify(); });
EXPECT_CALL(storageMock, storeImage(Eq("name"), _, _, _)).Times(0);
generator.generateImage(
"name", {}, {11}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction(), {});
generator.generateImage("dummyNotify", {}, {}, {}, {}, {});
notification.wait();
}
TEST_F(ImageCacheGenerator, DontStoreNullImageForAbortCallbackFailed)
{ {
ON_CALL(collectorMock, start(_, _, _, _, _)) ON_CALL(collectorMock, start(_, _, _, _, _))
.WillByDefault([&](auto, auto, auto, auto, auto abortCallback) { abortCallback(); }); .WillByDefault([&](auto, auto, auto, auto, auto abortCallback) {
abortCallback(QmlDesigner::ImageCache::AbortReason::Failed);
});
EXPECT_CALL(storageMock, EXPECT_CALL(storageMock,
storeImage(Eq("name"), Eq(Sqlite::TimeStamp{11}), Eq(QImage{}), Eq(QImage{}))) storeImage(Eq("name"), Eq(Sqlite::TimeStamp{11}), Eq(QImage{}), Eq(QImage{})))
@@ -231,7 +253,8 @@ TEST_F(ImageCacheGenerator, AbortForEmptyImage)
captureCallback(QImage{}, QImage{}); captureCallback(QImage{}, QImage{});
}); });
EXPECT_CALL(abortCallbackMock, Call()).WillOnce([&]() { notification.notify(); }); EXPECT_CALL(abortCallbackMock, Call(Eq(QmlDesigner::ImageCache::AbortReason::Failed)))
.WillOnce([&](auto) { notification.notify(); });
generator.generateImage( generator.generateImage(
"name", {}, {}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction(), {}); "name", {}, {}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction(), {});
@@ -264,7 +287,8 @@ TEST_F(ImageCacheGenerator, CleanIsCallingAbortCallback)
generator.generateImage( generator.generateImage(
"name2", {}, {11}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction(), {}); "name2", {}, {11}, imageCallbackMock.AsStdFunction(), abortCallbackMock.AsStdFunction(), {});
EXPECT_CALL(abortCallbackMock, Call()).Times(AtLeast(1)); EXPECT_CALL(abortCallbackMock, Call(Eq(QmlDesigner::ImageCache::AbortReason::Abort)))
.Times(AtLeast(1));
generator.clean(); generator.clean();
waitInThread.notify(); waitInThread.notify();
@@ -401,9 +425,11 @@ TEST_F(ImageCacheGenerator, UseLastTimeStampIfTasksAreMerged)
ON_CALL(collectorMock, start(Eq("notificationDummy"), _, _, _, _)) ON_CALL(collectorMock, start(Eq("notificationDummy"), _, _, _, _))
.WillByDefault([&](auto, auto, auto, auto, auto) { notification.notify(); }); .WillByDefault([&](auto, auto, auto, auto, auto) { notification.notify(); });
ON_CALL(collectorMock, start(Eq("name"), _, _, _, _)) ON_CALL(collectorMock, start(Eq("name"), _, _, _, _))
.WillByDefault([&](auto, auto, auto, auto, auto abortCallback) { abortCallback(); }); .WillByDefault([&](auto, auto, auto, auto, auto abortCallback) {
abortCallback(QmlDesigner::ImageCache::AbortReason::Failed);
});
EXPECT_CALL(storageMock, storeImage(Eq("name"), _, _, _)); EXPECT_CALL(storageMock, storeImage(Eq("name"), Eq(Sqlite::TimeStamp{4}), _, _));
generator.generateImage("waitDummy", {}, {}, {}, {}, {}); generator.generateImage("waitDummy", {}, {}, {}, {}, {});
generator.generateImage("name", {}, {3}, {}, abortCallbackMock.AsStdFunction(), {}); generator.generateImage("name", {}, {3}, {}, abortCallbackMock.AsStdFunction(), {});
@@ -438,16 +464,18 @@ TEST_F(ImageCacheGenerator, MergeCaptureCallbackIfTasksAreMerged)
TEST_F(ImageCacheGenerator, MergeAbortCallbackIfTasksAreMerged) TEST_F(ImageCacheGenerator, MergeAbortCallbackIfTasksAreMerged)
{ {
NiceMock<MockFunction<void()>> newerAbortCallbackMock; NiceMock<MockFunction<void(QmlDesigner::ImageCache::AbortReason)>> newerAbortCallbackMock;
ON_CALL(collectorMock, start(Eq("waitDummy"), _, _, _, _)) ON_CALL(collectorMock, start(Eq("waitDummy"), _, _, _, _))
.WillByDefault([&](auto, auto, auto, auto, auto) { waitInThread.wait(); }); .WillByDefault([&](auto, auto, auto, auto, auto) { waitInThread.wait(); });
ON_CALL(collectorMock, start(Eq("notificationDummy"), _, _, _, _)) ON_CALL(collectorMock, start(Eq("notificationDummy"), _, _, _, _))
.WillByDefault([&](auto, auto, auto, auto, auto) { notification.notify(); }); .WillByDefault([&](auto, auto, auto, auto, auto) { notification.notify(); });
ON_CALL(collectorMock, start(Eq("name"), _, _, _, _)) ON_CALL(collectorMock, start(Eq("name"), _, _, _, _))
.WillByDefault([&](auto, auto, auto, auto, auto abortCallback) { abortCallback(); }); .WillByDefault([&](auto, auto, auto, auto, auto abortCallback) {
abortCallback(QmlDesigner::ImageCache::AbortReason::Failed);
});
EXPECT_CALL(abortCallbackMock, Call()); EXPECT_CALL(abortCallbackMock, Call(Eq(QmlDesigner::ImageCache::AbortReason::Failed)));
EXPECT_CALL(newerAbortCallbackMock, Call()); EXPECT_CALL(newerAbortCallbackMock, Call(Eq(QmlDesigner::ImageCache::AbortReason::Failed)));
generator.generateImage("waitDummy", {}, {}, {}, {}, {}); generator.generateImage("waitDummy", {}, {}, {}, {}, {});
generator.generateImage("name", {}, {}, {}, abortCallbackMock.AsStdFunction(), {}); generator.generateImage("name", {}, {}, {}, abortCallbackMock.AsStdFunction(), {});

View File

@@ -37,8 +37,8 @@ public:
(Utils::SmallStringView name, (Utils::SmallStringView name,
Utils::SmallStringView state, Utils::SmallStringView state,
Sqlite::TimeStamp timeStamp, Sqlite::TimeStamp timeStamp,
CaptureCallback &&captureCallback, QmlDesigner::ImageCache::CaptureImageWithSmallImageCallback &&captureCallback,
AbortCallback &&abortCallback, QmlDesigner::ImageCache::AbortCallback &&abortCallback,
QmlDesigner::ImageCache::AuxiliaryData &&auxiliaryData), QmlDesigner::ImageCache::AuxiliaryData &&auxiliaryData),
(override)); (override));
MOCK_METHOD(void, clean, (), (override)); MOCK_METHOD(void, clean, (), (override));