|
3 | 3 | #include <QCryptographicHash> |
4 | 4 | #include <QDir> |
5 | 5 | #include <QFile> |
| 6 | +#include <QFutureWatcher> |
6 | 7 | #include <QImageReader> |
7 | 8 | #include <QObject> |
8 | 9 | #include <QPainter> |
9 | 10 | #include <QThreadPool> |
| 11 | +#include <QtConcurrent> |
10 | 12 | #include <QtQuick/QQuickItem> |
11 | 13 | #include <QtQuick/QQuickWindow> |
12 | 14 |
|
@@ -104,59 +106,63 @@ void CachingImageManager::updateSource(const QString& path) { |
104 | 106 |
|
105 | 107 | m_shaPath = path; |
106 | 108 |
|
107 | | - const QPointer<CachingImageManager> self(this); |
108 | | - QThreadPool::globalInstance()->start([path, self] { |
109 | | - const QString sha = self->sha256sum(path); |
110 | | - |
111 | | - QMetaObject::invokeMethod( |
112 | | - self, |
113 | | - [path, sha, self]() { |
114 | | - if (!self || self->m_path != path) { |
115 | | - // Object is destroyed or path has changed, ignore |
116 | | - return; |
117 | | - } |
118 | | - |
119 | | - const QSize size = self->effectiveSize(); |
120 | | - |
121 | | - if (!self->m_item || !size.width() || !size.height()) { |
122 | | - return; |
123 | | - } |
124 | | - |
125 | | - const QString fillMode = self->m_item->property("fillMode").toString(); |
126 | | - // clang-format off |
127 | | - const QString filename = QString("%1@%2x%3-%4.png") |
128 | | - .arg(sha).arg(size.width()).arg(size.height()) |
129 | | - .arg(fillMode == "PreserveAspectCrop" ? "crop" : fillMode == "PreserveAspectFit" ? "fit" : "stretch"); |
130 | | - // clang-format on |
131 | | - |
132 | | - const QUrl cache = self->m_cacheDir.resolved(QUrl(filename)); |
133 | | - if (self->m_cachePath == cache) { |
134 | | - return; |
135 | | - } |
136 | | - |
137 | | - self->m_cachePath = cache; |
138 | | - emit self->cachePathChanged(); |
139 | | - |
140 | | - if (!cache.isLocalFile()) { |
141 | | - qWarning() << "CachingImageManager::updateSource: cachePath" << cache << "is not a local file"; |
142 | | - return; |
143 | | - } |
144 | | - |
145 | | - const QImageReader reader(cache.toLocalFile()); |
146 | | - if (reader.canRead()) { |
147 | | - self->m_item->setProperty("source", cache); |
148 | | - } else { |
149 | | - self->m_item->setProperty("source", QUrl::fromLocalFile(path)); |
150 | | - self->createCache(path, cache.toLocalFile(), fillMode, size); |
151 | | - } |
152 | | - |
153 | | - // Clear current running sha if same |
154 | | - if (self->m_shaPath == path) { |
155 | | - self->m_shaPath = QString(); |
156 | | - } |
157 | | - }, |
158 | | - Qt::QueuedConnection); |
| 109 | + const auto future = QtConcurrent::run(&CachingImageManager::sha256sum, path); |
| 110 | + |
| 111 | + const auto watcher = new QFutureWatcher<QString>(this); |
| 112 | + |
| 113 | + connect(watcher, &QFutureWatcher<QString>::finished, this, [watcher, path, this]() { |
| 114 | + if (m_path != path) { |
| 115 | + // Object is destroyed or path has changed, ignore |
| 116 | + watcher->deleteLater(); |
| 117 | + return; |
| 118 | + } |
| 119 | + |
| 120 | + const QSize size = effectiveSize(); |
| 121 | + |
| 122 | + if (!m_item || !size.width() || !size.height()) { |
| 123 | + watcher->deleteLater(); |
| 124 | + return; |
| 125 | + } |
| 126 | + |
| 127 | + const QString fillMode = m_item->property("fillMode").toString(); |
| 128 | + // clang-format off |
| 129 | + const QString filename = QString("%1@%2x%3-%4.png") |
| 130 | + .arg(watcher->result()).arg(size.width()).arg(size.height()) |
| 131 | + .arg(fillMode == "PreserveAspectCrop" ? "crop" : fillMode == "PreserveAspectFit" ? "fit" : "stretch"); |
| 132 | + // clang-format on |
| 133 | + |
| 134 | + const QUrl cache = m_cacheDir.resolved(QUrl(filename)); |
| 135 | + if (m_cachePath == cache) { |
| 136 | + watcher->deleteLater(); |
| 137 | + return; |
| 138 | + } |
| 139 | + |
| 140 | + m_cachePath = cache; |
| 141 | + emit cachePathChanged(); |
| 142 | + |
| 143 | + if (!cache.isLocalFile()) { |
| 144 | + qWarning() << "CachingImageManager::updateSource: cachePath" << cache << "is not a local file"; |
| 145 | + watcher->deleteLater(); |
| 146 | + return; |
| 147 | + } |
| 148 | + |
| 149 | + const QImageReader reader(cache.toLocalFile()); |
| 150 | + if (reader.canRead()) { |
| 151 | + m_item->setProperty("source", cache); |
| 152 | + } else { |
| 153 | + m_item->setProperty("source", QUrl::fromLocalFile(path)); |
| 154 | + createCache(path, cache.toLocalFile(), fillMode, size); |
| 155 | + } |
| 156 | + |
| 157 | + // Clear current running sha if same |
| 158 | + if (m_shaPath == path) { |
| 159 | + m_shaPath = QString(); |
| 160 | + } |
| 161 | + |
| 162 | + watcher->deleteLater(); |
159 | 163 | }); |
| 164 | + |
| 165 | + watcher->setFuture(future); |
160 | 166 | } |
161 | 167 |
|
162 | 168 | QUrl CachingImageManager::cachePath() const { |
@@ -201,7 +207,7 @@ void CachingImageManager::createCache( |
201 | 207 | }); |
202 | 208 | } |
203 | 209 |
|
204 | | -QString CachingImageManager::sha256sum(const QString& path) const { |
| 210 | +QString CachingImageManager::sha256sum(const QString& path) { |
205 | 211 | QFile file(path); |
206 | 212 | if (!file.open(QIODevice::ReadOnly)) { |
207 | 213 | qWarning() << "CachingImageManager::sha256sum: failed to open" << path; |
|
0 commit comments