summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2009-12-14 06:30:07 (GMT)
committerMartin Jones <martin.jones@nokia.com>2009-12-14 06:30:07 (GMT)
commit30767891615c1c9fc20e8a26da923f94d1728b4b (patch)
tree2a0ea1d470f6a63f3bfbfb1c329f283a469e63a1
parent167578b865bf53a88ff699a67bce0f17912807d5 (diff)
downloadQt-30767891615c1c9fc20e8a26da923f94d1728b4b.zip
Qt-30767891615c1c9fc20e8a26da923f94d1728b4b.tar.gz
Qt-30767891615c1c9fc20e8a26da923f94d1728b4b.tar.bz2
Decode images loaded via network in a separate thread.
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsborderimage.cpp20
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimagebase.cpp14
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsparticles.cpp11
-rw-r--r--src/declarative/util/qmlpixmapcache.cpp424
-rw-r--r--src/declarative/util/qmlpixmapcache_p.h44
5 files changed, 344 insertions, 169 deletions
diff --git a/src/declarative/graphicsitems/qmlgraphicsborderimage.cpp b/src/declarative/graphicsitems/qmlgraphicsborderimage.cpp
index 01c3e37..877e141 100644
--- a/src/declarative/graphicsitems/qmlgraphicsborderimage.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsborderimage.cpp
@@ -79,7 +79,7 @@ QmlGraphicsBorderImage::~QmlGraphicsBorderImage()
if (d->sciReply)
d->sciReply->deleteLater();
if (d->sciPendingPixmapCache)
- QmlPixmapCache::cancelGet(d->sciurl, this);
+ QmlPixmapCache::cancel(d->sciurl, this);
}
/*!
\qmlproperty enum BorderImage::status
@@ -159,11 +159,11 @@ void QmlGraphicsBorderImage::setSource(const QUrl &url)
}
if (d->pendingPixmapCache) {
- QmlPixmapCache::cancelGet(d->url, this);
+ QmlPixmapCache::cancel(d->url, this);
d->pendingPixmapCache = false;
}
if (d->sciPendingPixmapCache) {
- QmlPixmapCache::cancelGet(d->sciurl, this);
+ QmlPixmapCache::cancel(d->sciurl, this);
d->sciPendingPixmapCache = false;
}
@@ -200,8 +200,9 @@ void QmlGraphicsBorderImage::setSource(const QUrl &url)
this, SLOT(sciRequestFinished()));
}
} else {
- QNetworkReply *reply = QmlPixmapCache::get(qmlEngine(this), d->url, &d->pix);
- if (reply) {
+ QmlPixmapReply::Status status = QmlPixmapCache::get(d->url, &d->pix);
+ if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) {
+ QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->url);
d->pendingPixmapCache = true;
connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
@@ -319,8 +320,9 @@ void QmlGraphicsBorderImage::setGridScaledImage(const QmlGraphicsGridScaledImage
d->verticalTileMode = sci.verticalTileRule();
d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl()));
- QNetworkReply *reply = QmlPixmapCache::get(qmlEngine(this), d->sciurl, &d->pix);
- if (reply) {
+ QmlPixmapReply::Status status = QmlPixmapCache::get(d->sciurl, &d->pix);
+ if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) {
+ QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->sciurl);
d->sciPendingPixmapCache = true;
connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
@@ -349,10 +351,10 @@ void QmlGraphicsBorderImage::requestFinished()
if (d->url.path().endsWith(QLatin1String(".sci"))) {
d->sciPendingPixmapCache = false;
- QmlPixmapCache::find(d->sciurl, &d->pix);
+ QmlPixmapCache::get(d->sciurl, &d->pix);
} else {
d->pendingPixmapCache = false;
- if (!QmlPixmapCache::find(d->url, &d->pix))
+ if (QmlPixmapCache::get(d->url, &d->pix) != QmlPixmapReply::Ready)
d->status = Error;
}
setImplicitWidth(d->pix.width());
diff --git a/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp b/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp
index 70ca59c..9dd9f1b 100644
--- a/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp
@@ -61,7 +61,7 @@ QmlGraphicsImageBase::~QmlGraphicsImageBase()
{
Q_D(QmlGraphicsImageBase);
if (d->pendingPixmapCache)
- QmlPixmapCache::cancelGet(d->url, this);
+ QmlPixmapCache::cancel(d->url, this);
}
QmlGraphicsImageBase::Status QmlGraphicsImageBase::status() const
@@ -91,7 +91,7 @@ void QmlGraphicsImageBase::setSource(const QUrl &url)
return;
if (d->pendingPixmapCache) {
- QmlPixmapCache::cancelGet(d->url, this);
+ QmlPixmapCache::cancel(d->url, this);
d->pendingPixmapCache = false;
}
@@ -112,16 +112,16 @@ void QmlGraphicsImageBase::setSource(const QUrl &url)
update();
} else {
d->status = Loading;
- bool ok = true;
- QNetworkReply *reply = QmlPixmapCache::get(qmlEngine(this), d->url, &d->pix, &ok);
- if (reply) {
+ QmlPixmapReply::Status status = QmlPixmapCache::get(d->url, &d->pix);
+ if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) {
+ QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->url);
d->pendingPixmapCache = true;
connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(requestProgress(qint64,qint64)));
} else {
//### should be unified with requestFinished
- if (ok) {
+ if (status == QmlPixmapReply::Ready) {
setImplicitWidth(d->pix.width());
setImplicitHeight(d->pix.height());
@@ -148,7 +148,7 @@ void QmlGraphicsImageBase::requestFinished()
d->pendingPixmapCache = false;
- if (!QmlPixmapCache::find(d->url, &d->pix))
+ if (QmlPixmapCache::get(d->url, &d->pix) != QmlPixmapReply::Ready)
d->status = Error;
setImplicitWidth(d->pix.width());
setImplicitHeight(d->pix.height());
diff --git a/src/declarative/graphicsitems/qmlgraphicsparticles.cpp b/src/declarative/graphicsitems/qmlgraphicsparticles.cpp
index 63c7658..8c5fb4f 100644
--- a/src/declarative/graphicsitems/qmlgraphicsparticles.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsparticles.cpp
@@ -641,7 +641,7 @@ QmlGraphicsParticles::~QmlGraphicsParticles()
{
Q_D(QmlGraphicsParticles);
if (d->pendingPixmapCache)
- QmlPixmapCache::cancelGet(d->url, this);
+ QmlPixmapCache::cancel(d->url, this);
}
/*!
@@ -663,7 +663,7 @@ void QmlGraphicsParticles::imageLoaded()
{
Q_D(QmlGraphicsParticles);
d->pendingPixmapCache = false;
- QmlPixmapCache::find(d->url, &d->image);
+ QmlPixmapCache::get(d->url, &d->image);
d->paintItem->updateSize();
d->paintItem->update();
}
@@ -676,7 +676,7 @@ void QmlGraphicsParticles::setSource(const QUrl &name)
return;
if (d->pendingPixmapCache) {
- QmlPixmapCache::cancelGet(d->url, this);
+ QmlPixmapCache::cancel(d->url, this);
d->pendingPixmapCache = false;
}
if (name.isEmpty()) {
@@ -687,8 +687,9 @@ void QmlGraphicsParticles::setSource(const QUrl &name)
} else {
d->url = name;
Q_ASSERT(!name.isRelative());
- QNetworkReply *reply = QmlPixmapCache::get(qmlEngine(this), d->url, &d->image);
- if (reply) {
+ QmlPixmapReply::Status status = QmlPixmapCache::get(d->url, &d->image);
+ if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) {
+ QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->url);
connect(reply, SIGNAL(finished()), this, SLOT(imageLoaded()));
d->pendingPixmapCache = true;
} else {
diff --git a/src/declarative/util/qmlpixmapcache.cpp b/src/declarative/util/qmlpixmapcache.cpp
index 16e3dc8..ef40c7f 100644
--- a/src/declarative/util/qmlpixmapcache.cpp
+++ b/src/declarative/util/qmlpixmapcache.cpp
@@ -44,81 +44,164 @@
#include "qfxperf_p_p.h"
#include <qmlengine.h>
+#include <private/qmlglobal_p.h>
+#include <QCoreApplication>
#include <QImageReader>
#include <QHash>
#include <QNetworkReply>
#include <QPixmapCache>
#include <QFile>
+#include <QThread>
+#include <QMutex>
+#include <QWaitCondition>
#include <QtCore/qdebug.h>
+#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
-class QSharedNetworkReply;
-typedef QHash<QString, QSharedNetworkReply *> QmlGraphicsSharedNetworkReplyHash;
-static QmlGraphicsSharedNetworkReplyHash qfxActiveNetworkReplies;
+class QmlImageReader : public QThread
+{
+ Q_OBJECT
+public:
+ QmlImageReader(QObject *parent=0);
+ ~QmlImageReader();
+
+ void read(QmlPixmapReply *rep);
+ void cancel(QmlPixmapReply *rep);
+
+protected:
+ void run();
+
+private:
+ struct Job {
+ Job() : reply(0), error(false) {}
+ QmlPixmapReply *reply;
+ QImage img;
+ bool error;
+ };
+
+ void loadImage(Job &job);
+
+ QList<Job> jobs;
+ Job runningJob;
+ QMutex mutex;
+ QWaitCondition haveJob;
+ bool quit;
+};
-class QSharedNetworkReply
+class QmlImageDecodeEvent : public QCustomEvent
{
public:
- QSharedNetworkReply(QNetworkReply *r) : reply(r), refCount(1) {}
- ~QSharedNetworkReply()
- {
- reply->deleteLater();
+ QmlImageDecodeEvent(bool err, QImage &img) : QCustomEvent(QEvent::User), error(err), image(img) {}
+
+ bool error;
+ QImage image;
+};
+
+Q_GLOBAL_STATIC(QmlImageReader, qmlImageReader)
+
+
+QmlImageReader::QmlImageReader(QObject *parent) : QThread(parent), quit(false)
+{
+ start(QThread::LowPriority);
+}
+
+QmlImageReader::~QmlImageReader()
+{
+ quit = true;
+ haveJob.wakeOne();
+}
+
+void QmlImageReader::read(QmlPixmapReply *reply)
+{
+ mutex.lock();
+ Job job;
+ job.reply = reply;
+ jobs.append(job);
+ haveJob.wakeOne();
+ mutex.unlock();
+}
+
+void QmlImageReader::cancel(QmlPixmapReply *reply)
+{
+ mutex.lock();
+ if (runningJob.reply != reply) {
+ QList<Job>::iterator it = jobs.begin();
+ while (it != jobs.end()) {
+ if ((*it).reply == reply) {
+ jobs.erase(it);
+ break;
+ }
+ ++it;
+ }
}
- QNetworkReply *reply;
- QPixmap pixmap; // ensure reference to pixmap to QPixmapCache does not discard
+ mutex.unlock();
+}
- int refCount;
- void addRef()
- {
- ++refCount;
+void QmlImageReader::loadImage(Job &job)
+{
+ QImageReader imgio(job.reply->device());
+ if (imgio.read(&job.img)) {
+ job.error = false;
+ } else {
+ job.error = true;
+ qWarning() << imgio.errorString();
}
- void release()
- {
- Q_ASSERT(refCount > 0);
- --refCount;
- if (refCount == 0) {
- QString key = reply->url().toString();
- qfxActiveNetworkReplies.remove(key);
- delete this;
- }
+}
+
+void QmlImageReader::run()
+{
+ while (1) {
+ mutex.lock();
+ if (!jobs.count())
+ haveJob.wait(&mutex);
+ if (quit)
+ break;
+ runningJob = jobs.takeFirst();
+ runningJob.reply->addRef();
+ mutex.unlock();
+ loadImage(runningJob);
+ mutex.lock();
+ QCoreApplication::postEvent(runningJob.reply, new QmlImageDecodeEvent(runningJob.error, runningJob.img));
+ runningJob.reply = 0;
+ mutex.unlock();
}
-};
+}
static bool readImage(QIODevice *dev, QPixmap *pixmap)
- {
- QImageReader imgio(dev);
+{
+ QImageReader imgio(dev);
//#define QT_TEST_SCALED_SIZE
#ifdef QT_TEST_SCALED_SIZE
- /*
- Some mechanism is needed for loading images at a limited size, especially
- for remote images. Loading only thumbnails of remote progressive JPEG
- images can be efficient. (Qt jpeg handler does not do so currently)
- */
-
- QSize limit(60,60);
- QSize sz = imgio.size();
- if (sz.width() > limit.width() || sz.height() > limit.height()) {
- sz.scale(limit,Qt::KeepAspectRatio);
- imgio.setScaledSize(sz);
- }
+ /*
+ Some mechanism is needed for loading images at a limited size, especially
+ for remote images. Loading only thumbnails of remote progressive JPEG
+ images can be efficient. (Qt jpeg handler does not do so currently)
+ */
+
+ QSize limit(60,60);
+ QSize sz = imgio.size();
+ if (sz.width() > limit.width() || sz.height() > limit.height()) {
+ sz.scale(limit,Qt::KeepAspectRatio);
+ imgio.setScaledSize(sz);
+ }
#endif
- QImage img;
- if (imgio.read(&img)) {
+ QImage img;
+ if (imgio.read(&img)) {
#ifdef QT_TEST_SCALED_SIZE
- if (!sz.isValid())
- img = img.scaled(limit,Qt::KeepAspectRatio);
+ if (!sz.isValid())
+ img = img.scaled(limit,Qt::KeepAspectRatio);
#endif
- *pixmap = QPixmap::fromImage(img);
- return true;
- } else {
- qWarning() << imgio.errorString();
- return false;
- }
+ *pixmap = QPixmap::fromImage(img);
+ return true;
+ } else {
+ qWarning() << imgio.errorString();
+ return false;
}
+}
/*!
\internal
@@ -136,155 +219,208 @@ static QString toLocalFileOrQrc(const QUrl& url)
return r;
}
-/*!
- Finds the cached pixmap corresponding to \a url.
- A previous call to get() must have requested the URL,
- and the QNetworkReply must have finished before calling
- this function.
+typedef QHash<QString, QmlPixmapReply *> QmlPixmapReplyHash;
+static QmlPixmapReplyHash qmlActivePixmapReplies;
- Returns true if the image was loaded without error.
-*/
-bool QmlPixmapCache::find(const QUrl& url, QPixmap *pixmap)
+class QmlPixmapReplyPrivate : public QObjectPrivate
{
-#ifdef Q_ENABLE_PERFORMANCE_LOG
- QmlPerfTimer<QmlPerf::PixmapLoad> perf;
-#endif
+ Q_DECLARE_PUBLIC(QmlPixmapReply)
- bool ok = true;
-#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
- QString lf = toLocalFileOrQrc(url);
- if (!lf.isEmpty()) {
- if (!QPixmapCache::find(lf,pixmap)) {
- QFile f(lf);
- if (f.open(QIODevice::ReadOnly)) {
- if (!readImage(&f, pixmap)) {
- qWarning() << "Format error loading" << url;
- *pixmap = QPixmap();
- ok = false;
- } else {
- QPixmapCache::insert(lf, *pixmap);
- ok = !pixmap->isNull();
- }
- } else {
- *pixmap = QPixmap();
- ok = false;
- }
- } else {
- ok = !pixmap->isNull();
- }
- return ok;
+public:
+ QmlPixmapReplyPrivate(const QString &url, QNetworkReply *r)
+ : QObjectPrivate(), refCount(1), urlKey(url), reply(r), status(QmlPixmapReply::Loading) {
}
-#endif
- QString key = url.toString();
- if (!QPixmapCache::find(key,pixmap)) {
- QmlGraphicsSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key);
- if (iter == qfxActiveNetworkReplies.end()) {
- // API usage error
- qWarning() << "QmlPixmapCache: URL not loaded" << url;
- ok = false;
- } else {
- if ((*iter)->reply->error()) {
- qWarning() << "Network error loading" << url << (*iter)->reply->errorString();
- *pixmap = QPixmap();
- ok = false;
- } else if (!readImage((*iter)->reply, pixmap)) {
- qWarning() << "Format error loading" << url;
- *pixmap = QPixmap();
- ok = false;
+ int refCount;
+ QString urlKey;
+ QNetworkReply *reply;
+ QPixmap pixmap; // ensure reference to pixmap so QPixmapCache does not discard
+ QImage image;
+ QmlPixmapReply::Status status;
+};
+
+
+QmlPixmapReply::QmlPixmapReply(const QString &key, QNetworkReply *reply)
+ : QObject(*new QmlPixmapReplyPrivate(key, reply), 0)
+{
+ Q_D(QmlPixmapReply);
+ connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), this, SIGNAL(downloadProgress(qint64,qint64)));
+ connect(d->reply, SIGNAL(finished()), this, SLOT(networkRequestDone()));
+}
+
+QmlPixmapReply::~QmlPixmapReply()
+{
+ Q_D(QmlPixmapReply);
+ if (d->status == Decoding)
+ qmlImageReader()->cancel(this);
+ delete d->reply;
+}
+
+void QmlPixmapReply::networkRequestDone()
+{
+ Q_D(QmlPixmapReply);
+ if (d->reply->error()) {
+ d->pixmap = QPixmap();
+ d->status = Error;
+ emit finished();
+ } else {
+ qmlImageReader()->read(this);
+ d->status = Decoding;
+ }
+}
+
+bool QmlPixmapReply::event(QEvent *event)
+{
+ Q_D(QmlPixmapReply);
+ if (event->type() == QEvent::User) {
+ if (!release(true)) {
+ QmlImageDecodeEvent *de = static_cast<QmlImageDecodeEvent*>(event);
+ d->status = de->error ? Error : Ready;
+ if (d->status == Ready) {
+ d->pixmap = QPixmap::fromImage(de->image);
+ QPixmapCache::insert(d->urlKey, d->pixmap);
+ d->image = QImage();
} else {
- if ((*iter)->refCount > 1)
- (*iter)->pixmap = *pixmap;
+ qWarning() << "Error decoding" << d->urlKey;
}
- (*iter)->release();
+ emit finished();
}
- QPixmapCache::insert(key, *pixmap);
- } else {
- ok = !pixmap->isNull();
-
- // We may be the second finder. Still need to check for active replies.
- QmlGraphicsSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key);
- if (iter != qfxActiveNetworkReplies.end())
- (*iter)->release();
+ return true;
}
- return ok;
+
+ return QObject::event(event);
}
-/*!
- Starts a network request to load \a url.
+QmlPixmapReply::Status QmlPixmapReply::status() const
+{
+ Q_D(const QmlPixmapReply);
+ return d->status;
+}
+
+QIODevice *QmlPixmapReply::device()
+{
+ Q_D(QmlPixmapReply);
+ return d->reply;
+}
+
+void QmlPixmapReply::addRef()
+{
+ Q_D(QmlPixmapReply);
+ ++d->refCount;
+}
+
+bool QmlPixmapReply::release(bool defer)
+{
+ Q_D(QmlPixmapReply);
+ Q_ASSERT(d->refCount > 0);
+ --d->refCount;
+ if (d->refCount == 0) {
+ qmlActivePixmapReplies.remove(d->urlKey);
+ if (defer)
+ deleteLater();
+ else
+ delete this;
+ return true;
+ }
- Returns a QNetworkReply if the image is not immediately available, otherwise
- returns 0. Caller should connect to QNetworkReply::finished() to then call
- find() when the image is available.
+ return false;
+}
- The returned QNetworkReply will be deleted when all get() calls are
- matched by a corresponding find() call.
+/*!
+ Finds the cached pixmap corresponding to \a url.
+ If the image is a network resource and has not yet
+ been retrieved and cached, request() must be called.
- If the \a ok parameter is passed and \a url is a local file,
- its value will be set to false if the pixmap could not be loaded;
- otherwise the pixmap was loaded and *ok will be true.
+ Returns Ready, or Error if the image has been retrieved,
+ otherwise the current retrieval status.
*/
-QNetworkReply *QmlPixmapCache::get(QmlEngine *engine, const QUrl& url, QPixmap *pixmap, bool *ok)
+QmlPixmapReply::Status QmlPixmapCache::get(const QUrl& url, QPixmap *pixmap)
{
+ QmlPixmapReply::Status status = QmlPixmapReply::Unrequested;
+
#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
QString lf = toLocalFileOrQrc(url);
if (!lf.isEmpty()) {
+ status = QmlPixmapReply::Ready;
if (!QPixmapCache::find(lf,pixmap)) {
- bool loaded = true;
QFile f(lf);
if (f.open(QIODevice::ReadOnly)) {
if (!readImage(&f, pixmap)) {
qWarning() << "Format error loading" << url;
*pixmap = QPixmap();
- loaded = false;
+ status = QmlPixmapReply::Error;
}
} else {
qWarning() << "Cannot open" << url;
*pixmap = QPixmap();
- loaded = false;
+ status = QmlPixmapReply::Error;
}
- if (loaded)
+ if (status == QmlPixmapReply::Ready)
QPixmapCache::insert(lf, *pixmap);
- if (ok) *ok = loaded;
}
- return 0;
+ return status;
}
#endif
QString key = url.toString();
- if (QPixmapCache::find(key,pixmap)) {
- return 0;
+ QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies.find(key);
+ if (QPixmapCache::find(key, pixmap)) {
+ if (iter != qmlActivePixmapReplies.end()) {
+ status = (*iter)->status();
+ (*iter)->release();
+ } else {
+ status = pixmap->isNull() ? QmlPixmapReply::Error : QmlPixmapReply::Ready;
+ }
+ } else if (iter != qmlActivePixmapReplies.end()) {
+ status = QmlPixmapReply::Loading;
}
- QmlGraphicsSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key);
- if (iter == qfxActiveNetworkReplies.end()) {
+ return status;
+}
+
+/*!
+ Starts a network request to load \a url.
+
+ Returns a QmlPixmapReply. Caller should connect to QmlPixmapReply::finished()
+ and call get() when the image is available.
+
+ The returned QmlPixmapReply will be deleted when all request() calls are
+ matched by a corresponding get() call.
+*/
+QmlPixmapReply *QmlPixmapCache::request(QmlEngine *engine, const QUrl &url)
+{
+ QString key = url.toString();
+ QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies.find(key);
+ if (iter == qmlActivePixmapReplies.end()) {
QNetworkRequest req(url);
- QSharedNetworkReply *item = new QSharedNetworkReply(engine->networkAccessManager()->get(req));
- iter = qfxActiveNetworkReplies.insert(key, item);
+ QmlPixmapReply *item = new QmlPixmapReply(key, engine->networkAccessManager()->get(req));
+ iter = qmlActivePixmapReplies.insert(key, item);
} else {
(*iter)->addRef();
}
- return (*iter)->reply;
+ return (*iter);
}
/*!
- Cancels a previous call to get().
+ Cancels a previous call to request().
May also cancel loading (eg. if no other pending request).
- Any connections from the QNetworkReply returned by get() to \a obj will be
+ Any connections from the QmlPixmapReply returned by request() to \a obj will be
disconnected.
*/
-void QmlPixmapCache::cancelGet(const QUrl& url, QObject* obj)
+void QmlPixmapCache::cancel(const QUrl& url, QObject *obj)
{
QString key = url.toString();
- QmlGraphicsSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key);
- if (iter == qfxActiveNetworkReplies.end())
+ QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies.find(key);
+ if (iter == qmlActivePixmapReplies.end())
return;
+
+ QmlPixmapReply *reply = *iter;
if (obj)
- QObject::disconnect((*iter)->reply, 0, obj, 0);
- (*iter)->release();
+ QObject::disconnect(reply, 0, obj, 0);
+ reply->release();
}
/*!
@@ -293,7 +429,9 @@ void QmlPixmapCache::cancelGet(const QUrl& url, QObject* obj)
*/
int QmlPixmapCache::pendingRequests()
{
- return qfxActiveNetworkReplies.count();
+ return qmlActivePixmapReplies.count();
}
+#include <qmlpixmapcache.moc>
+
QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlpixmapcache_p.h b/src/declarative/util/qmlpixmapcache_p.h
index d2e272c..b71873f 100644
--- a/src/declarative/util/qmlpixmapcache_p.h
+++ b/src/declarative/util/qmlpixmapcache_p.h
@@ -53,17 +53,51 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QmlEngine;
class QNetworkReply;
-class Q_DECLARATIVE_EXPORT QmlPixmapCache
+
+class QmlPixmapReplyPrivate;
+class QmlPixmapReply : public QObject
{
+ Q_OBJECT
public:
- static QNetworkReply *get(QmlEngine *, const QUrl& url, QPixmap *pixmap, bool *ok=0);
- static void cancelGet(const QUrl& url, QObject* obj);
+ QmlPixmapReply(const QString &key, QNetworkReply *reply);
+ ~QmlPixmapReply();
+
+ enum Status { Ready, Error, Unrequested, Loading, Decoding };
+ Status status() const;
+
+Q_SIGNALS:
+ void finished();
+ void downloadProgress(qint64, qint64);
- static bool find(const QUrl& url, QPixmap *pixmap); // url must have been passed to QmlPixmapCache::get, and any returned reply finished.
+protected:
+ bool event(QEvent *event);
- static int pendingRequests(); // mainly for test verification
+private:
+ QIODevice *device();
+ void addRef();
+ bool release(bool defer=false);
+
+private Q_SLOTS:
+ void networkRequestDone();
+
+private:
+ Q_DISABLE_COPY(QmlPixmapReply)
+ Q_DECLARE_PRIVATE(QmlPixmapReply)
+ friend class QmlImageReader;
+ friend class QmlPixmapCache;
};
+class QmlPixmapCache
+{
+public:
+ static QmlPixmapReply::Status get(const QUrl& url, QPixmap *pixmap);
+ static QmlPixmapReply *request(QmlEngine *, const QUrl& url);
+ static void cancel(const QUrl& url, QObject *obj);
+ static int pendingRequests();
+};
+
+
+
QT_END_NAMESPACE
QT_END_HEADER