QmlDesigner: Refactor ImageCache

Move the ImageCache from the ItemLibraryView to a
more centralized location.

Change-Id: Ic0721976650dad8af26c29b50fed8aec0fffbf75
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
Henning Gruendl
2022-05-25 17:04:20 +02:00
committed by Henning Gründl
parent 449334e419
commit 0a84ef4b2c
9 changed files with 101 additions and 127 deletions

View File

@@ -30,12 +30,6 @@
#include <asynchronousimagecache.h> #include <asynchronousimagecache.h>
#include <bindingproperty.h> #include <bindingproperty.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <imagecache/imagecachecollector.h>
#include <imagecache/imagecacheconnectionmanager.h>
#include <imagecache/imagecachefontcollector.h>
#include <imagecache/imagecachegenerator.h>
#include <imagecache/imagecachestorage.h>
#include <imagecache/timestampprovider.h>
#include <import.h> #include <import.h>
#include <nodelistproperty.h> #include <nodelistproperty.h>
#include <projectexplorer/kit.h> #include <projectexplorer/kit.h>
@@ -44,7 +38,6 @@
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <rewriterview.h> #include <rewriterview.h>
#include <sqlitedatabase.h> #include <sqlitedatabase.h>
#include <synchronousimagecache.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <qmlitemnode.h> #include <qmlitemnode.h>
@@ -52,38 +45,9 @@
namespace QmlDesigner { namespace QmlDesigner {
namespace { ItemLibraryView::ItemLibraryView(AsynchronousImageCache &imageCache)
ProjectExplorer::Target *activeTarget(ProjectExplorer::Project *project) : AbstractView()
{ , m_imageCache(imageCache)
if (project)
return project->activeTarget();
return {};
}
} // namespace
class ItemLibraryView::ImageCacheData
{
public:
Sqlite::Database database{Utils::PathString{
Core::ICore::cacheResourcePath("imagecache-v2.db").toString()},
Sqlite::JournalMode::Wal,
Sqlite::LockingMode::Normal};
ImageCacheStorage<Sqlite::Database> storage{database};
ImageCacheConnectionManager connectionManager;
ImageCacheCollector collector{connectionManager, QSize{300, 300}, QSize{600, 600}};
ImageCacheFontCollector fontCollector;
ImageCacheGenerator generator{collector, storage};
ImageCacheGenerator fontGenerator{fontCollector, storage};
TimeStampProvider timeStampProvider;
AsynchronousImageCache cache{storage, generator, timeStampProvider};
AsynchronousImageCache asynchronousFontImageCache{storage, fontGenerator, timeStampProvider};
SynchronousImageCache synchronousFontImageCache{storage, timeStampProvider, fontCollector};
};
ItemLibraryView::ItemLibraryView(QObject* parent)
: AbstractView(parent)
{} {}
ItemLibraryView::~ItemLibraryView() ItemLibraryView::~ItemLibraryView()
@@ -97,11 +61,8 @@ bool ItemLibraryView::hasWidget() const
WidgetInfo ItemLibraryView::widgetInfo() WidgetInfo ItemLibraryView::widgetInfo()
{ {
if (m_widget.isNull()) { if (m_widget.isNull())
m_widget = new ItemLibraryWidget{imageCacheData()->cache, m_widget = new ItemLibraryWidget{m_imageCache};
imageCacheData()->asynchronousFontImageCache,
imageCacheData()->synchronousFontImageCache};
}
return createWidgetInfo(m_widget.data(), return createWidgetInfo(m_widget.data(),
new WidgetInfo::ToolBarWidgetDefaultFactory<ItemLibraryWidget>(m_widget.data()), new WidgetInfo::ToolBarWidgetDefaultFactory<ItemLibraryWidget>(m_widget.data()),
@@ -182,43 +143,6 @@ void ItemLibraryView::usedImportsChanged(const QList<Import> &usedImports)
m_widget->updateUsedImports(usedImports); m_widget->updateUsedImports(usedImports);
} }
ItemLibraryView::ImageCacheData *ItemLibraryView::imageCacheData()
{
std::call_once(imageCacheFlag, [this]() {
m_imageCacheData = std::make_unique<ImageCacheData>();
auto setTargetInImageCache =
[imageCacheData = m_imageCacheData.get()](ProjectExplorer::Target *target) {
if (target == imageCacheData->collector.target())
return;
if (target)
imageCacheData->cache.clean();
imageCacheData->collector.setTarget(target);
};
if (auto project = ProjectExplorer::SessionManager::startupProject(); project) {
m_imageCacheData->collector.setTarget(project->activeTarget());
connect(project,
&ProjectExplorer::Project::activeTargetChanged,
this,
setTargetInImageCache);
}
connect(ProjectExplorer::SessionManager::instance(),
&ProjectExplorer::SessionManager::startupProjectChanged,
this,
[=](ProjectExplorer::Project *project) {
setTargetInImageCache(activeTarget(project));
});
});
return m_imageCacheData.get();
}
AsynchronousImageCache &ItemLibraryView::imageCache()
{
return imageCacheData()->cache;
}
void ItemLibraryView::documentMessagesChanged(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &) void ItemLibraryView::documentMessagesChanged(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &)
{ {
if (m_hasErrors && errors.isEmpty()) if (m_hasErrors && errors.isEmpty())

View File

@@ -29,19 +29,16 @@
#include <QPointer> #include <QPointer>
#include <mutex>
namespace QmlDesigner { namespace QmlDesigner {
class ItemLibraryWidget; class ItemLibraryWidget;
class AsynchronousImageCache;
class ItemLibraryView : public AbstractView class ItemLibraryView : public AbstractView
{ {
Q_OBJECT Q_OBJECT
public: public:
ItemLibraryView(QObject* parent = nullptr); ItemLibraryView(class AsynchronousImageCache &imageCache);
~ItemLibraryView() override; ~ItemLibraryView() override;
bool hasWidget() const override; bool hasWidget() const override;
@@ -58,17 +55,11 @@ public:
void customNotification(const AbstractView *view, const QString &identifier, void customNotification(const AbstractView *view, const QString &identifier,
const QList<ModelNode> &nodeList, const QList<QVariant> &data) override; const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
AsynchronousImageCache &imageCache();
protected: protected:
void updateImports(); void updateImports();
private: private:
class ImageCacheData; AsynchronousImageCache &m_imageCache;
ImageCacheData *imageCacheData();
std::once_flag imageCacheFlag;
std::unique_ptr<ImageCacheData> m_imageCacheData;
QPointer<ItemLibraryWidget> m_widget; QPointer<ItemLibraryWidget> m_widget;
bool m_hasErrors = false; bool m_hasErrors = false;
QVariantMap m_importableExtensions3DMap; QVariantMap m_importableExtensions3DMap;

View File

@@ -140,18 +140,13 @@ void ItemLibraryWidget::resizeEvent(QResizeEvent *event)
isHorizontalLayout = event->size().width() >= HORIZONTAL_LAYOUT_WIDTH_LIMIT; isHorizontalLayout = event->size().width() >= HORIZONTAL_LAYOUT_WIDTH_LIMIT;
} }
ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache, ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache)
AsynchronousImageCache &asynchronousFontImageCache,
SynchronousImageCache &synchronousFontImageCache)
: m_itemIconSize(24, 24) : m_itemIconSize(24, 24)
, m_fontImageCache(synchronousFontImageCache)
, m_itemLibraryModel(new ItemLibraryModel(this)) , m_itemLibraryModel(new ItemLibraryModel(this))
, m_addModuleModel(new ItemLibraryAddImportModel(this)) , m_addModuleModel(new ItemLibraryAddImportModel(this))
, m_itemsWidget(new QQuickWidget(this)) , m_itemsWidget(new QQuickWidget(this))
, m_imageCache{imageCache} , m_imageCache{imageCache}
{ {
Q_UNUSED(asynchronousFontImageCache)
m_compressionTimer.setInterval(200); m_compressionTimer.setInterval(200);
m_compressionTimer.setSingleShot(true); m_compressionTimer.setSingleShot(true);
ItemLibraryModel::registerQmlTypes(); ItemLibraryModel::registerQmlTypes();

View File

@@ -56,7 +56,6 @@ class Model;
class ItemLibraryModel; class ItemLibraryModel;
class ItemLibraryAddImportModel; class ItemLibraryAddImportModel;
class ItemLibraryResourceView; class ItemLibraryResourceView;
class SynchronousImageCache;
class AsynchronousImageCache; class AsynchronousImageCache;
class ImageCacheCollector; class ImageCacheCollector;
@@ -67,9 +66,7 @@ class ItemLibraryWidget : public QFrame
public: public:
Q_PROPERTY(bool subCompEditMode READ subCompEditMode NOTIFY subCompEditModeChanged) Q_PROPERTY(bool subCompEditMode READ subCompEditMode NOTIFY subCompEditModeChanged)
ItemLibraryWidget(AsynchronousImageCache &imageCache, ItemLibraryWidget(AsynchronousImageCache &imageCache);
AsynchronousImageCache &asynchronousFontImageCache,
SynchronousImageCache &synchronousFontImageCache);
~ItemLibraryWidget(); ~ItemLibraryWidget();
void setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo); void setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo);
@@ -115,7 +112,6 @@ private:
QTimer m_compressionTimer; QTimer m_compressionTimer;
QSize m_itemIconSize; QSize m_itemIconSize;
SynchronousImageCache &m_fontImageCache;
QPointer<ItemLibraryInfo> m_itemLibraryInfo; QPointer<ItemLibraryInfo> m_itemLibraryInfo;
QPointer<ItemLibraryModel> m_itemLibraryModel; QPointer<ItemLibraryModel> m_itemLibraryModel;

View File

@@ -47,12 +47,11 @@ class Edit3DView;
namespace Internal { class DesignModeWidget; } namespace Internal { class DesignModeWidget; }
class ViewManagerData; class ViewManagerData;
class AsynchronousImageCache;
class QMLDESIGNERCORE_EXPORT ViewManager class QMLDESIGNERCORE_EXPORT ViewManager
{ {
public: public:
ViewManager(); ViewManager(class AsynchronousImageCache &imageCache);
~ViewManager(); ~ViewManager();
void attachRewriterView(); void attachRewriterView();
@@ -107,8 +106,6 @@ public:
void disableStandardViews(); void disableStandardViews();
void enableStandardViews(); void enableStandardViews();
AsynchronousImageCache &imageCache();
private: // functions private: // functions
Q_DISABLE_COPY(ViewManager) Q_DISABLE_COPY(ViewManager)

View File

@@ -62,6 +62,10 @@ static Q_LOGGING_CATEGORY(viewBenchmark, "qtc.viewmanager.attach", QtWarningMsg)
class ViewManagerData class ViewManagerData
{ {
public: public:
ViewManagerData(AsynchronousImageCache &imageCache)
: itemLibraryView(imageCache)
{}
InteractiveConnectionManager connectionManager; InteractiveConnectionManager connectionManager;
CapturingConnectionManager capturingConnectionManager; CapturingConnectionManager capturingConnectionManager;
QmlModelState savedState; QmlModelState savedState;
@@ -90,12 +94,13 @@ static CrumbleBar *crumbleBar() {
return QmlDesignerPlugin::instance()->mainWidget()->crumbleBar(); return QmlDesignerPlugin::instance()->mainWidget()->crumbleBar();
} }
ViewManager::ViewManager() ViewManager::ViewManager(AsynchronousImageCache &imageCache)
: d(std::make_unique<ViewManagerData>()) : d(std::make_unique<ViewManagerData>(imageCache))
{ {
d->formEditorView.setGotoErrorCallback([this](int line, int column) { d->formEditorView.setGotoErrorCallback([this](int line, int column) {
d->textEditorView.gotoCursorPosition(line, column); d->textEditorView.gotoCursorPosition(line, column);
if (Internal::DesignModeWidget *designModeWidget = QmlDesignerPlugin::instance()->mainWidget()) if (Internal::DesignModeWidget *designModeWidget = QmlDesignerPlugin::instance()
->mainWidget())
designModeWidget->showDockWidget("TextEditor"); designModeWidget->showDockWidget("TextEditor");
}); });
} }
@@ -438,11 +443,6 @@ void ViewManager::enableStandardViews()
attachViewsExceptRewriterAndComponetView(); attachViewsExceptRewriterAndComponetView();
} }
AsynchronousImageCache &ViewManager::imageCache()
{
return d->itemLibraryView.imageCache();
}
void ViewManager::addView(std::unique_ptr<AbstractView> &&view) void ViewManager::addView(std::unique_ptr<AbstractView> &&view)
{ {
d->additionalViews.push_back(std::move(view)); d->additionalViews.push_back(std::move(view));

View File

@@ -137,7 +137,7 @@ class QmlDesignerPluginPrivate
{ {
public: public:
QmlDesignerProjectManager projectManager; QmlDesignerProjectManager projectManager;
ViewManager viewManager; ViewManager viewManager{projectManager.asynchronousImageCache()};
DocumentManager documentManager; DocumentManager documentManager;
ShortCutManager shortCutManager; ShortCutManager shortCutManager;
SettingsPage settingsPage; SettingsPage settingsPage;
@@ -670,7 +670,7 @@ void QmlDesignerPlugin::emitUsageStatisticsHelpRequested(const QString &identifi
AsynchronousImageCache &QmlDesignerPlugin::imageCache() AsynchronousImageCache &QmlDesignerPlugin::imageCache()
{ {
return m_instance->d->viewManager.imageCache(); return m_instance->d->projectManager.asynchronousImageCache();
} }
void QmlDesignerPlugin::registerPreviewImageProvider(QQmlEngine *engine) void QmlDesignerPlugin::registerPreviewImageProvider(QQmlEngine *engine)

View File

@@ -44,6 +44,7 @@
#include <qtsupport/qtkitinformation.h> #include <qtsupport/qtkitinformation.h>
#include <asynchronousexplicitimagecache.h> #include <asynchronousexplicitimagecache.h>
#include <asynchronousimagecache.h>
#include <imagecache/asynchronousimagefactory.h> #include <imagecache/asynchronousimagefactory.h>
#include <imagecache/explicitimagecacheimageprovider.h> #include <imagecache/explicitimagecacheimageprovider.h>
#include <imagecache/imagecachecollector.h> #include <imagecache/imagecachecollector.h>
@@ -60,6 +61,14 @@ namespace QmlDesigner {
namespace { namespace {
ProjectExplorer::Target *activeTarget(ProjectExplorer::Project *project)
{
if (project)
return project->activeTarget();
return {};
}
QString defaultImagePath() QString defaultImagePath()
{ {
return Core::ICore::resourcePath("qmldesigner/welcomepage/images/newThumbnail.png").toString(); return Core::ICore::resourcePath("qmldesigner/welcomepage/images/newThumbnail.png").toString();
@@ -89,7 +98,22 @@ public:
} // namespace } // namespace
class PreviewImageCacheData class QmlDesignerProjectManager::ImageCacheData
{
public:
Sqlite::Database database{Utils::PathString{
Core::ICore::cacheResourcePath("imagecache-v2.db").toString()},
Sqlite::JournalMode::Wal,
Sqlite::LockingMode::Normal};
ImageCacheStorage<Sqlite::Database> storage{database};
ImageCacheConnectionManager connectionManager;
ImageCacheCollector collector{connectionManager, QSize{300, 300}, QSize{600, 600}};
ImageCacheGenerator generator{collector, storage};
TimeStampProvider timeStampProvider;
AsynchronousImageCache asynchronousImageCache{storage, generator, timeStampProvider};
};
class QmlDesignerProjectManager::PreviewImageCacheData
{ {
public: public:
Sqlite::Database database{Utils::PathString{ Sqlite::Database database{Utils::PathString{
@@ -100,7 +124,7 @@ public:
AsynchronousExplicitImageCache cache{storage}; AsynchronousExplicitImageCache cache{storage};
}; };
class QmlDesignerProjectManagerProjectData class QmlDesignerProjectManager::QmlDesignerProjectManagerProjectData
{ {
public: public:
QmlDesignerProjectManagerProjectData(ImageCacheStorage<Sqlite::Database> &storage) QmlDesignerProjectManagerProjectData(ImageCacheStorage<Sqlite::Database> &storage)
@@ -117,7 +141,7 @@ public:
}; };
QmlDesignerProjectManager::QmlDesignerProjectManager() QmlDesignerProjectManager::QmlDesignerProjectManager()
: m_imageCacheData{std::make_unique<PreviewImageCacheData>()} : m_previewImageCacheData{std::make_unique<PreviewImageCacheData>()}
{ {
auto editorManager = ::Core::EditorManager::instance(); auto editorManager = ::Core::EditorManager::instance();
QObject::connect(editorManager, &::Core::EditorManager::editorOpened, [&](auto *editor) { QObject::connect(editorManager, &::Core::EditorManager::editorOpened, [&](auto *editor) {
@@ -145,12 +169,17 @@ QmlDesignerProjectManager::~QmlDesignerProjectManager() = default;
void QmlDesignerProjectManager::registerPreviewImageProvider(QQmlEngine *engine) const void QmlDesignerProjectManager::registerPreviewImageProvider(QQmlEngine *engine) const
{ {
auto imageProvider = std::make_unique<ExplicitImageCacheImageProvider>(m_imageCacheData->cache, auto imageProvider = std::make_unique<ExplicitImageCacheImageProvider>(m_previewImageCacheData->cache,
QImage{defaultImagePath()}); QImage{defaultImagePath()});
engine->addImageProvider("project_preview", imageProvider.release()); engine->addImageProvider("project_preview", imageProvider.release());
} }
AsynchronousImageCache &QmlDesignerProjectManager::asynchronousImageCache()
{
return imageCacheData()->asynchronousImageCache;
}
void QmlDesignerProjectManager::editorOpened(::Core::IEditor *) {} void QmlDesignerProjectManager::editorOpened(::Core::IEditor *) {}
void QmlDesignerProjectManager::currentEditorChanged(::Core::IEditor *) void QmlDesignerProjectManager::currentEditorChanged(::Core::IEditor *)
@@ -171,7 +200,7 @@ void QmlDesignerProjectManager::editorsClosed(const QList<::Core::IEditor *> &)
void QmlDesignerProjectManager::projectAdded(::ProjectExplorer::Project *project) void QmlDesignerProjectManager::projectAdded(::ProjectExplorer::Project *project)
{ {
m_projectData = std::make_unique<QmlDesignerProjectManagerProjectData>(m_imageCacheData->storage); m_projectData = std::make_unique<QmlDesignerProjectManagerProjectData>(m_previewImageCacheData->storage);
m_projectData->activeTarget = project->activeTarget(); m_projectData->activeTarget = project->activeTarget();
} }
@@ -183,4 +212,36 @@ void QmlDesignerProjectManager::aboutToRemoveProject(::ProjectExplorer::Project
void QmlDesignerProjectManager::projectRemoved(::ProjectExplorer::Project *) {} void QmlDesignerProjectManager::projectRemoved(::ProjectExplorer::Project *) {}
QmlDesignerProjectManager::ImageCacheData *QmlDesignerProjectManager::imageCacheData()
{
std::call_once(imageCacheFlag, [this]() {
m_imageCacheData = std::make_unique<ImageCacheData>();
auto setTargetInImageCache =
[imageCacheData = m_imageCacheData.get()](ProjectExplorer::Target *target) {
if (target == imageCacheData->collector.target())
return;
if (target)
imageCacheData->asynchronousImageCache.clean();
imageCacheData->collector.setTarget(target);
};
if (auto project = ProjectExplorer::SessionManager::startupProject(); project) {
m_imageCacheData->collector.setTarget(project->activeTarget());
QObject::connect(project,
&ProjectExplorer::Project::activeTargetChanged,
this,
setTargetInImageCache);
}
QObject::connect(ProjectExplorer::SessionManager::instance(),
&ProjectExplorer::SessionManager::startupProjectChanged,
this,
[=](ProjectExplorer::Project *project) {
setTargetInImageCache(activeTarget(project));
});
});
return m_imageCacheData.get();
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -26,8 +26,10 @@
#pragma once #pragma once
#include <QList> #include <QList>
#include <QObject>
#include <memory> #include <memory>
#include <mutex>
QT_FORWARD_DECLARE_CLASS(QQmlEngine) QT_FORWARD_DECLARE_CLASS(QQmlEngine)
@@ -42,17 +44,22 @@ class Target;
namespace QmlDesigner { namespace QmlDesigner {
class QmlDesignerProjectManager : public QObject
{
Q_OBJECT
class QmlDesignerProjectManagerProjectData; class QmlDesignerProjectManagerProjectData;
class PreviewImageCacheData; class PreviewImageCacheData;
class ImageCacheData;
class QmlDesignerProjectManager
{
public: public:
QmlDesignerProjectManager(); QmlDesignerProjectManager();
~QmlDesignerProjectManager(); ~QmlDesignerProjectManager();
void registerPreviewImageProvider(QQmlEngine *engine) const; void registerPreviewImageProvider(QQmlEngine *engine) const;
class AsynchronousImageCache &asynchronousImageCache();
private: private:
void editorOpened(::Core::IEditor *editor); void editorOpened(::Core::IEditor *editor);
void currentEditorChanged(::Core::IEditor *); void currentEditorChanged(::Core::IEditor *);
@@ -60,9 +67,12 @@ private:
void projectAdded(::ProjectExplorer::Project *project); void projectAdded(::ProjectExplorer::Project *project);
void aboutToRemoveProject(::ProjectExplorer::Project *project); void aboutToRemoveProject(::ProjectExplorer::Project *project);
void projectRemoved(::ProjectExplorer::Project *project); void projectRemoved(::ProjectExplorer::Project *project);
ImageCacheData *imageCacheData();
private: private:
std::unique_ptr<PreviewImageCacheData> m_imageCacheData; std::once_flag imageCacheFlag;
std::unique_ptr<ImageCacheData> m_imageCacheData;
std::unique_ptr<PreviewImageCacheData> m_previewImageCacheData;
std::unique_ptr<QmlDesignerProjectManagerProjectData> m_projectData; std::unique_ptr<QmlDesignerProjectManagerProjectData> m_projectData;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner