plugin/cim: use QtConcurrent

This commit is contained in:
2 * r + 2 * t 2025-09-03 23:16:58 +10:00
parent 8e6c7bc5e8
commit bcba9f6d73
3 changed files with 54 additions and 47 deletions

View file

@ -3,10 +3,12 @@
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QFutureWatcher>
#include <QImageReader> #include <QImageReader>
#include <QObject> #include <QObject>
#include <QPainter> #include <QPainter>
#include <QThreadPool> #include <QThreadPool>
#include <QtConcurrent>
#include <QtQuick/QQuickItem> #include <QtQuick/QQuickItem>
#include <QtQuick/QQuickWindow> #include <QtQuick/QQuickWindow>
@ -104,59 +106,63 @@ void CachingImageManager::updateSource(const QString& path) {
m_shaPath = path; m_shaPath = path;
const QPointer<CachingImageManager> self(this); const auto future = QtConcurrent::run(&CachingImageManager::sha256sum, path);
QThreadPool::globalInstance()->start([path, self] {
const QString sha = self->sha256sum(path);
QMetaObject::invokeMethod( const auto watcher = new QFutureWatcher<QString>(this);
self,
[path, sha, self]() {
if (!self || self->m_path != path) {
// Object is destroyed or path has changed, ignore
return;
}
const QSize size = self->effectiveSize(); connect(watcher, &QFutureWatcher<QString>::finished, this, [watcher, path, this]() {
if (m_path != path) {
// Object is destroyed or path has changed, ignore
watcher->deleteLater();
return;
}
if (!self->m_item || !size.width() || !size.height()) { const QSize size = effectiveSize();
return;
}
const QString fillMode = self->m_item->property("fillMode").toString(); if (!m_item || !size.width() || !size.height()) {
// clang-format off watcher->deleteLater();
const QString filename = QString("%1@%2x%3-%4.png") return;
.arg(sha).arg(size.width()).arg(size.height()) }
.arg(fillMode == "PreserveAspectCrop" ? "crop" : fillMode == "PreserveAspectFit" ? "fit" : "stretch");
// clang-format on
const QUrl cache = self->m_cacheDir.resolved(QUrl(filename)); const QString fillMode = m_item->property("fillMode").toString();
if (self->m_cachePath == cache) { // clang-format off
return; const QString filename = QString("%1@%2x%3-%4.png")
} .arg(watcher->result()).arg(size.width()).arg(size.height())
.arg(fillMode == "PreserveAspectCrop" ? "crop" : fillMode == "PreserveAspectFit" ? "fit" : "stretch");
// clang-format on
self->m_cachePath = cache; const QUrl cache = m_cacheDir.resolved(QUrl(filename));
emit self->cachePathChanged(); if (m_cachePath == cache) {
watcher->deleteLater();
return;
}
if (!cache.isLocalFile()) { m_cachePath = cache;
qWarning() << "CachingImageManager::updateSource: cachePath" << cache << "is not a local file"; emit cachePathChanged();
return;
}
const QImageReader reader(cache.toLocalFile()); if (!cache.isLocalFile()) {
if (reader.canRead()) { qWarning() << "CachingImageManager::updateSource: cachePath" << cache << "is not a local file";
self->m_item->setProperty("source", cache); watcher->deleteLater();
} else { return;
self->m_item->setProperty("source", QUrl::fromLocalFile(path)); }
self->createCache(path, cache.toLocalFile(), fillMode, size);
}
// Clear current running sha if same const QImageReader reader(cache.toLocalFile());
if (self->m_shaPath == path) { if (reader.canRead()) {
self->m_shaPath = QString(); m_item->setProperty("source", cache);
} } else {
}, m_item->setProperty("source", QUrl::fromLocalFile(path));
Qt::QueuedConnection); createCache(path, cache.toLocalFile(), fillMode, size);
}
// Clear current running sha if same
if (m_shaPath == path) {
m_shaPath = QString();
}
watcher->deleteLater();
}); });
watcher->setFuture(future);
} }
QUrl CachingImageManager::cachePath() const { QUrl CachingImageManager::cachePath() const {
@ -201,7 +207,7 @@ void CachingImageManager::createCache(
}); });
} }
QString CachingImageManager::sha256sum(const QString& path) const { QString CachingImageManager::sha256sum(const QString& path) {
QFile file(path); QFile file(path);
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "CachingImageManager::sha256sum: failed to open" << path; qWarning() << "CachingImageManager::sha256sum: failed to open" << path;

View file

@ -1,7 +1,8 @@
#pragma once #pragma once
#include <QFuture>
#include <QObject>
#include <QtQuick/QQuickItem> #include <QtQuick/QQuickItem>
#include <qobject.h>
#include <qqmlintegration.h> #include <qqmlintegration.h>
class CachingImageManager : public QObject { class CachingImageManager : public QObject {
@ -56,5 +57,5 @@ private:
[[nodiscard]] QSize effectiveSize() const; [[nodiscard]] QSize effectiveSize() const;
void createCache(const QString& path, const QString& cache, const QString& fillMode, const QSize& size) const; void createCache(const QString& path, const QString& cache, const QString& fillMode, const QSize& size) const;
[[nodiscard]] QString sha256sum(const QString& path) const; [[nodiscard]] static QString sha256sum(const QString& path);
}; };

View file

@ -155,5 +155,5 @@ private:
void updateEntries(); void updateEntries();
void updateEntriesForDir(const QString& dir); void updateEntriesForDir(const QString& dir);
void applyChanges(const QSet<QString>& removedPaths, const QSet<QString>& addedPaths); void applyChanges(const QSet<QString>& removedPaths, const QSet<QString>& addedPaths);
static bool compareEntries(const FileSystemEntry* a, const FileSystemEntry* b); [[nodiscard]] static bool compareEntries(const FileSystemEntry* a, const FileSystemEntry* b);
}; };