The general answer is: it can't be safely done. In specific cases though, it can be done, but it requires close scrutiny of the code involved, and some proof of there being no issues due to reentrancy.
As for the use of the synchronous class, you simply need to run a local event loop within the requestXxxx
method's implementation. If it runs in a dedicated thread, then the reentrancy problems are less of an issue since you control what objects are active in the thread.
Since your implementation of QQuickImageProvider
can specify the ForceAsynchronousImageLoading
flag, your provider will run in its own thread, and can safely run its own message loop.
Note that the default QML image provider takes an URI as input, and will be more than happy to load images from the web - thus you don't have to worry about it in this case.
So, even through your custom image provider is completely unnecessary, if you were to create it, here's how you might do it:
class MyImageProvider : public QQuickImageProvider {
public:
MyImageProvider();
Flags flags() const { return ForceAsynchronousImageLoading; }
QImage requestImage(const QString & id, QSize * size, const QSize & requestedSize)
Q_DECL_OVERRIDE;
}
QImage MyImageProvider::requestImage(
const QString & id, QSize * size, const QSize & requestedSize)
{
QImage image;
QEventLoop loop;
QNetworkAccessManager mgr;
QObject::connect(&mgr, &QNetworkAccessManager::finished,
[&loop, size](QNetworkReply* reply) {
image.load(reply, "JPG");
if (size) *size = image.size();
loop.quit();
delete reply;
});
mgr.get(QNetworkRequest(QUrl(id)));
loop.exec();
return image;
}