summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/declarative/graphicsitems/qdeclarativeborderimage.cpp60
-rw-r--r--src/declarative/graphicsitems/qdeclarativeborderimage_p.h3
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimage.cpp15
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase.cpp42
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase_p.h7
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h6
-rw-r--r--src/declarative/util/qdeclarativepixmapcache.cpp101
-rw-r--r--src/declarative/util/qdeclarativepixmapcache_p.h2
8 files changed, 178 insertions, 58 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp
index 1f26338..de16668 100644
--- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp
@@ -168,18 +168,26 @@ void QDeclarativeBorderImage::setSource(const QUrl &url)
d->url = url;
d->sciurl = QUrl();
+ emit sourceChanged(d->url);
+
+ if (isComponentComplete())
+ load();
+}
+
+void QDeclarativeBorderImage::load()
+{
+ Q_D(QDeclarativeBorderImage);
if (d->progress != 0.0) {
d->progress = 0.0;
emit progressChanged(d->progress);
}
- if (url.isEmpty()) {
+ if (d->url.isEmpty()) {
d->pix = QPixmap();
d->status = Null;
setImplicitWidth(0);
setImplicitHeight(0);
emit statusChanged(d->status);
- emit sourceChanged(d->url);
update();
} else {
d->status = Loading;
@@ -195,11 +203,21 @@ void QDeclarativeBorderImage::setSource(const QUrl &url)
{
QNetworkRequest req(d->url);
d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
- QObject::connect(d->sciReply, SIGNAL(finished()),
- this, SLOT(sciRequestFinished()));
+
+ static int sciReplyFinished = -1;
+ static int thisSciRequestFinished = -1;
+ if (sciReplyFinished == -1) {
+ sciReplyFinished =
+ QNetworkReply::staticMetaObject.indexOfSignal("finished()");
+ thisSciRequestFinished =
+ QDeclarativeBorderImage::staticMetaObject.indexOfSlot("sciRequestFinished()");
+ }
+
+ QMetaObject::connect(d->sciReply, sciReplyFinished, this,
+ thisSciRequestFinished, Qt::DirectConnection);
}
} else {
- QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->url, &d->pix);
+ QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->url, &d->pix, d->async);
if (status != QDeclarativePixmapReply::Ready && status != QDeclarativePixmapReply::Error) {
QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(this), d->url);
d->pendingPixmapCache = true;
@@ -217,7 +235,6 @@ void QDeclarativeBorderImage::setSource(const QUrl &url)
d->status = Ready;
d->progress = 1.0;
emit statusChanged(d->status);
- emit sourceChanged(d->url);
emit progressChanged(d->progress);
update();
}
@@ -319,13 +336,30 @@ void QDeclarativeBorderImage::setGridScaledImage(const QDeclarativeGridScaledIma
d->verticalTileMode = sci.verticalTileRule();
d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl()));
- QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->sciurl, &d->pix);
+ QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->sciurl, &d->pix, d->async);
if (status != QDeclarativePixmapReply::Ready && status != QDeclarativePixmapReply::Error) {
QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(this), d->sciurl);
d->sciPendingPixmapCache = true;
- connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
- connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
- this, SLOT(requestProgress(qint64,qint64)));
+
+ static int replyDownloadProgress = -1;
+ static int replyFinished = -1;
+ static int thisRequestProgress = -1;
+ static int thisRequestFinished = -1;
+ if (replyDownloadProgress == -1) {
+ replyDownloadProgress =
+ QDeclarativePixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
+ replyFinished =
+ QDeclarativePixmapReply::staticMetaObject.indexOfSignal("finished()");
+ thisRequestProgress =
+ QDeclarativeBorderImage::staticMetaObject.indexOfSlot("requestProgress(qint64,qint64)");
+ thisRequestFinished =
+ QDeclarativeBorderImage::staticMetaObject.indexOfSlot("requestFinished()");
+ }
+
+ QMetaObject::connect(reply, replyFinished, this,
+ thisRequestFinished, Qt::DirectConnection);
+ QMetaObject::connect(reply, replyDownloadProgress, this,
+ thisRequestProgress, Qt::DirectConnection);
} else {
//### should be unified with requestFinished
setImplicitWidth(d->pix.width());
@@ -337,7 +371,6 @@ void QDeclarativeBorderImage::setGridScaledImage(const QDeclarativeGridScaledIma
d->status = Ready;
d->progress = 1.0;
emit statusChanged(d->status);
- emit sourceChanged(d->url);
emit progressChanged(1.0);
update();
}
@@ -350,10 +383,10 @@ void QDeclarativeBorderImage::requestFinished()
if (d->url.path().endsWith(QLatin1String(".sci"))) {
d->sciPendingPixmapCache = false;
- QDeclarativePixmapCache::get(d->sciurl, &d->pix);
+ QDeclarativePixmapCache::get(d->sciurl, &d->pix, d->async);
} else {
d->pendingPixmapCache = false;
- if (QDeclarativePixmapCache::get(d->url, &d->pix) != QDeclarativePixmapReply::Ready)
+ if (QDeclarativePixmapCache::get(d->url, &d->pix, d->async) != QDeclarativePixmapReply::Ready)
d->status = Error;
}
setImplicitWidth(d->pix.width());
@@ -363,7 +396,6 @@ void QDeclarativeBorderImage::requestFinished()
d->status = Ready;
d->progress = 1.0;
emit statusChanged(d->status);
- emit sourceChanged(d->url);
emit progressChanged(1.0);
update();
}
diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage_p.h b/src/declarative/graphicsitems/qdeclarativeborderimage_p.h
index db81fd8..a759e67 100644
--- a/src/declarative/graphicsitems/qdeclarativeborderimage_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeborderimage_p.h
@@ -84,6 +84,9 @@ Q_SIGNALS:
void horizontalTileModeChanged();
void verticalTileModeChanged();
+protected:
+ virtual void load();
+
private:
void setGridScaledImage(const QDeclarativeGridScaledImage& sci);
diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp
index 33b38e0..338b086 100644
--- a/src/declarative/graphicsitems/qdeclarativeimage.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp
@@ -300,6 +300,21 @@ void QDeclarativeImage::geometryChanged(const QRectF &newGeometry, const QRectF
The URL may be absolute, or relative to the URL of the component.
*/
+/*!
+ \qmlproperty bool Image::asynchronous
+
+ Specifies that images on the local filesystem should be loaded
+ asynchronously in a separate thread. The default value is
+ false, causing the user interface thread to block while the
+ image is loaded. Setting \a asynchronous to true is useful where
+ maintaining a responsive user interface is more desireable
+ than having images immediately visible.
+
+ Note that this property is only valid for images read from the
+ local filesystem. Images loaded via a network resource (e.g. HTTP)
+ are always loaded asynchonously.
+*/
+
void QDeclarativeImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
{
Q_D(QDeclarativeImage);
diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
index 18053d3..a8cce3f 100644
--- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
@@ -75,6 +75,23 @@ qreal QDeclarativeImageBase::progress() const
return d->progress;
}
+
+bool QDeclarativeImageBase::asynchronous() const
+{
+ Q_D(const QDeclarativeImageBase);
+ return d->async;
+}
+
+void QDeclarativeImageBase::setAsynchronous(bool async)
+{
+ Q_D(QDeclarativeImageBase);
+ if (d->async != async) {
+ d->async = async;
+ emit asynchronousChanged();
+ }
+}
+
+
QUrl QDeclarativeImageBase::source() const
{
Q_D(const QDeclarativeImageBase);
@@ -94,23 +111,31 @@ void QDeclarativeImageBase::setSource(const QUrl &url)
}
d->url = url;
+ emit sourceChanged(d->url);
+
+ if (isComponentComplete())
+ load();
+}
+
+void QDeclarativeImageBase::load()
+{
+ Q_D(QDeclarativeImageBase);
if (d->progress != 0.0) {
d->progress = 0.0;
emit progressChanged(d->progress);
}
- if (url.isEmpty()) {
+ if (d->url.isEmpty()) {
d->pix = QPixmap();
d->status = Null;
setImplicitWidth(0);
setImplicitHeight(0);
emit statusChanged(d->status);
- emit sourceChanged(d->url);
emit pixmapChanged();
update();
} else {
d->status = Loading;
- QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->url, &d->pix);
+ QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->url, &d->pix, d->async);
if (status != QDeclarativePixmapReply::Ready && status != QDeclarativePixmapReply::Error) {
QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(this), d->url);
d->pendingPixmapCache = true;
@@ -147,7 +172,6 @@ void QDeclarativeImageBase::setSource(const QUrl &url)
}
d->progress = 1.0;
emit statusChanged(d->status);
- emit sourceChanged(d->url);
emit progressChanged(d->progress);
emit pixmapChanged();
update();
@@ -163,7 +187,7 @@ void QDeclarativeImageBase::requestFinished()
d->pendingPixmapCache = false;
- if (QDeclarativePixmapCache::get(d->url, &d->pix) != QDeclarativePixmapReply::Ready)
+ if (QDeclarativePixmapCache::get(d->url, &d->pix, d->async) != QDeclarativePixmapReply::Ready)
d->status = Error;
setImplicitWidth(d->pix.width());
setImplicitHeight(d->pix.height());
@@ -172,7 +196,6 @@ void QDeclarativeImageBase::requestFinished()
d->status = Ready;
d->progress = 1.0;
emit statusChanged(d->status);
- emit sourceChanged(d->url);
emit progressChanged(1.0);
emit pixmapChanged();
update();
@@ -187,5 +210,12 @@ void QDeclarativeImageBase::requestProgress(qint64 received, qint64 total)
}
}
+void QDeclarativeImageBase::componentComplete()
+{
+ Q_D(QDeclarativeImageBase);
+ QDeclarativeItem::componentComplete();
+ if (d->url.isValid())
+ load();
+}
QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h
index 47be139..c8c50ac 100644
--- a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h
@@ -57,6 +57,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeImageBase : public QDeclarativeItem
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+ Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
public:
~QDeclarativeImageBase();
@@ -67,13 +68,19 @@ public:
QUrl source() const;
virtual void setSource(const QUrl &url);
+ bool asynchronous() const;
+ void setAsynchronous(bool);
+
Q_SIGNALS:
void sourceChanged(const QUrl &);
void statusChanged(Status);
void progressChanged(qreal progress);
void pixmapChanged();
+ void asynchronousChanged();
protected:
+ virtual void load();
+ virtual void componentComplete();
QDeclarativeImageBase(QDeclarativeImageBasePrivate &dd, QDeclarativeItem *parent);
private Q_SLOTS:
diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
index d540e40..2e062a8 100644
--- a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
@@ -68,7 +68,8 @@ public:
QDeclarativeImageBasePrivate()
: status(QDeclarativeImageBase::Null),
progress(0.0),
- pendingPixmapCache(false)
+ pendingPixmapCache(false),
+ async(false)
{
}
@@ -76,7 +77,8 @@ public:
QDeclarativeImageBase::Status status;
QUrl url;
qreal progress;
- bool pendingPixmapCache;
+ bool pendingPixmapCache : 1;
+ bool async : 1;
};
QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp
index c4b07cc..cfb25dd 100644
--- a/src/declarative/util/qdeclarativepixmapcache.cpp
+++ b/src/declarative/util/qdeclarativepixmapcache.cpp
@@ -79,6 +79,14 @@ inline uint qHash(const QUrl &uri)
}
#endif
+static QString toLocalFileOrQrc(const QUrl& url)
+{
+ QString r = url.toLocalFile();
+ if (r.isEmpty() && url.scheme() == QLatin1String("qrc"))
+ r = QLatin1Char(':') + url.path();
+ return r;
+}
+
class QDeclarativeImageReaderEvent : public QEvent
{
public:
@@ -208,6 +216,7 @@ bool QDeclarativeImageRequestHandler::event(QEvent *event)
// fetch
if (url.scheme() == QLatin1String("image")) {
+ // Use QmlImageProvider
QImage image = QDeclarativeEnginePrivate::get(engine)->getImageFromProvider(url);
QDeclarativeImageReaderEvent::ReadError errorCode = QDeclarativeImageReaderEvent::NoError;
QString errorStr;
@@ -217,14 +226,36 @@ bool QDeclarativeImageRequestHandler::event(QEvent *event)
}
QCoreApplication::postEvent(runningJob, new QDeclarativeImageReaderEvent(errorCode, errorStr, image));
} else {
- QNetworkRequest req(url);
- req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
- QNetworkReply *reply = networkAccessManager()->get(req);
+ QString lf = toLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+ // Image is local - load/decode immediately
+ QImage image;
+ QDeclarativeImageReaderEvent::ReadError errorCode = QDeclarativeImageReaderEvent::NoError;
+ QString errorStr;
+ QFile f(lf);
+ if (f.open(QIODevice::ReadOnly)) {
+ QImageReader imgio(&f);
+ if (!imgio.read(&image)) {
+ errorStr = QLatin1String("Error decoding: ") + url.toString()
+ + QLatin1String(" \"") + imgio.errorString() + QLatin1String("\"");
+ errorCode = QDeclarativeImageReaderEvent::Loading;
+ }
+ } else {
+ errorStr = QLatin1String("Cannot open: ") + url.toString();
+ errorCode = QDeclarativeImageReaderEvent::Loading;
+ }
+ QCoreApplication::postEvent(runningJob, new QDeclarativeImageReaderEvent(errorCode, errorStr, image));
+ } else {
+ // Network resource
+ QNetworkRequest req(url);
+ req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
+ QNetworkReply *reply = networkAccessManager()->get(req);
- QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress);
- QMetaObject::connect(reply, replyFinished, this, thisNetworkRequestDone);
+ QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress);
+ QMetaObject::connect(reply, replyFinished, this, thisNetworkRequestDone);
- replies.insert(reply, runningJob);
+ replies.insert(reply, runningJob);
+ }
}
}
return true;
@@ -381,14 +412,6 @@ static bool readImage(QIODevice *dev, QPixmap *pixmap, QString &errorString)
This class is NOT reentrant.
*/
-static QString toLocalFileOrQrc(const QUrl& url)
-{
- QString r = url.toLocalFile();
- if (r.isEmpty() && url.scheme() == QLatin1String("qrc"))
- r = QLatin1Char(':') + url.path();
- return r;
-}
-
typedef QHash<QUrl, QDeclarativePixmapReply *> QDeclarativePixmapReplyHash;
Q_GLOBAL_STATIC(QDeclarativePixmapReplyHash, qmlActivePixmapReplies);
@@ -500,40 +523,48 @@ bool QDeclarativePixmapReply::release(bool defer)
Returns Ready, or Error if the image has been retrieved,
otherwise the current retrieval status.
+
+ If \a async is false the image will be loaded and decoded immediately;
+ otherwise the image will be loaded and decoded in a separate thread.
+
+ Note that images sourced from the network will always be loaded and
+ decoded asynchonously.
*/
-QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QPixmap *pixmap)
+QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QPixmap *pixmap, bool async)
{
QDeclarativePixmapReply::Status status = QDeclarativePixmapReply::Unrequested;
+ QByteArray key = url.toEncoded(QUrl::FormattingOption(0x100));
+ QString strKey = QString::fromLatin1(key.constData(), key.count());
#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
- QString lf = toLocalFileOrQrc(url);
- if (!lf.isEmpty()) {
- status = QDeclarativePixmapReply::Ready;
- if (!QPixmapCache::find(lf,pixmap)) {
- QFile f(lf);
- if (f.open(QIODevice::ReadOnly)) {
- QString errorString;
- if (!readImage(&f, pixmap, errorString)) {
- errorString = QLatin1String("Error decoding: ") + url.toString()
- + QLatin1String(" \"") + errorString + QLatin1String("\"");
- qWarning() << errorString;
+ if (!async) {
+ QString lf = toLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+ status = QDeclarativePixmapReply::Ready;
+ if (!QPixmapCache::find(strKey,pixmap)) {
+ QFile f(lf);
+ if (f.open(QIODevice::ReadOnly)) {
+ QString errorString;
+ if (!readImage(&f, pixmap, errorString)) {
+ errorString = QLatin1String("Error decoding: ") + url.toString()
+ + QLatin1String(" \"") + errorString + QLatin1String("\"");
+ qWarning() << errorString;
+ *pixmap = QPixmap();
+ status = QDeclarativePixmapReply::Error;
+ }
+ } else {
+ qWarning() << "Cannot open" << url;
*pixmap = QPixmap();
status = QDeclarativePixmapReply::Error;
}
- } else {
- qWarning() << "Cannot open" << url;
- *pixmap = QPixmap();
- status = QDeclarativePixmapReply::Error;
+ if (status == QDeclarativePixmapReply::Ready)
+ QPixmapCache::insert(strKey, *pixmap);
}
- if (status == QDeclarativePixmapReply::Ready)
- QPixmapCache::insert(lf, *pixmap);
+ return status;
}
- return status;
}
#endif
- QByteArray key = url.toEncoded(QUrl::FormattingOption(0x100));
- QString strKey = QString::fromLatin1(key.constData(), key.count());
QDeclarativePixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url);
if (iter != qmlActivePixmapReplies()->end() && (*iter)->status() == QDeclarativePixmapReply::Ready) {
// Must check this, since QPixmapCache::insert may have failed.
diff --git a/src/declarative/util/qdeclarativepixmapcache_p.h b/src/declarative/util/qdeclarativepixmapcache_p.h
index c615254..b8949db 100644
--- a/src/declarative/util/qdeclarativepixmapcache_p.h
+++ b/src/declarative/util/qdeclarativepixmapcache_p.h
@@ -92,7 +92,7 @@ private:
class Q_DECLARATIVE_EXPORT QDeclarativePixmapCache
{
public:
- static QDeclarativePixmapReply::Status get(const QUrl& url, QPixmap *pixmap);
+ static QDeclarativePixmapReply::Status get(const QUrl& url, QPixmap *pixmap, bool async=false);
static QDeclarativePixmapReply *request(QDeclarativeEngine *, const QUrl& url);
static void cancel(const QUrl& url, QObject *obj);
static int pendingRequests();