diff --git a/src/icon.h b/src/icon.h --- a/src/icon.h +++ b/src/icon.h @@ -93,8 +93,8 @@ protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; QImage findIcon(const QSize& size); - void handleFinished(QNetworkAccessManager* qnam, QNetworkReply* reply); - void handleReadyRead(QNetworkReply* reply); + void handleFinished(QNetworkReply* reply); + void handleRedirect(QNetworkAccessManager* qnam, QNetworkReply* reply); QIcon::Mode iconMode() const; bool guessMonochrome(const QImage &img); diff --git a/src/icon.cpp b/src/icon.cpp --- a/src/icon.cpp +++ b/src/icon.cpp @@ -385,7 +385,7 @@ QQuickItem::geometryChanged(newGeometry, oldGeometry); } -void Icon::handleFinished(QNetworkAccessManager* qnam, QNetworkReply* reply) { +void Icon::handleRedirect(QNetworkAccessManager* qnam, QNetworkReply* reply) { if (reply && reply->error() == QNetworkReply::NoError) { const QUrl possibleRedirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); if (!possibleRedirectUrl.isEmpty()) { @@ -399,39 +399,31 @@ QNetworkRequest request(possibleRedirectUrl); request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); m_networkReply = qnam->get(request); - connect(m_networkReply.data(), &QNetworkReply::readyRead, this, [this](){handleReadyRead(m_networkReply); }); - connect(m_networkReply.data(), &QNetworkReply::finished, this, [this, qnam](){handleFinished(qnam, m_networkReply); }); + connect(m_networkReply.data(), &QNetworkReply::redirected, this, [this, qnam](){ handleRedirect(qnam, m_networkReply); }); + connect(m_networkReply.data(), &QNetworkReply::finished, this, [this](){handleFinished(m_networkReply); }); return; } } } -void Icon::handleReadyRead(QNetworkReply* reply) -{ - if (reply && reply->attribute(QNetworkRequest::RedirectionTargetAttribute).isNull()) { - // We're handing the event loop back while doing network work, and it turns out - // this fairly regularly results in things being deleted under us. So, just - // handle that and crash less :) - QPointer me(this); - QPointer guardedReply(reply); - QByteArray data; - do { - data.append(guardedReply->read(32768)); - // Because we are in the main thread, this could be potentially very expensive, so let's not block - qApp->processEvents(); - if(!me || !guardedReply) { - return; - } - } while(!guardedReply->atEnd()); - m_loadedImage = QImage::fromData(data); - if (m_loadedImage.isNull()) { - // broken image from data, inform the user of this with some useful broken-image thing... - const QSize size = QSize(width(), height()) * (window() ? window()->devicePixelRatio() : qApp->devicePixelRatio()); - m_loadedImage = QIcon::fromTheme(m_fallback).pixmap(size, iconMode(), QIcon::On).toImage(); - } - m_changed = true; - update(); +void Icon::handleFinished(QNetworkReply* reply) +{ + if (!reply || !reply->attribute(QNetworkRequest::RedirectionTargetAttribute).isNull()) { + return; } + + m_loadedImage = QImage(); + + const QString filename = reply->url().fileName(); + if (!m_loadedImage.load(reply, filename.mid(filename.indexOf(QLatin1Char('.'))).toLatin1().constData())) { + qDebug() << "received broken image" << reply->url(); + + // broken image from data, inform the user of this with some useful broken-image thing... + const QSize size = QSize(width(), height()) * (window() ? window()->devicePixelRatio() : qApp->devicePixelRatio()); + m_loadedImage = QIcon::fromTheme(m_fallback).pixmap(size, iconMode(), QIcon::On).toImage(); + } + m_changed = true; + update(); } QImage Icon::findIcon(const QSize &size) @@ -478,8 +470,8 @@ QNetworkRequest request(url); request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); m_networkReply = qnam->get(request); - connect(m_networkReply.data(), &QNetworkReply::readyRead, this, [this](){ handleReadyRead(m_networkReply); }); - connect(m_networkReply.data(), &QNetworkReply::finished, this, [this, qnam](){ handleFinished(qnam, m_networkReply); }); + connect(m_networkReply.data(), &QNetworkReply::redirected, this, [this, qnam](){ handleRedirect(qnam, m_networkReply); }); + connect(m_networkReply.data(), &QNetworkReply::finished, this, [this](){ handleFinished(m_networkReply); }); } // Temporary icon while we wait for the real image to load... img = QIcon::fromTheme(QStringLiteral("image-x-icon")).pixmap(size, iconMode(), QIcon::On).toImage();