diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachedispatchcollector.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachedispatchcollector.h new file mode 100644 index 00000000000..d0f0872f200 --- /dev/null +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachedispatchcollector.h @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "imagecachecollectorinterface.h" + +namespace QmlDesigner { + +template +class ImageCacheDispatchCollector final : public ImageCacheCollectorInterface +{ +public: + ImageCacheDispatchCollector(CollectorEntries collectors) + : m_collectors{std::move(collectors)} {}; + + void start(Utils::SmallStringView filePath, + Utils::SmallStringView state, + const ImageCache::AuxiliaryData &auxiliaryData, + CaptureCallback captureCallback, + AbortCallback abortCallback) override + { + std::apply( + [&](const auto &...collectors) { + dispatchStart(filePath, + state, + auxiliaryData, + std::move(captureCallback), + std::move(abortCallback), + collectors...); + }, + m_collectors); + } + + std::pair createImage(Utils::SmallStringView filePath, + Utils::SmallStringView state, + const ImageCache::AuxiliaryData &auxiliaryData) override + { + return std::apply( + [&](const auto &...entries) { + return dispatchCreateImage(filePath, state, auxiliaryData, entries...); + }, + m_collectors); + } + + QIcon createIcon(Utils::SmallStringView filePath, + Utils::SmallStringView state, + const ImageCache::AuxiliaryData &auxiliaryData) override + { + return std::apply( + [&](const auto &...entries) { + return dispatchCreateIcon(filePath, state, auxiliaryData, entries...); + }, + m_collectors); + } + +private: + template + void dispatchStart(Utils::SmallStringView filePath, + Utils::SmallStringView state, + const ImageCache::AuxiliaryData &auxiliaryData, + CaptureCallback captureCallback, + AbortCallback abortCallback, + const Collector &collector, + const Collectors &...collectors) + { + if (collector.first(filePath, state, auxiliaryData)) { + collector.second->start(filePath, + state, + auxiliaryData, + std::move(captureCallback), + std::move(abortCallback)); + } else { + dispatchStart(filePath, + state, + auxiliaryData, + std::move(captureCallback), + std::move(abortCallback), + collectors...); + } + } + + void dispatchStart(Utils::SmallStringView, + Utils::SmallStringView, + const ImageCache::AuxiliaryData &, + CaptureCallback, + AbortCallback) + { + qWarning() << "ImageCacheDispatchCollector: cannot handle file type."; + } + + template + QIcon dispatchCreateIcon(Utils::SmallStringView filePath, + Utils::SmallStringView state, + const ImageCache::AuxiliaryData &auxiliaryData, + const Collector &collector, + const Collectors &...collectors) + { + if (collector.first(filePath, state, auxiliaryData)) { + return collector.second->createIcon(filePath, state, auxiliaryData); + } + + return dispatchCreateIcon(filePath, state, auxiliaryData, collectors...); + } + + QIcon dispatchCreateIcon(Utils::SmallStringView, + Utils::SmallStringView, + const ImageCache::AuxiliaryData &) + { + qWarning() << "ImageCacheDispatchCollector: cannot handle file type."; + + return {}; + } + + template + std::pair dispatchCreateImage(Utils::SmallStringView filePath, + Utils::SmallStringView state, + const ImageCache::AuxiliaryData &auxiliaryData, + const Collector &collector, + const Collectors &...collectors) + { + if (collector.first(filePath, state, auxiliaryData)) { + return collector.second->createImage(filePath, state, auxiliaryData); + } + + return dispatchCreateImage(filePath, state, auxiliaryData, collectors...); + } + + std::pair dispatchCreateImage(Utils::SmallStringView, + Utils::SmallStringView, + const ImageCache::AuxiliaryData &) + { + qWarning() << "ImageCacheDispatchCollector: cannot handle file type."; + + return {}; + } + +private: + CollectorEntries m_collectors; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/include/viewmanager.h b/src/plugins/qmldesigner/designercore/include/viewmanager.h index 1be785655a2..dd77c07f459 100644 --- a/src/plugins/qmldesigner/designercore/include/viewmanager.h +++ b/src/plugins/qmldesigner/designercore/include/viewmanager.h @@ -51,8 +51,7 @@ class ViewManagerData; class QMLDESIGNERCORE_EXPORT ViewManager { public: - ViewManager(class AsynchronousImageCache &imageCache, - class AsynchronousImageCache &meshImageCache); + ViewManager(class AsynchronousImageCache &imageCache); ~ViewManager(); void attachRewriterView(); diff --git a/src/plugins/qmldesigner/designercore/model/viewmanager.cpp b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp index d1b53b05ae2..d713d16bf53 100644 --- a/src/plugins/qmldesigner/designercore/model/viewmanager.cpp +++ b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp @@ -62,9 +62,9 @@ static Q_LOGGING_CATEGORY(viewBenchmark, "qtc.viewmanager.attach", QtWarningMsg) class ViewManagerData { public: - ViewManagerData(AsynchronousImageCache &imageCache, AsynchronousImageCache &meshImageCache) + ViewManagerData(AsynchronousImageCache &imageCache) : itemLibraryView(imageCache) - , propertyEditorView(meshImageCache) + , propertyEditorView(imageCache) {} InteractiveConnectionManager connectionManager; @@ -95,8 +95,8 @@ static CrumbleBar *crumbleBar() { return QmlDesignerPlugin::instance()->mainWidget()->crumbleBar(); } -ViewManager::ViewManager(AsynchronousImageCache &imageCache, AsynchronousImageCache &meshImageCache) - : d(std::make_unique(imageCache, meshImageCache)) +ViewManager::ViewManager(AsynchronousImageCache &imageCache) + : d(std::make_unique(imageCache)) { d->formEditorView.setGotoErrorCallback([this](int line, int column) { d->textEditorView.gotoCursorPosition(line, column); diff --git a/src/plugins/qmldesigner/qmldesignercore.cmake b/src/plugins/qmldesigner/qmldesignercore.cmake index 6fb21afc490..e6031f3efbf 100644 --- a/src/plugins/qmldesigner/qmldesignercore.cmake +++ b/src/plugins/qmldesigner/qmldesignercore.cmake @@ -125,6 +125,7 @@ function(extend_with_qmldesigner_core target_name) imagecache/asynchronousimagefactory.h imagecache/imagecachecollector.cpp imagecache/imagecachecollector.h + imagecache/imagecachedispatchcollector.h imagecache/imagecachecollectorinterface.h imagecache/imagecacheconnectionmanager.cpp imagecache/imagecacheconnectionmanager.h diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index 331c8e7852f..131bedac04d 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -135,8 +135,7 @@ class QmlDesignerPluginPrivate { public: QmlDesignerProjectManager projectManager; - ViewManager viewManager{projectManager.asynchronousImageCache(), - projectManager.asynchronousMeshImageCache()}; + ViewManager viewManager{projectManager.asynchronousImageCache()}; DocumentManager documentManager; ShortCutManager shortCutManager; SettingsPage settingsPage; diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index a32bd8988c6..7376b90ea59 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -438,6 +438,7 @@ Project { "imagecache/imagecachecollectorinterface.h", "imagecache/imagecacheconnectionmanager.cpp", "imagecache/imagecacheconnectionmanager.h", + "imagecache/imagecachedispatchcollector.h, "imagecache/imagecachegeneratorinterface.h", "imagecache/imagecachegenerator.cpp", "imagecache/imagecachegenerator.h", diff --git a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp index b685d6feb14..12031a3a34e 100644 --- a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp +++ b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,23 @@ public: } }; +auto makeCollecterDispatcherChain(ImageCacheCollector &nodeInstanceCollector, + MeshImageCacheCollector &meshImageCollector) +{ + return std::make_tuple( + std::make_pair([](Utils::SmallStringView filePath, + [[maybe_unused]] Utils::SmallStringView state, + [[maybe_unused]] const QmlDesigner::ImageCache::AuxiliaryData + &auxiliaryData) { return filePath.endsWith(".qml"); }, + &nodeInstanceCollector), + std::make_pair( + [](Utils::SmallStringView filePath, + [[maybe_unused]] Utils::SmallStringView state, + [[maybe_unused]] const QmlDesigner::ImageCache::AuxiliaryData &auxiliaryData) { + return filePath.endsWith(".mesh") || filePath.startsWith("#"); + }, + &meshImageCollector)); +} } // namespace class QmlDesignerProjectManager::ImageCacheData @@ -109,12 +127,13 @@ public: ImageCacheStorage storage{database}; ImageCacheConnectionManager connectionManager; MeshImageCacheCollector meshImageCollector{connectionManager, QSize{300, 300}, QSize{600, 600}}; - ImageCacheGenerator meshGenerator{meshImageCollector, storage}; ImageCacheCollector nodeInstanceCollector{connectionManager, QSize{300, 300}, QSize{600, 600}}; - ImageCacheGenerator nodeInstanceGenerator{nodeInstanceCollector, storage}; + ImageCacheDispatchCollector + dispatchCollector{makeCollecterDispatcherChain(nodeInstanceCollector, meshImageCollector)}; + ImageCacheGenerator generator{dispatchCollector, storage}; TimeStampProvider timeStampProvider; - AsynchronousImageCache asynchronousImageCache{storage, nodeInstanceGenerator, timeStampProvider}; - AsynchronousImageCache asynchronousMeshImageCache{storage, meshGenerator, timeStampProvider}; + AsynchronousImageCache asynchronousImageCache{storage, generator, timeStampProvider}; }; class QmlDesignerProjectManager::PreviewImageCacheData @@ -213,11 +232,6 @@ AsynchronousImageCache &QmlDesignerProjectManager::asynchronousImageCache() return imageCacheData()->asynchronousImageCache; } -AsynchronousImageCache &QmlDesignerProjectManager::asynchronousMeshImageCache() -{ - return imageCacheData()->asynchronousMeshImageCache; -} - void QmlDesignerProjectManager::editorOpened(::Core::IEditor *) {} void QmlDesignerProjectManager::currentEditorChanged(::Core::IEditor *) diff --git a/src/plugins/qmldesigner/qmldesignerprojectmanager.h b/src/plugins/qmldesigner/qmldesignerprojectmanager.h index 88414cc4bb8..b3567d3b127 100644 --- a/src/plugins/qmldesigner/qmldesignerprojectmanager.h +++ b/src/plugins/qmldesigner/qmldesignerprojectmanager.h @@ -59,7 +59,6 @@ public: void registerPreviewImageProvider(QQmlEngine *engine) const; class AsynchronousImageCache &asynchronousImageCache(); - class AsynchronousImageCache &asynchronousMeshImageCache(); private: void editorOpened(::Core::IEditor *editor); diff --git a/tests/unit/unittest/CMakeLists.txt b/tests/unit/unittest/CMakeLists.txt index 1408ebf3c35..61c8f0802a7 100644 --- a/tests/unit/unittest/CMakeLists.txt +++ b/tests/unit/unittest/CMakeLists.txt @@ -81,6 +81,7 @@ add_qtc_test(unittest GTEST synchronousimagecache-test.cpp imagecachegenerator-test.cpp imagecachestorage-test.cpp + imagecachedispatchcollector-test.cpp sqlitedatabasemock.h sqlitereadstatementmock.cpp sqlitereadstatementmock.h sqlitereadwritestatementmock.cpp @@ -191,6 +192,7 @@ extend_qtc_test(unittest imagecache/imagecachegenerator.h imagecache/imagecachegeneratorinterface.h imagecache/imagecachestorage.h + imagecache/imagecachedispatchcollector.h imagecache/imagecachestorageinterface.h imagecache/synchronousimagecache.cpp imagecache/timestampproviderinterface.h diff --git a/tests/unit/unittest/imagecachedispatchcollector-test.cpp b/tests/unit/unittest/imagecachedispatchcollector-test.cpp new file mode 100644 index 00000000000..0bd98d0d709 --- /dev/null +++ b/tests/unit/unittest/imagecachedispatchcollector-test.cpp @@ -0,0 +1,408 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include "imagecachecollectormock.h" + +#include +#include + +#include + +namespace { +using QmlDesigner::ImageCache::FontCollectorSizesAuxiliaryData; + +MATCHER_P(IsIcon, icon, std::string(negation ? "isn't " : "is ") + PrintToString(icon)) +{ + const QIcon &other = arg; + return icon.availableSizes() == other.availableSizes(); +} + +MATCHER_P2(IsImage, + image, + smallImage, + std::string(negation ? "aren't " : "are ") + PrintToString(image) + " and " + + PrintToString(smallImage)) +{ + const std::pair &other = arg; + return other.first == image && other.second == smallImage; +} + +class ImageCacheDispatchCollector : public ::testing::Test +{ +protected: + ImageCacheDispatchCollector() + { + ON_CALL(collectorMock1, createIcon(_, _, _)).WillByDefault(Return(icon1)); + ON_CALL(collectorMock2, createIcon(_, _, _)).WillByDefault(Return(icon2)); + + ON_CALL(collectorMock1, createImage(_, _, _)) + .WillByDefault(Return(std::pair{image1, smallImage1})); + ON_CALL(collectorMock2, createImage(_, _, _)) + .WillByDefault(Return(std::pair{image2, smallImage2})); + } + +protected: + std::vector sizes{{20, 11}}; + NiceMock> captureCallbackMock; + NiceMock> abortCallbackMock; + NiceMock collectorMock1; + NiceMock collectorMock2; + QImage image1{1, 1, QImage::Format_ARGB32}; + QImage image2{2, 2, QImage::Format_ARGB32}; + QImage smallImage1{1, 1, QImage::Format_ARGB32}; + QImage smallImage2{2, 1, QImage::Format_ARGB32}; + QIcon icon1{QPixmap::fromImage(image1)}; + QIcon icon2{QPixmap::fromImage(image2)}; +}; + +TEST_F(ImageCacheDispatchCollector, CallQmlCollectorStart) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair( + [](Utils::SmallStringView filePath, + [[maybe_unused]] Utils::SmallStringView state, + [[maybe_unused]] const QmlDesigner::ImageCache::AuxiliaryData &auxiliaryData) { + Utils::SmallStringView ending = ".ui.qml"; + return filePath.size() > ending.size() + && std::equal(ending.rbegin(), ending.rend(), filePath.rbegin()); + }, + &collectorMock1), + std::make_pair( + [](Utils::SmallStringView filePath, + [[maybe_unused]] Utils::SmallStringView state, + [[maybe_unused]] const QmlDesigner::ImageCache::AuxiliaryData &auxiliaryData) { + Utils::SmallStringView ending = ".qml"; + return filePath.size() > ending.size() + && std::equal(ending.rbegin(), ending.rend(), filePath.rbegin()); + }, + &collectorMock2))}; + + EXPECT_CALL(captureCallbackMock, Call(_, _)); + EXPECT_CALL(abortCallbackMock, Call(_)); + EXPECT_CALL(collectorMock2, + start(Eq("foo.qml"), + Eq("state"), + VariantWith( + AllOf(Field(&FontCollectorSizesAuxiliaryData::sizes, + ElementsAre(QSize{20, 11})), + Field(&FontCollectorSizesAuxiliaryData::colorName, Eq(u"color")))), + _, + _)) + .WillRepeatedly([&](auto, auto, auto, auto captureCallback, auto abortCallback) { + captureCallback(QImage{}, QImage{}); + abortCallback(QmlDesigner::ImageCache::AbortReason::Abort); + }); + EXPECT_CALL(collectorMock1, start(_, _, _, _, _)).Times(0); + + collector.start("foo.qml", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}, + captureCallbackMock.AsStdFunction(), + abortCallbackMock.AsStdFunction()); +} + +TEST_F(ImageCacheDispatchCollector, CallUiFileCollectorStart) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock2))}; + + EXPECT_CALL(captureCallbackMock, Call(_, _)); + EXPECT_CALL(abortCallbackMock, Call(_)); + EXPECT_CALL(collectorMock1, + start(Eq("foo.ui.qml"), + Eq("state"), + VariantWith( + AllOf(Field(&FontCollectorSizesAuxiliaryData::sizes, + ElementsAre(QSize{20, 11})), + Field(&FontCollectorSizesAuxiliaryData::colorName, Eq(u"color")))), + _, + _)) + .WillRepeatedly([&](auto, auto, auto, auto captureCallback, auto abortCallback) { + captureCallback(QImage{}, QImage{}); + abortCallback(QmlDesigner::ImageCache::AbortReason::Abort); + }); + EXPECT_CALL(collectorMock2, start(_, _, _, _, _)).Times(0); + + collector.start("foo.ui.qml", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}, + captureCallbackMock.AsStdFunction(), + abortCallbackMock.AsStdFunction()); +} + +TEST_F(ImageCacheDispatchCollector, DontCallCollectorStartForUnknownFile) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return false; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return false; }, + &collectorMock2))}; + + EXPECT_CALL(collectorMock2, start(_, _, _, _, _)).Times(0); + EXPECT_CALL(collectorMock1, start(_, _, _, _, _)).Times(0); + + collector.start("foo.mesh", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}, + captureCallbackMock.AsStdFunction(), + abortCallbackMock.AsStdFunction()); +} + +TEST_F(ImageCacheDispatchCollector, CallFirstCollectorCreateIcon) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock2))}; + + auto icon = collector.createIcon("foo.ui.qml", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}); + + ASSERT_THAT(icon, IsIcon(icon1)); +} + +TEST_F(ImageCacheDispatchCollector, FirstCollectorCreateIconCalls) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock2))}; + + EXPECT_CALL(collectorMock1, + createIcon(Eq("foo.ui.qml"), + Eq("state"), + VariantWith( + AllOf(Field(&FontCollectorSizesAuxiliaryData::sizes, + ElementsAre(QSize{20, 11})), + Field(&FontCollectorSizesAuxiliaryData::colorName, + Eq(u"color")))))); + EXPECT_CALL(collectorMock2, createIcon(_, _, _)).Times(0); + + auto icon = collector.createIcon("foo.ui.qml", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}); +} + +TEST_F(ImageCacheDispatchCollector, CallSecondCollectorCreateIcon) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return false; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock2))}; + + auto icon = collector.createIcon("foo.qml", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}); + + ASSERT_THAT(icon, IsIcon(icon2)); +} + +TEST_F(ImageCacheDispatchCollector, SecondCollectorCreateIconCalls) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return false; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock2))}; + + EXPECT_CALL(collectorMock2, + createIcon(Eq("foo.qml"), + Eq("state"), + VariantWith( + AllOf(Field(&FontCollectorSizesAuxiliaryData::sizes, + ElementsAre(QSize{20, 11})), + Field(&FontCollectorSizesAuxiliaryData::colorName, + Eq(u"color")))))); + EXPECT_CALL(collectorMock1, createIcon(_, _, _)).Times(0); + + auto icon = collector.createIcon("foo.qml", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}); +} + +TEST_F(ImageCacheDispatchCollector, DontCallCollectorCreateIconForUnknownFile) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return false; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return false; }, + &collectorMock2))}; + + auto icon = collector.createIcon("foo.mesh", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}); + + ASSERT_TRUE(icon.isNull()); +} + +TEST_F(ImageCacheDispatchCollector, CallFirstCollectorCreateImage) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock2))}; + + auto image = collector.createImage("foo.qml", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}); + + ASSERT_THAT(image, IsImage(image1, smallImage1)); +} + +TEST_F(ImageCacheDispatchCollector, FirstCollectorCreateImageCalls) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock2))}; + + EXPECT_CALL(collectorMock1, + createImage(Eq("foo.ui.qml"), + Eq("state"), + VariantWith( + AllOf(Field(&FontCollectorSizesAuxiliaryData::sizes, + ElementsAre(QSize{20, 11})), + Field(&FontCollectorSizesAuxiliaryData::colorName, + Eq(u"color")))))); + EXPECT_CALL(collectorMock2, createImage(_, _, _)).Times(0); + + auto icon = collector.createImage("foo.ui.qml", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}); +} + +TEST_F(ImageCacheDispatchCollector, CallSecondCollectorCreateImage) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return false; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock2))}; + + auto image = collector.createImage("foo.ui.qml", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}); + + ASSERT_THAT(image, IsImage(image2, smallImage2)); +} + +TEST_F(ImageCacheDispatchCollector, SecondCollectorCreateImageCalls) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return false; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return true; }, + &collectorMock2))}; + + EXPECT_CALL(collectorMock2, + createImage(Eq("foo.qml"), + Eq("state"), + VariantWith( + AllOf(Field(&FontCollectorSizesAuxiliaryData::sizes, + ElementsAre(QSize{20, 11})), + Field(&FontCollectorSizesAuxiliaryData::colorName, + Eq(u"color")))))); + EXPECT_CALL(collectorMock1, createImage(_, _, _)).Times(0); + + auto icon = collector.createImage("foo.qml", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}); +} + +TEST_F(ImageCacheDispatchCollector, DontCallCollectorCreateImageForUnknownFile) +{ + QmlDesigner::ImageCacheDispatchCollector collector{std::make_tuple( + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return false; }, + &collectorMock1), + std::make_pair([](Utils::SmallStringView, + Utils::SmallStringView, + const QmlDesigner::ImageCache::AuxiliaryData &) { return false; }, + &collectorMock2))}; + + auto image = collector.createImage("foo.mesh", + "state", + FontCollectorSizesAuxiliaryData{sizes, "color", "text"}); + + ASSERT_TRUE(image.first.isNull() && image.second.isNull()); +} + +} // namespace