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 <bindingproperty.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 <nodelistproperty.h>
#include <projectexplorer/kit.h>
@@ -44,7 +38,6 @@
#include <projectexplorer/target.h>
#include <rewriterview.h>
#include <sqlitedatabase.h>
#include <synchronousimagecache.h>
#include <utils/algorithm.h>
#include <qmldesignerplugin.h>
#include <qmlitemnode.h>
@@ -52,38 +45,9 @@
namespace QmlDesigner {
namespace {
ProjectExplorer::Target *activeTarget(ProjectExplorer::Project *project)
{
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(AsynchronousImageCache &imageCache)
: AbstractView()
, m_imageCache(imageCache)
{}
ItemLibraryView::~ItemLibraryView()
@@ -97,11 +61,8 @@ bool ItemLibraryView::hasWidget() const
WidgetInfo ItemLibraryView::widgetInfo()
{
if (m_widget.isNull()) {
m_widget = new ItemLibraryWidget{imageCacheData()->cache,
imageCacheData()->asynchronousFontImageCache,
imageCacheData()->synchronousFontImageCache};
}
if (m_widget.isNull())
m_widget = new ItemLibraryWidget{m_imageCache};
return createWidgetInfo(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);
}
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> &)
{
if (m_hasErrors && errors.isEmpty())

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -44,6 +44,7 @@
#include <qtsupport/qtkitinformation.h>
#include <asynchronousexplicitimagecache.h>
#include <asynchronousimagecache.h>
#include <imagecache/asynchronousimagefactory.h>
#include <imagecache/explicitimagecacheimageprovider.h>
#include <imagecache/imagecachecollector.h>
@@ -60,6 +61,14 @@ namespace QmlDesigner {
namespace {
ProjectExplorer::Target *activeTarget(ProjectExplorer::Project *project)
{
if (project)
return project->activeTarget();
return {};
}
QString defaultImagePath()
{
return Core::ICore::resourcePath("qmldesigner/welcomepage/images/newThumbnail.png").toString();
@@ -89,7 +98,22 @@ public:
} // 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:
Sqlite::Database database{Utils::PathString{
@@ -100,7 +124,7 @@ public:
AsynchronousExplicitImageCache cache{storage};
};
class QmlDesignerProjectManagerProjectData
class QmlDesignerProjectManager::QmlDesignerProjectManagerProjectData
{
public:
QmlDesignerProjectManagerProjectData(ImageCacheStorage<Sqlite::Database> &storage)
@@ -117,7 +141,7 @@ public:
};
QmlDesignerProjectManager::QmlDesignerProjectManager()
: m_imageCacheData{std::make_unique<PreviewImageCacheData>()}
: m_previewImageCacheData{std::make_unique<PreviewImageCacheData>()}
{
auto editorManager = ::Core::EditorManager::instance();
QObject::connect(editorManager, &::Core::EditorManager::editorOpened, [&](auto *editor) {
@@ -145,12 +169,17 @@ QmlDesignerProjectManager::~QmlDesignerProjectManager() = default;
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()});
engine->addImageProvider("project_preview", imageProvider.release());
}
AsynchronousImageCache &QmlDesignerProjectManager::asynchronousImageCache()
{
return imageCacheData()->asynchronousImageCache;
}
void QmlDesignerProjectManager::editorOpened(::Core::IEditor *) {}
void QmlDesignerProjectManager::currentEditorChanged(::Core::IEditor *)
@@ -171,7 +200,7 @@ void QmlDesignerProjectManager::editorsClosed(const QList<::Core::IEditor *> &)
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();
}
@@ -183,4 +212,36 @@ void QmlDesignerProjectManager::aboutToRemoveProject(::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

View File

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