Fix a crash with newest library
This is basically a replica of
4c0020385a
for Spectral.
This commit is contained in:
parent
b71359e92a
commit
c2f66dcc70
|
@ -4,39 +4,38 @@
|
||||||
#include <jobs/mediathumbnailjob.h>
|
#include <jobs/mediathumbnailjob.h>
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QThread>
|
||||||
#include <QtCore/QReadWriteLock>
|
#include <QtCore/QReadWriteLock>
|
||||||
|
|
||||||
using QMatrixClient::BaseJob;
|
using QMatrixClient::BaseJob;
|
||||||
using QMatrixClient::Connection;
|
|
||||||
|
|
||||||
ThumbnailResponse::ThumbnailResponse(Connection* c, QString mediaId,
|
ThumbnailResponse::ThumbnailResponse(QMatrixClient::Connection* c,
|
||||||
const QSize& requestedSize)
|
QString mediaId, const QSize& requestedSize)
|
||||||
: c(c),
|
: c(c),
|
||||||
mediaId(std::move(mediaId)),
|
mediaId(std::move(mediaId)),
|
||||||
requestedSize(requestedSize),
|
requestedSize(requestedSize),
|
||||||
errorStr("Image request hasn't started") {
|
errorStr("Image request hasn't started") {
|
||||||
moveToThread(c->thread());
|
|
||||||
if (requestedSize.isEmpty()) {
|
if (requestedSize.isEmpty()) {
|
||||||
errorStr.clear();
|
errorStr.clear();
|
||||||
emit finished();
|
emit finished();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (mediaId.count('/') != 1) {
|
||||||
|
errorStr =
|
||||||
|
tr("Media id '%1' doesn't follow server/mediaId pattern")
|
||||||
|
.arg(mediaId);
|
||||||
|
emit finished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Execute a request on the main thread asynchronously
|
// Execute a request on the main thread asynchronously
|
||||||
|
moveToThread(c->thread());
|
||||||
QMetaObject::invokeMethod(this, &ThumbnailResponse::startRequest,
|
QMetaObject::invokeMethod(this, &ThumbnailResponse::startRequest,
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThumbnailResponse::startRequest() {
|
void ThumbnailResponse::startRequest() {
|
||||||
// Runs in the main thread, not QML thread
|
// Runs in the main thread, not QML thread
|
||||||
if (mediaId.count('/') != 1) {
|
Q_ASSERT(QThread::currentThread() == c->thread());
|
||||||
errorStr =
|
|
||||||
QStringLiteral("Media id '%1' doesn't follow server/mediaId pattern")
|
|
||||||
.arg(mediaId);
|
|
||||||
emit finished();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWriteLocker _(&lock);
|
|
||||||
job = c->getThumbnail(mediaId, requestedSize);
|
job = c->getThumbnail(mediaId, requestedSize);
|
||||||
// Connect to any possible outcome including abandonment
|
// Connect to any possible outcome including abandonment
|
||||||
// to make sure the QML thread is not left stuck forever.
|
// to make sure the QML thread is not left stuck forever.
|
||||||
|
@ -44,13 +43,16 @@ void ThumbnailResponse::startRequest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThumbnailResponse::prepareResult() {
|
void ThumbnailResponse::prepareResult() {
|
||||||
|
Q_ASSERT(QThread::currentThread() == job->thread());
|
||||||
|
Q_ASSERT(job->error() != BaseJob::Pending);
|
||||||
{
|
{
|
||||||
QWriteLocker _(&lock);
|
QWriteLocker _(&lock);
|
||||||
Q_ASSERT(job->error() != BaseJob::Pending);
|
|
||||||
|
|
||||||
if (job->error() == BaseJob::Success) {
|
if (job->error() == BaseJob::Success) {
|
||||||
image = job->thumbnail();
|
image = job->thumbnail();
|
||||||
errorStr.clear();
|
errorStr.clear();
|
||||||
|
} else if (job->error() == BaseJob::Abandoned) {
|
||||||
|
errorStr = tr("Image request has been cancelled");
|
||||||
|
qDebug() << "ThumbnailResponse: cancelled for" << mediaId;
|
||||||
} else {
|
} else {
|
||||||
errorStr = job->errorString();
|
errorStr = job->errorString();
|
||||||
qWarning() << "ThumbnailResponse: no valid image for" << mediaId << "-"
|
qWarning() << "ThumbnailResponse: no valid image for" << mediaId << "-"
|
||||||
|
@ -61,6 +63,13 @@ void ThumbnailResponse::prepareResult() {
|
||||||
emit finished();
|
emit finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ThumbnailResponse::doCancel() {
|
||||||
|
// Runs in the main thread, not QML thread
|
||||||
|
Q_ASSERT(QThread::currentThread() == job->thread());
|
||||||
|
if (job)
|
||||||
|
job->abandon();
|
||||||
|
}
|
||||||
|
|
||||||
QQuickTextureFactory* ThumbnailResponse::textureFactory() const {
|
QQuickTextureFactory* ThumbnailResponse::textureFactory() const {
|
||||||
QReadLocker _(&lock);
|
QReadLocker _(&lock);
|
||||||
return QQuickTextureFactory::textureFactoryForImage(image);
|
return QQuickTextureFactory::textureFactoryForImage(image);
|
||||||
|
@ -72,12 +81,8 @@ QString ThumbnailResponse::errorString() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThumbnailResponse::cancel() {
|
void ThumbnailResponse::cancel() {
|
||||||
QWriteLocker _(&lock);
|
QMetaObject::invokeMethod(this, &ThumbnailResponse::doCancel,
|
||||||
if (job) {
|
Qt::QueuedConnection);
|
||||||
job->abandon();
|
|
||||||
job = nullptr;
|
|
||||||
}
|
|
||||||
errorStr = "Image request has been cancelled";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QQuickImageResponse* ImageProvider::requestImageResponse(
|
QQuickImageResponse* ImageProvider::requestImageResponse(
|
||||||
|
|
|
@ -2,23 +2,24 @@
|
||||||
#define IMAGEPROVIDER_H
|
#define IMAGEPROVIDER_H
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <jobs/mediathumbnailjob.h>
|
|
||||||
#include <QThreadPool>
|
|
||||||
#include <QtCore/QAtomicPointer>
|
|
||||||
#include <QtCore/QReadWriteLock>
|
|
||||||
#include <QtQuick/QQuickAsyncImageProvider>
|
#include <QtQuick/QQuickAsyncImageProvider>
|
||||||
|
#include <QtCore/QAtomicPointer>
|
||||||
|
|
||||||
namespace QMatrixClient {
|
namespace QMatrixClient {
|
||||||
class Connection;
|
class Connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ThumbnailResponse : public QQuickImageResponse {
|
class ThumbnailResponse : public QQuickImageResponse {
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ThumbnailResponse(QMatrixClient::Connection* c, QString mediaId,
|
ThumbnailResponse(QMatrixClient::Connection* c, QString mediaId,
|
||||||
const QSize& requestedSize);
|
const QSize& requestedSize);
|
||||||
~ThumbnailResponse() override = default;
|
~ThumbnailResponse() override = default;
|
||||||
|
|
||||||
|
private slots:
|
||||||
void startRequest();
|
void startRequest();
|
||||||
|
void prepareResult();
|
||||||
|
void doCancel();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMatrixClient::Connection* c;
|
QMatrixClient::Connection* c;
|
||||||
|
@ -28,9 +29,8 @@ class ThumbnailResponse : public QQuickImageResponse {
|
||||||
|
|
||||||
QImage image;
|
QImage image;
|
||||||
QString errorStr;
|
QString errorStr;
|
||||||
mutable QReadWriteLock lock;
|
mutable QReadWriteLock lock; // Guards ONLY these two members above
|
||||||
|
|
||||||
void prepareResult();
|
|
||||||
QQuickTextureFactory* textureFactory() const override;
|
QQuickTextureFactory* textureFactory() const override;
|
||||||
QString errorString() const override;
|
QString errorString() const override;
|
||||||
void cancel() override;
|
void cancel() override;
|
||||||
|
@ -41,7 +41,7 @@ class ImageProvider : public QObject, public QQuickAsyncImageProvider {
|
||||||
Q_PROPERTY(QMatrixClient::Connection* connection READ connection WRITE
|
Q_PROPERTY(QMatrixClient::Connection* connection READ connection WRITE
|
||||||
setConnection NOTIFY connectionChanged)
|
setConnection NOTIFY connectionChanged)
|
||||||
public:
|
public:
|
||||||
explicit ImageProvider() : QObject(), QQuickAsyncImageProvider() {}
|
explicit ImageProvider() = default;
|
||||||
|
|
||||||
QQuickImageResponse* requestImageResponse(
|
QQuickImageResponse* requestImageResponse(
|
||||||
const QString& id, const QSize& requestedSize) override;
|
const QString& id, const QSize& requestedSize) override;
|
||||||
|
@ -49,6 +49,7 @@ class ImageProvider : public QObject, public QQuickAsyncImageProvider {
|
||||||
QMatrixClient::Connection* connection() { return m_connection; }
|
QMatrixClient::Connection* connection() { return m_connection; }
|
||||||
void setConnection(QMatrixClient::Connection* connection) {
|
void setConnection(QMatrixClient::Connection* connection) {
|
||||||
m_connection.store(connection);
|
m_connection.store(connection);
|
||||||
|
emit connectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
Loading…
Reference in New Issue