summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/declarative/graphicsitems/qdeclarativeborderimage.cpp100
-rw-r--r--src/declarative/graphicsitems/qdeclarativeborderimage_p_p.h2
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimage.cpp4
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase.cpp65
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h5
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem.cpp2
-rw-r--r--src/declarative/graphicsitems/qdeclarativeloader.cpp2
-rw-r--r--src/declarative/graphicsitems/qdeclarativerepeater.cpp38
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext.cpp148
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext_p.h3
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext_p_p.h4
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextedit.cpp2
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput.cpp46
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput_p_p.h1
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp4
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp3
-rw-r--r--src/declarative/qml/qdeclarativedom.cpp2
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp8
-rw-r--r--src/declarative/qml/qdeclarativeimport.cpp6
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp2
-rw-r--r--src/declarative/util/qdeclarativepixmapcache.cpp1115
-rw-r--r--src/declarative/util/qdeclarativepixmapcache_p.h85
-rw-r--r--src/declarative/util/qdeclarativestyledtext.cpp6
-rw-r--r--src/declarative/util/qdeclarativeview.cpp2
-rw-r--r--src/declarative/util/qdeclarativexmllistmodel.cpp2
-rw-r--r--src/gui/text/qtextdocument_p.cpp7
-rw-r--r--src/gui/text/qtextdocument_p.h1
-rw-r--r--src/imports/gestures/qdeclarativegesturearea.cpp2
-rw-r--r--src/imports/particles/qdeclarativeparticles.cpp33
29 files changed, 972 insertions, 728 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp
index d4ca9eb..44c206b 100644
--- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp
@@ -94,8 +94,6 @@ QDeclarativeBorderImage::~QDeclarativeBorderImage()
Q_D(QDeclarativeBorderImage);
if (d->sciReply)
d->sciReply->deleteLater();
- if (d->sciPendingPixmapCache)
- QDeclarativePixmapCache::cancel(d->sciurl, this);
}
/*!
\qmlproperty enumeration BorderImage::status
@@ -164,15 +162,6 @@ void QDeclarativeBorderImage::setSource(const QUrl &url)
d->sciReply = 0;
}
- if (d->pendingPixmapCache) {
- QDeclarativePixmapCache::cancel(d->url, this);
- d->pendingPixmapCache = false;
- }
- if (d->sciPendingPixmapCache) {
- QDeclarativePixmapCache::cancel(d->sciurl, this);
- d->sciPendingPixmapCache = false;
- }
-
d->url = url;
d->sciurl = QUrl();
emit sourceChanged(d->url);
@@ -190,7 +179,7 @@ void QDeclarativeBorderImage::load()
}
if (d->url.isEmpty()) {
- d->pix = QPixmap();
+ d->pix.clear();
d->status = Null;
setImplicitWidth(0);
setImplicitHeight(0);
@@ -224,26 +213,24 @@ void QDeclarativeBorderImage::load()
thisSciRequestFinished, Qt::DirectConnection);
}
} else {
- QSize impsize;
- QString errorString;
- QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->url, &d->pix, &errorString, &impsize, d->async);
- if (status != QDeclarativePixmapReply::Ready && status != QDeclarativePixmapReply::Error) {
- QDeclarativePixmapReply *reply = QDeclarativePixmapCache::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)));
+
+ d->pix.load(qmlEngine(this), d->url, d->async);
+
+ if (d->pix.isLoading()) {
+ d->pix.connectFinished(this, SLOT(requestFinished()));
+ d->pix.connectDownloadProgress(this, SLOT(requestProgress(qint64,qint64)));
} else {
- //### should be unified with requestFinished
+ QSize impsize = d->pix.implicitSize();
setImplicitWidth(impsize.width());
setImplicitHeight(impsize.height());
- if (d->pix.isNull()) {
+ if (d->pix.isReady()) {
+ d->status = Ready;
+ } else {
d->status = Error;
- qmlInfo(this) << errorString;
+ qmlInfo(this) << d->pix.error();
}
- if (d->status == Loading)
- d->status = Ready;
+
d->progress = 1.0;
emit statusChanged(d->status);
emit progressChanged(d->progress);
@@ -343,47 +330,40 @@ void QDeclarativeBorderImage::setGridScaledImage(const QDeclarativeGridScaledIma
d->verticalTileMode = sci.verticalTileRule();
d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl()));
- QSize impsize;
- QString errorString;
- QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->sciurl, &d->pix, &errorString, &impsize, d->async);
- if (status != QDeclarativePixmapReply::Ready && status != QDeclarativePixmapReply::Error) {
- QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(this), d->sciurl);
- d->sciPendingPixmapCache = true;
-
- static int replyDownloadProgress = -1;
- static int replyFinished = -1;
+
+ d->pix.load(qmlEngine(this), d->sciurl, d->async);
+
+ if (d->pix.isLoading()) {
static int thisRequestProgress = -1;
static int thisRequestFinished = -1;
- if (replyDownloadProgress == -1) {
- replyDownloadProgress =
- QDeclarativePixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
- replyFinished =
- QDeclarativePixmapReply::staticMetaObject.indexOfSignal("finished()");
+ if (thisRequestProgress == -1) {
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);
+ d->pix.connectFinished(this, thisRequestFinished);
+ d->pix.connectDownloadProgress(this, thisRequestProgress);
+
} else {
- //### should be unified with requestFinished
+
+ QSize impsize = d->pix.implicitSize();
setImplicitWidth(impsize.width());
setImplicitHeight(impsize.height());
- if (d->pix.isNull()) {
+ if (d->pix.isReady()) {
+ d->status = Ready;
+ } else {
d->status = Error;
- qmlInfo(this) << errorString;
+ qmlInfo(this) << d->pix.error();
}
- if (d->status == Loading)
- d->status = Ready;
+
d->progress = 1.0;
emit statusChanged(d->status);
emit progressChanged(1.0);
update();
+
}
}
}
@@ -392,27 +372,17 @@ void QDeclarativeBorderImage::requestFinished()
{
Q_D(QDeclarativeBorderImage);
- QSize impsize;
- if (d->url.path().endsWith(QLatin1String(".sci"))) {
- d->sciPendingPixmapCache = false;
- QString errorString;
- if (QDeclarativePixmapCache::get(d->sciurl, &d->pix, &errorString, &impsize, d->async) != QDeclarativePixmapReply::Ready) {
- d->status = Error;
- qmlInfo(this) << errorString;
- }
+ QSize impsize = d->pix.implicitSize();
+ if (d->pix.isError()) {
+ d->status = Error;
+ qmlInfo(this) << d->pix.error();
} else {
- d->pendingPixmapCache = false;
- QString errorString;
- if (QDeclarativePixmapCache::get(d->url, &d->pix, &errorString, &impsize, d->async) != QDeclarativePixmapReply::Ready) {
- d->status = Error;
- qmlInfo(this) << errorString;
- }
+ d->status = Ready;
}
+
setImplicitWidth(impsize.width());
setImplicitHeight(impsize.height());
- if (d->status == Loading)
- d->status = Ready;
d->progress = 1.0;
emit statusChanged(d->status);
emit progressChanged(1.0);
diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage_p_p.h b/src/declarative/graphicsitems/qdeclarativeborderimage_p_p.h
index 01e4a00..65583d6 100644
--- a/src/declarative/graphicsitems/qdeclarativeborderimage_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeborderimage_p_p.h
@@ -66,7 +66,6 @@ class QDeclarativeBorderImagePrivate : public QDeclarativeImageBasePrivate
public:
QDeclarativeBorderImagePrivate()
: border(0), sciReply(0),
- sciPendingPixmapCache(false),
horizontalTileMode(QDeclarativeBorderImage::Stretch),
verticalTileMode(QDeclarativeBorderImage::Stretch),
redirectCount(0)
@@ -97,7 +96,6 @@ public:
QDeclarativeScaleGrid *border;
QUrl sciurl;
QNetworkReply *sciReply;
- bool sciPendingPixmapCache;
QDeclarativeBorderImage::TileMode horizontalTileMode;
QDeclarativeBorderImage::TileMode verticalTileMode;
int redirectCount;
diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp
index ff61302..e0db580 100644
--- a/src/declarative/graphicsitems/qdeclarativeimage.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp
@@ -126,7 +126,7 @@ QDeclarativeImage::~QDeclarativeImage()
QPixmap QDeclarativeImage::pixmap() const
{
Q_D(const QDeclarativeImage);
- return d->pix;
+ return d->pix.pixmap();
}
void QDeclarativeImage::setPixmap(const QPixmap &pix)
@@ -140,7 +140,7 @@ void QDeclarativeImage::setPixmap(const QPixmap &pix)
void QDeclarativeImagePrivate::setPixmap(const QPixmap &pixmap)
{
Q_Q(QDeclarativeImage);
- pix = pixmap;
+ pix.setPixmap(pixmap);
q->setImplicitWidth(pix.width());
q->setImplicitHeight(pix.height());
diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
index c3f8195..67f2327 100644
--- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
@@ -57,9 +57,6 @@ QDeclarativeImageBase::QDeclarativeImageBase(QDeclarativeImageBasePrivate &dd, Q
QDeclarativeImageBase::~QDeclarativeImageBase()
{
- Q_D(QDeclarativeImageBase);
- if (d->pendingPixmapCache)
- QDeclarativePixmapCache::cancel(d->url, this);
}
QDeclarativeImageBase::Status QDeclarativeImageBase::status() const
@@ -91,7 +88,6 @@ void QDeclarativeImageBase::setAsynchronous(bool async)
}
}
-
QUrl QDeclarativeImageBase::source() const
{
Q_D(const QDeclarativeImageBase);
@@ -105,11 +101,6 @@ void QDeclarativeImageBase::setSource(const QUrl &url)
if ((d->url.isEmpty() == url.isEmpty()) && url == d->url)
return;
- if (d->pendingPixmapCache) {
- QDeclarativePixmapCache::cancel(d->url, this);
- d->pendingPixmapCache = false;
- }
-
d->url = url;
emit sourceChanged(d->url);
@@ -122,6 +113,7 @@ void QDeclarativeImageBase::setSourceSize(const QSize& size)
Q_D(QDeclarativeImageBase);
if (d->sourcesize == size)
return;
+
d->sourcesize = size;
emit sourceSizeChanged();
if (isComponentComplete())
@@ -143,7 +135,7 @@ void QDeclarativeImageBase::load()
}
if (d->url.isEmpty()) {
- d->pix = QPixmap();
+ d->pix.clear();
d->status = Null;
setImplicitWidth(0);
setImplicitHeight(0);
@@ -152,48 +144,37 @@ void QDeclarativeImageBase::load()
update();
} else {
d->status = Loading;
- int reqwidth = d->sourcesize.width();
- int reqheight = d->sourcesize.height();
- QSize impsize;
- QString errorString;
- QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->url, &d->pix, &errorString, &impsize, d->async, reqwidth, reqheight);
- if (status != QDeclarativePixmapReply::Ready && status != QDeclarativePixmapReply::Error) {
- QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(this), d->url, reqwidth, reqheight);
- d->pendingPixmapCache = true;
-
- static int replyDownloadProgress = -1;
- static int replyFinished = -1;
+
+ d->pix.load(qmlEngine(this), d->url, d->sourcesize, d->async);
+
+ if (d->pix.isLoading()) {
+
static int thisRequestProgress = -1;
static int thisRequestFinished = -1;
- if (replyDownloadProgress == -1) {
- replyDownloadProgress =
- QDeclarativePixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
- replyFinished =
- QDeclarativePixmapReply::staticMetaObject.indexOfSignal("finished()");
+ if (thisRequestProgress == -1) {
thisRequestProgress =
QDeclarativeImageBase::staticMetaObject.indexOfSlot("requestProgress(qint64,qint64)");
thisRequestFinished =
QDeclarativeImageBase::staticMetaObject.indexOfSlot("requestFinished()");
}
- QMetaObject::connect(reply, replyFinished, this,
- thisRequestFinished, Qt::DirectConnection);
- QMetaObject::connect(reply, replyDownloadProgress, this,
- thisRequestProgress, Qt::DirectConnection);
+ d->pix.connectFinished(this, thisRequestFinished);
+ d->pix.connectDownloadProgress(this, thisRequestProgress);
+
} else {
- //### should be unified with requestFinished
- if (status == QDeclarativePixmapReply::Ready) {
- setImplicitWidth(impsize.width());
- setImplicitHeight(impsize.height());
+ QSize impsize = d->pix.implicitSize();
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
- if (d->status == Loading)
- d->status = Ready;
+ if (d->pix.isReady()) {
+ d->status = Ready;
if (!d->sourcesize.isValid())
emit sourceSizeChanged();
+
} else {
d->status = Error;
- qmlInfo(this) << errorString;
+ qmlInfo(this) << d->pix.error();
}
d->progress = 1.0;
emit statusChanged(d->status);
@@ -201,6 +182,7 @@ void QDeclarativeImageBase::load()
pixmapChange();
update();
}
+
}
emit statusChanged(d->status);
@@ -210,14 +192,13 @@ void QDeclarativeImageBase::requestFinished()
{
Q_D(QDeclarativeImageBase);
- d->pendingPixmapCache = false;
+ QSize impsize = d->pix.implicitSize();
- QSize impsize;
- QString errorString;
- if (QDeclarativePixmapCache::get(d->url, &d->pix, &errorString, &impsize, d->async, d->sourcesize.width(), d->sourcesize.height()) != QDeclarativePixmapReply::Ready) {
+ if (d->pix.isError()) {
d->status = Error;
- qmlInfo(this) << errorString;
+ qmlInfo(this) << d->pix.error();
}
+
setImplicitWidth(impsize.width());
setImplicitHeight(impsize.height());
diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
index 392c1db..aee8b28 100644
--- a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
@@ -54,6 +54,7 @@
//
#include "private/qdeclarativeitem_p.h"
+#include "private/qdeclarativepixmapcache_p.h"
#include <QtCore/QPointer>
@@ -68,18 +69,16 @@ public:
QDeclarativeImageBasePrivate()
: status(QDeclarativeImageBase::Null),
progress(0.0),
- pendingPixmapCache(false),
async(false)
{
QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents;
}
- QPixmap pix;
+ QDeclarativePixmap pix;
QDeclarativeImageBase::Status status;
QUrl url;
qreal progress;
QSize sourcesize;
- bool pendingPixmapCache : 1;
bool async : 1;
};
diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp
index 4abffc6..bd935c9 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp
@@ -2145,7 +2145,7 @@ QDeclarativeAnchorLine QDeclarativeItemPrivate::baseline() const
\property QDeclarativeItem::baselineOffset
\brief The position of the item's baseline in local coordinates.
- The baseline of a Text item is the imaginary line on which the text
+ The baseline of a \l Text item is the imaginary line on which the text
sits. Controls containing text usually set their baseline to the
baseline of their text.
diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp
index c8c9e44..e745ca6 100644
--- a/src/declarative/graphicsitems/qdeclarativeloader.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp
@@ -119,7 +119,7 @@ void QDeclarativeLoaderPrivate::initResize()
property, or loaded from a URL via the \l source property.
Loader can be used to delay the creation of a component until it is required.
- For example, this loads "Page1.qml" as a component into the \l Loader element
+ For example, this loads "Page1.qml" as a component into the Loader element
when the \l MouseArea is clicked:
\code
diff --git a/src/declarative/graphicsitems/qdeclarativerepeater.cpp b/src/declarative/graphicsitems/qdeclarativerepeater.cpp
index 87da904..3be4014 100644
--- a/src/declarative/graphicsitems/qdeclarativerepeater.cpp
+++ b/src/declarative/graphicsitems/qdeclarativerepeater.cpp
@@ -85,6 +85,19 @@ QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate()
The \l model of a Repeater can be any of the supported \l {qmlmodels}{Data Models}.
+ Items instantiated by the Repeater are inserted, in order, as
+ children of the Repeater's parent. The insertion starts immediately after
+ the repeater's position in its parent stacking list. This allows
+ a Repeater to be used inside a layout. For example, the following Repeater's
+ items are stacked between a red rectangle and a blue rectangle:
+
+ \snippet doc/src/snippets/declarative/repeater.qml layout
+
+ \image repeater.png
+
+
+ \section2 The \c index and \c modelData properties
+
The index of a delegate is exposed as an accessible \c index property in the delegate.
Properties of the model are also available depending upon the type of \l {qmlmodels}{Data Model}.
@@ -105,25 +118,22 @@ QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate()
\o \image repeater-modeldata.png
\endtable
- Items instantiated by the Repeater are inserted, in order, as
- children of the Repeater's parent. The insertion starts immediately after
- the repeater's position in its parent stacking list. This allows
- a Repeater to be used inside a layout. For example, the following Repeater's
- items are stacked between a red rectangle and a blue rectangle:
-
- \snippet doc/src/snippets/declarative/repeater.qml layout
-
- \image repeater.png
A Repeater item owns all items it instantiates. Removing or dynamically destroying
an item created by a Repeater results in unpredictable behavior.
- Note that if a repeater is
- required to instantiate a large number of items, it may be more efficient to
- use other view elements such as ListView.
- \note Repeater is \l {Item}-based, and can only repeat \l {Item}-derived objects.
- For example, it cannot be used to repeat QtObjects.
+ \section2 Considerations when using Repeater
+
+ The Repeater element creates all of its delegate items when the repeater is first
+ created. This can be inefficient if there are a large number of delegate items and
+ not all of the items are required to be visible at the same time. If this is the case,
+ consider using other view elements like ListView (which only creates delegate items
+ when they are scrolled into view) or use the \l {Dynamic Object Creation} methods to
+ create items as they are required.
+
+ Also, note that Repeater is \l {Item}-based, and can only repeat \l {Item}-derived objects.
+ For example, it cannot be used to repeat QtObjects:
\badcode
Item {
//XXX does not work! Can't repeat QtObject as it doesn't derive from Item.
diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp
index 0bd9a53..a7e2ed0 100644
--- a/src/declarative/graphicsitems/qdeclarativetext.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetext.cpp
@@ -61,52 +61,100 @@ class QTextDocumentWithImageResources : public QTextDocument {
Q_OBJECT
public:
- QTextDocumentWithImageResources(QDeclarativeText *parent) :
- QTextDocument(parent),
- outstanding(0)
- {
- }
+ QTextDocumentWithImageResources(QDeclarativeText *parent);
+ virtual ~QTextDocumentWithImageResources();
+ void setText(const QString &);
int resourcesLoading() const { return outstanding; }
protected:
- QVariant loadResource(int type, const QUrl &name)
- {
- QUrl url = qmlContext(parent())->resolvedUrl(name);
-
- if (type == QTextDocument::ImageResource) {
- QPixmap pm;
- QString errorString;
- QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(url, &pm, &errorString, 0, false, 0, 0);
- if (status == QDeclarativePixmapReply::Ready)
- return pm;
- if (status == QDeclarativePixmapReply::Error) {
- if (!errors.contains(url)) {
- errors.insert(url);
- qmlInfo(parent()) << errorString;
- }
- } else {
- QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(parent()), url);
- connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
+ QVariant loadResource(int type, const QUrl &name);
+
+private slots:
+ void requestFinished();
+
+private:
+ QHash<QUrl, QDeclarativePixmap *> m_resources;
+
+ int outstanding;
+ static QSet<QUrl> errors;
+};
+
+QTextDocumentWithImageResources::QTextDocumentWithImageResources(QDeclarativeText *parent)
+: QTextDocument(parent), outstanding(0)
+{
+}
+
+QTextDocumentWithImageResources::~QTextDocumentWithImageResources()
+{
+ if (!m_resources.isEmpty())
+ qDeleteAll(m_resources);
+}
+
+QVariant QTextDocumentWithImageResources::loadResource(int type, const QUrl &name)
+{
+ QDeclarativeContext *context = qmlContext(parent());
+ QUrl url = context->resolvedUrl(name);
+
+ if (type == QTextDocument::ImageResource) {
+ QHash<QUrl, QDeclarativePixmap *>::Iterator iter = m_resources.find(url);
+
+ if (iter == m_resources.end()) {
+ QDeclarativePixmap *p = new QDeclarativePixmap(context->engine(), url);
+ iter = m_resources.insert(name, p);
+
+ if (p->isLoading()) {
+ p->connectFinished(this, SLOT(requestFinished()));
outstanding++;
}
}
- return QTextDocument::loadResource(type,url); // The *resolved* URL
+ QDeclarativePixmap *p = *iter;
+ if (p->isReady()) {
+ return p->pixmap();
+ } else if (p->isError()) {
+ if (!errors.contains(url)) {
+ errors.insert(url);
+ qmlInfo(parent()) << p->error();
+ }
+ }
}
-private slots:
- void requestFinished()
- {
- outstanding--;
- if (outstanding == 0)
- static_cast<QDeclarativeText*>(parent())->reloadWithResources();
+ return QTextDocument::loadResource(type,url); // The *resolved* URL
+}
+
+void QTextDocumentWithImageResources::requestFinished()
+{
+ outstanding--;
+ if (outstanding == 0) {
+ QDeclarativeText *textItem = static_cast<QDeclarativeText*>(parent());
+ QString text = textItem->text();
+#ifndef QT_NO_TEXTHTMLPARSER
+ setHtml(text);
+#else
+ setPlainText(text);
+#endif
+ QDeclarativeTextPrivate *d = QDeclarativeTextPrivate::get(textItem);
+ d->updateLayout();
+ d->markImgDirty();
}
+}
-private:
- int outstanding;
- static QSet<QUrl> errors;
-};
+void QTextDocumentWithImageResources::setText(const QString &text)
+{
+ if (!m_resources.isEmpty()) {
+ qWarning("CLEAR");
+ qDeleteAll(m_resources);
+ m_resources.clear();
+ outstanding = 0;
+ }
+
+#ifndef QT_NO_TEXTHTMLPARSER
+ setHtml(text);
+#else
+ setPlainText(text);
+#endif
+}
QSet<QUrl> QTextDocumentWithImageResources::errors;
@@ -314,11 +362,7 @@ void QDeclarativeText::setText(const QString &n)
if (d->richText) {
if (isComponentComplete()) {
d->ensureDoc();
-#ifndef QT_NO_TEXTHTMLPARSER
- d->doc->setHtml(n);
-#else
- d->doc->setPlainText(n);
-#endif
+ d->doc->setText(n);
}
}
@@ -607,11 +651,7 @@ void QDeclarativeText::setTextFormat(TextFormat format)
} else if (!wasRich && d->richText) {
if (isComponentComplete()) {
d->ensureDoc();
-#ifndef QT_NO_TEXTHTMLPARSER
- d->doc->setHtml(d->text);
-#else
- d->doc->setPlainText(d->text);
-#endif
+ d->doc->setText(d->text);
}
d->updateLayout();
d->markImgDirty();
@@ -1074,20 +1114,6 @@ void QDeclarativeTextPrivate::ensureDoc()
}
}
-void QDeclarativeText::reloadWithResources()
-{
- Q_D(QDeclarativeText);
- if (!d->richText)
- return;
-#ifndef QT_NO_TEXTHTMLPARSER
- d->doc->setHtml(d->text);
-#else
- d->doc->setPlainText(d->text);
-#endif
- d->updateLayout();
- d->markImgDirty();
-}
-
/*!
Returns the number of resources (images) that are being loaded asynchronously.
*/
@@ -1173,11 +1199,7 @@ void QDeclarativeText::componentComplete()
if (d->dirty) {
if (d->richText) {
d->ensureDoc();
-#ifndef QT_NO_TEXTHTMLPARSER
- d->doc->setHtml(d->text);
-#else
- d->doc->setPlainText(d->text);
-#endif
+ d->doc->setText(d->text);
}
d->updateLayout();
d->dirty = false;
diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h
index cd97df3..2cc4d52 100644
--- a/src/declarative/graphicsitems/qdeclarativetext_p.h
+++ b/src/declarative/graphicsitems/qdeclarativetext_p.h
@@ -168,9 +168,6 @@ protected:
private:
Q_DISABLE_COPY(QDeclarativeText)
Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeText)
-
- friend class QTextDocumentWithImageResources;
- void reloadWithResources();
};
QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h
index 332f99e..51a5514 100644
--- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h
@@ -124,6 +124,10 @@ public:
QSize cachedLayoutSize;
QDeclarativeText::TextFormat format;
QDeclarativeText::WrapMode wrapMode;
+
+ static inline QDeclarativeTextPrivate *get(QDeclarativeText *t) {
+ return t->d_func();
+ }
};
QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp
index c6566ff..c066f11 100644
--- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp
@@ -203,7 +203,7 @@ QString QDeclarativeTextEdit::text() const
Sets the font size in pixels.
Using this function makes the font device dependent.
- Use \l pointSize to set the size of the font in a device independent manner.
+ Use \l font.pointSize to set the size of the font in a device independent manner.
*/
/*!
diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp
index ed999a2..374f371 100644
--- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp
@@ -100,8 +100,6 @@ void QDeclarativeTextInput::setText(const QString &s)
if(s == text())
return;
d->control->setText(s);
- d->updateHorizontalScroll();
- //emit textChanged();
}
/*!
@@ -550,9 +548,9 @@ void QDeclarativeTextInput::setAutoScroll(bool b)
return;
d->autoScroll = b;
- d->updateHorizontalScroll();
//We need to repaint so that the scrolling is taking into account.
updateSize(true);
+ d->updateHorizontalScroll();
emit autoScrollChanged(d->autoScroll);
}
@@ -1020,27 +1018,43 @@ bool QDeclarativeTextInput::event(QEvent* ev)
void QDeclarativeTextInput::geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry)
{
- if (newGeometry.width() != oldGeometry.width())
+ Q_D(QDeclarativeTextInput);
+ if (newGeometry.width() != oldGeometry.width()) {
updateSize();
+ d->updateHorizontalScroll();
+ }
QDeclarativePaintedItem::geometryChanged(newGeometry, oldGeometry);
}
+int QDeclarativeTextInputPrivate::calculateTextWidth()
+{
+ int cursorWidth = control->cursorWidth();
+ if(cursorItem)
+ cursorWidth = cursorItem->width();
+
+ QFontMetrics fm = QFontMetrics(font);
+ int leftBearing = 0;
+ int rightBearing = 0;
+ if (!control->text().isEmpty()) {
+ leftBearing = qMax(0, -fm.leftBearing(control->text().at(0)));
+ rightBearing = qMax(0, -fm.rightBearing(control->text().at(control->text().count()-1)));
+ }
+
+ return qRound(control->naturalTextWidth()) + qMax(cursorWidth, leftBearing) + rightBearing;
+}
+
void QDeclarativeTextInputPrivate::updateHorizontalScroll()
{
Q_Q(QDeclarativeTextInput);
- QFontMetrics fm = QFontMetrics(font);
int cix = qRound(control->cursorToX());
QRect br(q->boundingRect().toRect());
- //###Is this using bearing appropriately?
- int minLB = qMax(0, -fm.minLeftBearing());
- int minRB = qMax(0, -fm.minRightBearing());
- int widthUsed = qRound(control->naturalTextWidth()) + 1 + minRB;
+ int widthUsed = calculateTextWidth();
if (autoScroll) {
- if ((minLB + widthUsed) <= br.width()) {
+ if (widthUsed <= br.width()) {
// text fits in br; use hscroll for alignment
switch (hAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
case Qt::AlignRight:
- hscroll = widthUsed - br.width() + 1;
+ hscroll = widthUsed - br.width() - 1;
break;
case Qt::AlignHCenter:
hscroll = (widthUsed - br.width()) / 2;
@@ -1050,7 +1064,6 @@ void QDeclarativeTextInputPrivate::updateHorizontalScroll()
hscroll = 0;
break;
}
- hscroll -= minLB;
} else if (cix - hscroll >= br.width()) {
// text doesn't fit, cursor is to the right of br (scroll right)
hscroll = cix - br.width() + 1;
@@ -1070,7 +1083,6 @@ void QDeclarativeTextInputPrivate::updateHorizontalScroll()
} else {
hscroll = 0;
}
- hscroll -= minLB;
}
}
@@ -1095,7 +1107,6 @@ void QDeclarativeTextInput::drawContents(QPainter *p, const QRect &r)
offset = QPoint(d->hscroll, 0);
}
d->control->draw(p, offset, r, flags);
-
p->restore();
}
@@ -1448,8 +1459,8 @@ void QDeclarativeTextInput::selectionChanged()
void QDeclarativeTextInput::q_textChanged()
{
Q_D(QDeclarativeTextInput);
- d->updateHorizontalScroll();
updateSize();
+ d->updateHorizontalScroll();
updateMicroFocus();
emit textChanged();
emit displayTextChanged();
@@ -1475,10 +1486,7 @@ void QDeclarativeTextInput::updateSize(bool needsRedraw)
int w = width();
int h = height();
setImplicitHeight(d->control->height());
- int cursorWidth = d->control->cursorWidth();
- if(d->cursorItem)
- cursorWidth = d->cursorItem->width();
- setImplicitWidth(d->control->naturalTextWidth() + cursorWidth);
+ setImplicitWidth(d->calculateTextWidth());
setContentsSize(QSize(width(), height()));//Repaints if changed
if(w==width() && h==height() && needsRedraw){
clearCache();
diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h
index 8b74bcc..4ac5134 100644
--- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h
@@ -100,6 +100,7 @@ public:
void startCreatingCursor();
void focusChanged(bool hasFocus);
void updateHorizontalScroll();
+ int calculateTextWidth();
QLineControl* control;
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 623e3df..e3ce70e 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -228,10 +228,10 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop,
}
break;
case QMetaType::Float:
- if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: float expected"));
+ if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected"));
break;
case QVariant::Double:
- if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: double expected"));
+ if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected"));
break;
case QVariant::Color:
{
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp
index 9d3032c..5617ae9 100644
--- a/src/declarative/qml/qdeclarativecomponent.cpp
+++ b/src/declarative/qml/qdeclarativecomponent.cpp
@@ -448,7 +448,8 @@ void QDeclarativeComponent::loadUrl(const QUrl &url)
d->clear();
- if (url.isRelative() && !url.isEmpty())
+ if ((url.isRelative() && !url.isEmpty())
+ || url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929
d->url = d->engine->baseUrl().resolved(url);
else
d->url = url;
diff --git a/src/declarative/qml/qdeclarativedom.cpp b/src/declarative/qml/qdeclarativedom.cpp
index a3cddb5..5b30bde 100644
--- a/src/declarative/qml/qdeclarativedom.cpp
+++ b/src/declarative/qml/qdeclarativedom.cpp
@@ -493,7 +493,7 @@ int QDeclarativeDomDynamicProperty::propertyType() const
return QMetaType::type("int");
case QDeclarativeParser::Object::DynamicProperty::Real:
- return QMetaType::type("double");
+ return sizeof(qreal) == sizeof(double) ? QMetaType::type("double") : QMetaType::type("float");
case QDeclarativeParser::Object::DynamicProperty::String:
return QMetaType::type("QString");
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 8b15ae9..8bf7450 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -151,6 +151,7 @@ void QDeclarativeEnginePrivate::defineModule()
}
/*!
+\keyword QmlGlobalQtObject
\qmlclass Qt QDeclarativeEnginePrivate
\brief The QML global Qt object provides useful enums and functions from Qt.
@@ -1077,7 +1078,7 @@ If you are certain the files will be local, you could simplify to:
\snippet doc/src/snippets/declarative/componentCreation.js 2
To create a QML object from an arbitrary string of QML (instead of a file),
-use \l{Qt::createQmlObject()}{Qt.createQmlObject()}.
+use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}.
*/
QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, QScriptEngine *engine)
@@ -1124,7 +1125,7 @@ Each object in this array has the members \c lineNumber, \c columnNumber, \c fil
Note that this function returns immediately, and therefore may not work if
the \a qml string loads new components (that is, external QML files that have not yet been loaded).
-If this is the case, consider using \l{Qt::createComponent()}{Qt.createComponent()} instead.
+If this is the case, consider using \l{QML:Qt::createComponent()}{Qt.createComponent()} instead.
*/
QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngine *engine)
@@ -1728,8 +1729,7 @@ void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const
/*!
\qmlmethod Qt::quit()
This function causes the QDeclarativeEngine::quit() signal to be emitted.
-Within the \l {Qt Declarative UI Runtime}{qml} application this causes the
-launcher application to exit.
+Within the \l {QML Viewer}, this causes the launcher application to exit.
*/
QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptEngine *e)
diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp
index a2e3831..fe05d20 100644
--- a/src/declarative/qml/qdeclarativeimport.cpp
+++ b/src/declarative/qml/qdeclarativeimport.cpp
@@ -409,7 +409,8 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl);
if (!localFileOrQrc.isEmpty()) {
QString dir = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri)));
- if (dir.isEmpty() || !QDir().exists(dir)) {
+ QFileInfo dirinfo(dir);
+ if (dir.isEmpty() || !dirinfo.exists() || !dirinfo.isDir()) {
if (errorString)
*errorString = QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri_arg);
return false; // local import dirs must exist
@@ -425,7 +426,8 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
if (prefix.isEmpty()) {
// directory must at least exist for valid import
QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri)));
- if (localFileOrQrc.isEmpty() || !QDir().exists(localFileOrQrc)) {
+ QFileInfo dirinfo(localFileOrQrc);
+ if (localFileOrQrc.isEmpty() || !dirinfo.exists() || !dirinfo.isDir()) {
if (errorString) {
if (localFileOrQrc.isEmpty())
*errorString = QDeclarativeImportDatabase::tr("import \"%1\" has no qmldir and no namespace").arg(uri);
diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp
index c32cab6..153e2be 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -1152,7 +1152,7 @@ bool QDeclarativeMetaType::copy(int type, void *data, const void *copy)
*static_cast<float *>(data) = float(0);
return true;
case QMetaType::Double:
- *static_cast<double *>(data) = double();
+ *static_cast<double *>(data) = double(0);
return true;
case QMetaType::QChar:
*static_cast<NS(QChar) *>(data) = NS(QChar)();
diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp
index 0c2f23d..fdc2455 100644
--- a/src/declarative/util/qdeclarativepixmapcache.cpp
+++ b/src/declarative/util/qdeclarativepixmapcache.cpp
@@ -55,104 +55,209 @@
#include <QFile>
#include <QThread>
#include <QMutex>
+#include <QMutexLocker>
+#include <QWaitCondition>
#include <QBuffer>
#include <QWaitCondition>
#include <QtCore/qdebug.h>
#include <private/qobject_p.h>
#include <QSslError>
-// Maximum number of simultaneous image requests to send.
-static const int maxImageRequestCount = 8;
+#define IMAGEREQUEST_MAX_REQUEST_COUNT 8
+#define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16
+#define CACHE_EXPIRE_TIME 30
+#define CACHE_REMOVAL_FRACTION 4
QT_BEGIN_NAMESPACE
-class QDeclarativeImageReaderEvent : public QEvent
+class QDeclarativePixmapReader;
+class QDeclarativePixmapData;
+class QDeclarativePixmapReply : public QObject
{
+ Q_OBJECT
public:
enum ReadError { NoError, Loading, Decoding };
- QDeclarativeImageReaderEvent(QDeclarativeImageReaderEvent::ReadError err, const QString &errStr, const QImage &img)
- : QEvent(QEvent::User), error(err), errorString(errStr), image(img) {}
+ QDeclarativePixmapReply(QDeclarativePixmapData *);
+ ~QDeclarativePixmapReply();
- ReadError error;
- QString errorString;
- QImage image;
+ QDeclarativePixmapData *data;
+ QDeclarativePixmapReader *reader;
+
+ bool loading;
+ int redirectCount;
+
+ class Event : public QEvent {
+ public:
+ Event(ReadError, const QString &, const QSize &, const QImage &);
+
+ ReadError error;
+ QString errorString;
+ QSize implicitSize;
+ QImage image;
+ };
+ void postReply(ReadError, const QString &, const QSize &, const QImage &);
+
+
+Q_SIGNALS:
+ void finished();
+ void downloadProgress(qint64, qint64);
+
+protected:
+ bool event(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QDeclarativePixmapReply)
+
+public:
+ static int finishedIndex;
+ static int downloadProgressIndex;
};
-class QDeclarativeImageRequestHandler;
-class QDeclarativeImageReader : public QThread
+class QDeclarativePixmapData;
+class QDeclarativePixmapReader : public QThread
{
Q_OBJECT
public:
- QDeclarativeImageReader(QDeclarativeEngine *eng);
- ~QDeclarativeImageReader();
+ QDeclarativePixmapReader(QDeclarativeEngine *eng);
+ ~QDeclarativePixmapReader();
- QDeclarativePixmapReply *getImage(const QUrl &url, int req_width, int req_height);
+ QDeclarativePixmapReply *getImage(QDeclarativePixmapData *);
void cancel(QDeclarativePixmapReply *rep);
- static QDeclarativeImageReader *instance(QDeclarativeEngine *engine);
+ static QDeclarativePixmapReader *instance(QDeclarativeEngine *engine);
protected:
void run();
+private slots:
+ void networkRequestDone();
+
private:
+ void processJobs();
+ void processJob(QDeclarativePixmapReply *);
+
QList<QDeclarativePixmapReply*> jobs;
QList<QDeclarativePixmapReply*> cancelled;
QDeclarativeEngine *engine;
- QDeclarativeImageRequestHandler *handler;
QObject *eventLoopQuitHack;
+
QMutex mutex;
+ class ThreadObject : public QObject {
+ public:
+ ThreadObject(QDeclarativePixmapReader *);
+ void processJobs();
+ virtual bool event(QEvent *e);
+ private:
+ QDeclarativePixmapReader *reader;
+ } *threadObject;
+ QWaitCondition waitCondition;
+
+ QNetworkAccessManager *networkAccessManager();
+ QNetworkAccessManager *accessManager;
- static QHash<QDeclarativeEngine *,QDeclarativeImageReader*> readers;
+ QHash<QNetworkReply*,QDeclarativePixmapReply*> replies;
+
+ static int replyDownloadProgress;
+ static int replyFinished;
+ static int downloadProgress;
+ static int thisNetworkRequestDone;
+ static QHash<QDeclarativeEngine *,QDeclarativePixmapReader*> readers;
static QMutex readerMutex;
- friend class QDeclarativeImageRequestHandler;
};
-QHash<QDeclarativeEngine *,QDeclarativeImageReader*> QDeclarativeImageReader::readers;
-QMutex QDeclarativeImageReader::readerMutex;
-
-
-class QDeclarativeImageRequestHandler : public QObject
+class QDeclarativePixmapData
{
- Q_OBJECT
public:
- QDeclarativeImageRequestHandler(QDeclarativeImageReader *read, QDeclarativeEngine *eng)
- : QObject(), accessManager(0), engine(eng), reader(read), redirectCount(0)
+ QDeclarativePixmapData(const QUrl &u, const QSize &s, const QString &e)
+ : refCount(1), inCache(false), pixmapStatus(QDeclarativePixmap::Error),
+ url(u), errorString(e), requestSize(s), reply(0), prevUnreferenced(0),
+ prevUnreferencedPtr(0), nextUnreferenced(0)
{
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
- QDeclarativePixmapReply *getImage(const QUrl &url, int req_width, int req_height);
- void cancel(QDeclarativePixmapReply *reply);
-
-protected:
- bool event(QEvent *event);
+ QDeclarativePixmapData(const QUrl &u, const QSize &r)
+ : refCount(1), inCache(false), pixmapStatus(QDeclarativePixmap::Loading),
+ url(u), requestSize(r), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0),
+ nextUnreferenced(0)
+ {
+ }
-private slots:
- void networkRequestDone();
+ QDeclarativePixmapData(const QUrl &u, const QPixmap &p, const QSize &s, const QSize &r)
+ : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QDeclarativePixmap::Ready),
+ url(u), pixmap(p), implicitSize(s), requestSize(r), reply(0), prevUnreferenced(0),
+ prevUnreferencedPtr(0), nextUnreferenced(0)
+ {
+ }
-private:
- QNetworkAccessManager *networkAccessManager() {
- if (!accessManager)
- accessManager = QDeclarativeEnginePrivate::get(engine)->createNetworkAccessManager(this);
- return accessManager;
+ QDeclarativePixmapData(const QPixmap &p)
+ : refCount(1), inCache(false), privatePixmap(true), pixmapStatus(QDeclarativePixmap::Ready),
+ pixmap(p), implicitSize(p.size()), requestSize(p.size()), reply(0), prevUnreferenced(0),
+ prevUnreferencedPtr(0), nextUnreferenced(0)
+ {
}
- QHash<QNetworkReply*,QDeclarativePixmapReply*> replies;
- QNetworkAccessManager *accessManager;
- QDeclarativeEngine *engine;
- QDeclarativeImageReader *reader;
- int redirectCount;
+ int cost() const;
+ void addref();
+ void release();
+ void addToCache();
+ void removeFromCache();
- static int replyDownloadProgress;
- static int replyFinished;
- static int downloadProgress;
- static int thisNetworkRequestDone;
+ uint refCount;
+
+ bool inCache:1;
+ bool privatePixmap:1;
+
+ QDeclarativePixmap::Status pixmapStatus;
+ QUrl url;
+ QString errorString;
+ QPixmap pixmap;
+ QSize implicitSize;
+ QSize requestSize;
+
+ QDeclarativePixmapReply *reply;
+
+ QDeclarativePixmapData *prevUnreferenced;
+ QDeclarativePixmapData**prevUnreferencedPtr;
+ QDeclarativePixmapData *nextUnreferenced;
};
-//===========================================================================
+int QDeclarativePixmapReply::finishedIndex = -1;
+int QDeclarativePixmapReply::downloadProgressIndex = -1;
+
+// XXX
+QHash<QDeclarativeEngine *,QDeclarativePixmapReader*> QDeclarativePixmapReader::readers;
+QMutex QDeclarativePixmapReader::readerMutex;
-static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, int req_width, int req_height)
+int QDeclarativePixmapReader::replyDownloadProgress = -1;
+int QDeclarativePixmapReader::replyFinished = -1;
+int QDeclarativePixmapReader::downloadProgress = -1;
+int QDeclarativePixmapReader::thisNetworkRequestDone = -1;
+
+
+void QDeclarativePixmapReply::postReply(ReadError error, const QString &errorString,
+ const QSize &implicitSize, const QImage &image)
+{
+ loading = false;
+ QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, image));
+}
+
+QDeclarativePixmapReply::Event::Event(ReadError e, const QString &s, const QSize &iSize, const QImage &i)
+: QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), image(i)
+{
+}
+
+QNetworkAccessManager *QDeclarativePixmapReader::networkAccessManager()
+{
+ if (!accessManager) {
+ Q_ASSERT(threadObject);
+ accessManager = QDeclarativeEnginePrivate::get(engine)->createNetworkAccessManager(threadObject);
+ }
+ return accessManager;
+}
+
+static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize,
+ const QSize &requestSize)
{
QImageReader imgio(dev);
@@ -163,17 +268,17 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e
}
bool scaled = false;
- if (req_width > 0 || req_height > 0) {
+ if (requestSize.width() > 0 || requestSize.height() > 0) {
QSize s = imgio.size();
- if (req_width && (force_scale || req_width < s.width())) {
- if (req_height <= 0)
- s.setHeight(s.height()*req_width/s.width());
- s.setWidth(req_width); scaled = true;
+ if (requestSize.width() && (force_scale || requestSize.width() < s.width())) {
+ if (requestSize.height() <= 0)
+ s.setHeight(s.height()*requestSize.width()/s.width());
+ s.setWidth(requestSize.width()); scaled = true;
}
- if (req_height && (force_scale || req_height < s.height())) {
- if (req_width <= 0)
- s.setWidth(s.width()*req_height/s.height());
- s.setHeight(req_height); scaled = true;
+ if (requestSize.height() && (force_scale || requestSize.height() < s.height())) {
+ if (requestSize.width() <= 0)
+ s.setWidth(s.width()*requestSize.height()/s.height());
+ s.setHeight(requestSize.height()); scaled = true;
}
if (scaled) { imgio.setScaledSize(s); }
}
@@ -187,130 +292,39 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e
return true;
} else {
if (errorString)
- *errorString = QDeclarativePixmapCache::tr("Error decoding: %1: %2").arg(url.toString())
+ *errorString = QDeclarativePixmap::tr("Error decoding: %1: %2").arg(url.toString())
.arg(imgio.errorString());
return false;
}
}
-
-//===========================================================================
-
-int QDeclarativeImageRequestHandler::replyDownloadProgress = -1;
-int QDeclarativeImageRequestHandler::replyFinished = -1;
-int QDeclarativeImageRequestHandler::downloadProgress = -1;
-int QDeclarativeImageRequestHandler::thisNetworkRequestDone = -1;
-
-typedef QHash<QUrl, QSize> QDeclarativePixmapSizeHash;
-Q_GLOBAL_STATIC(QDeclarativePixmapSizeHash, qmlOriginalSizes);
-
-bool QDeclarativeImageRequestHandler::event(QEvent *event)
+QDeclarativePixmapReader::QDeclarativePixmapReader(QDeclarativeEngine *eng)
+: QThread(eng), engine(eng), threadObject(0), accessManager(0)
{
- if (event->type() == QEvent::User) {
- if (replyDownloadProgress == -1) {
- replyDownloadProgress = QNetworkReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
- replyFinished = QNetworkReply::staticMetaObject.indexOfSignal("finished()");
- downloadProgress = QDeclarativePixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
- thisNetworkRequestDone = QDeclarativeImageRequestHandler::staticMetaObject.indexOfSlot("networkRequestDone()");
- }
-
- while (1) {
- reader->mutex.lock();
-
- if (reader->cancelled.count()) {
- for (int i = 0; i < reader->cancelled.count(); ++i) {
- QDeclarativePixmapReply *job = reader->cancelled.at(i);
- QNetworkReply *reply = replies.key(job, 0);
- if (reply && reply->isRunning()) {
- // cancel any jobs already started
- replies.remove(reply);
- reply->close();
- job->release(true);
- } else {
- // remove from pending job list
- for (int j = 0; j < reader->jobs.count(); ++j) {
- if (reader->jobs.at(j) == job) {
- reader->jobs.removeAt(j);
- job->release(true);
- break;
- }
- }
- }
- }
- reader->cancelled.clear();
- }
-
- if (!reader->jobs.count() || replies.count() > maxImageRequestCount) {
- reader->mutex.unlock();
- break;
- }
-
- QDeclarativePixmapReply *runningJob = reader->jobs.takeLast();
- QUrl url = runningJob->url();
- reader->mutex.unlock();
-
- // fetch
- if (url.scheme() == QLatin1String("image")) {
- // Use QmlImageProvider
- QSize read_impsize;
- QImage image = QDeclarativeEnginePrivate::get(engine)->getImageFromProvider(url, &read_impsize, QSize(runningJob->forcedWidth(),runningJob->forcedHeight()));
- qmlOriginalSizes()->insert(url, read_impsize);
- QDeclarativeImageReaderEvent::ReadError errorCode = QDeclarativeImageReaderEvent::NoError;
- QString errorStr;
- if (image.isNull()) {
- errorCode = QDeclarativeImageReaderEvent::Loading;
- errorStr = QDeclarativePixmapCache::tr("Failed to get image from provider: %1").arg(url.toString());
- }
- QCoreApplication::postEvent(runningJob, new QDeclarativeImageReaderEvent(errorCode, errorStr, image));
- } else {
- QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(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)) {
- QSize read_impsize;
- if (readImage(url, &f, &image, &errorStr, &read_impsize, runningJob->forcedWidth(),runningJob->forcedHeight())) {
- qmlOriginalSizes()->insert(url, read_impsize);
- } else {
- errorCode = QDeclarativeImageReaderEvent::Loading;
- }
- } else {
- errorStr = QDeclarativePixmapCache::tr("Cannot open: %1").arg(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);
+ eventLoopQuitHack = new QObject;
+ eventLoopQuitHack->moveToThread(this);
+ connect(eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection);
+ start(QThread::IdlePriority);
+}
- replies.insert(reply, runningJob);
- }
- }
- }
- return true;
- }
+QDeclarativePixmapReader::~QDeclarativePixmapReader()
+{
+ readerMutex.lock();
+ readers.remove(engine);
+ readerMutex.unlock();
- return QObject::event(event);
+ eventLoopQuitHack->deleteLater();
+ wait();
}
-#define IMAGEREQUESTHANDLER_MAX_REDIRECT_RECURSION 16
-
-void QDeclarativeImageRequestHandler::networkRequestDone()
+void QDeclarativePixmapReader::networkRequestDone()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
QDeclarativePixmapReply *job = replies.take(reply);
if (job) {
- redirectCount++;
- if (redirectCount < IMAGEREQUESTHANDLER_MAX_REDIRECT_RECURSION) {
+ job->redirectCount++;
+ if (job->redirectCount < IMAGEREQUEST_MAX_REDIRECT_RECURSION) {
QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (redirect.isValid()) {
QUrl url = reply->url().resolved(redirect.toUrl());
@@ -327,62 +341,141 @@ void QDeclarativeImageRequestHandler::networkRequestDone()
return;
}
}
- redirectCount=0;
QImage image;
- QDeclarativeImageReaderEvent::ReadError error;
+ QDeclarativePixmapReply::ReadError error = QDeclarativePixmapReply::NoError;
QString errorString;
+ QSize readSize;
if (reply->error()) {
- error = QDeclarativeImageReaderEvent::Loading;
+ error = QDeclarativePixmapReply::Loading;
errorString = reply->errorString();
} else {
- QSize read_impsize;
QByteArray all = reply->readAll();
QBuffer buff(&all);
buff.open(QIODevice::ReadOnly);
- if (readImage(reply->url(), &buff, &image, &errorString, &read_impsize, job->forcedWidth(), job->forcedHeight())) {
- qmlOriginalSizes()->insert(reply->url(), read_impsize);
- error = QDeclarativeImageReaderEvent::NoError;
- } else {
- error = QDeclarativeImageReaderEvent::Decoding;
+ if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->data->requestSize)) {
+ error = QDeclarativePixmapReply::Decoding;
}
}
// send completion event to the QDeclarativePixmapReply
- QCoreApplication::postEvent(job, new QDeclarativeImageReaderEvent(error, errorString, image));
+ job->postReply(error, errorString, readSize, image);
}
- // kick off event loop again if we have dropped below max request count
- if (replies.count() == maxImageRequestCount)
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
reply->deleteLater();
+
+ // kick off event loop again incase we have dropped below max request count
+ threadObject->processJobs();
}
-//===========================================================================
+QDeclarativePixmapReader::ThreadObject::ThreadObject(QDeclarativePixmapReader *i)
+: reader(i)
+{
+}
+
+void QDeclarativePixmapReader::ThreadObject::processJobs()
+{
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+}
-QDeclarativeImageReader::QDeclarativeImageReader(QDeclarativeEngine *eng)
- : QThread(eng), engine(eng), handler(0)
+bool QDeclarativePixmapReader::ThreadObject::event(QEvent *e)
{
- eventLoopQuitHack = new QObject;
- eventLoopQuitHack->moveToThread(this);
- connect(eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection);
- start(QThread::IdlePriority);
+ if (e->type() == QEvent::User) {
+ reader->processJobs();
+ return true;
+ } else {
+ return QObject::event(e);
+ }
}
-QDeclarativeImageReader::~QDeclarativeImageReader()
+void QDeclarativePixmapReader::processJobs()
{
- readerMutex.lock();
- readers.remove(engine);
- readerMutex.unlock();
+ QMutexLocker locker(&mutex);
+
+ while (true) {
+ if (cancelled.isEmpty() && (jobs.isEmpty() || replies.count() >= IMAGEREQUEST_MAX_REQUEST_COUNT))
+ return; // Nothing else to do
+
+ // Clean cancelled jobs
+ if (cancelled.count()) {
+ for (int i = 0; i < cancelled.count(); ++i) {
+ QDeclarativePixmapReply *job = cancelled.at(i);
+ QNetworkReply *reply = replies.key(job, 0);
+ if (reply && reply->isRunning()) {
+ // cancel any jobs already started
+ replies.remove(reply);
+ reply->close();
+ }
+ delete job;
+ }
+ cancelled.clear();
+ }
- eventLoopQuitHack->deleteLater();
- wait();
+ if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) {
+ QDeclarativePixmapReply *runningJob = jobs.takeLast();
+ runningJob->loading = true;
+
+ locker.unlock();
+ processJob(runningJob);
+ locker.relock();
+ }
+ }
+}
+
+void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob)
+{
+ QUrl url = runningJob->data->url;
+
+ // fetch
+ if (url.scheme() == QLatin1String("image")) {
+ // Use QmlImageProvider
+ QSize readSize;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ QImage image = ep->getImageFromProvider(url, &readSize, runningJob->data->requestSize);
+
+ QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
+ QString errorStr;
+ if (image.isNull()) {
+ errorCode = QDeclarativePixmapReply::Loading;
+ errorStr = QDeclarativePixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+ }
+
+ runningJob->postReply(errorCode, errorStr, readSize, image);
+ } else {
+ QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+ // Image is local - load/decode immediately
+ QImage image;
+ QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
+ QString errorStr;
+ QFile f(lf);
+ QSize readSize;
+ if (f.open(QIODevice::ReadOnly)) {
+ if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->data->requestSize))
+ errorCode = QDeclarativePixmapReply::Loading;
+ } else {
+ errorStr = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString());
+ errorCode = QDeclarativePixmapReply::Loading;
+ }
+ runningJob->postReply(errorCode, errorStr, readSize, 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);
+
+ replies.insert(reply, runningJob);
+ }
+ }
}
-QDeclarativeImageReader *QDeclarativeImageReader::instance(QDeclarativeEngine *engine)
+QDeclarativePixmapReader *QDeclarativePixmapReader::instance(QDeclarativeEngine *engine)
{
readerMutex.lock();
- QDeclarativeImageReader *reader = readers.value(engine);
+ QDeclarativePixmapReader *reader = readers.value(engine);
if (!reader) {
- reader = new QDeclarativeImageReader(engine);
+ reader = new QDeclarativePixmapReader(engine);
readers.insert(engine, reader);
}
readerMutex.unlock();
@@ -390,348 +483,510 @@ QDeclarativeImageReader *QDeclarativeImageReader::instance(QDeclarativeEngine *e
return reader;
}
-QDeclarativePixmapReply *QDeclarativeImageReader::getImage(const QUrl &url, int req_width, int req_height)
+QDeclarativePixmapReply *QDeclarativePixmapReader::getImage(QDeclarativePixmapData *data)
{
mutex.lock();
- QDeclarativePixmapReply *reply = new QDeclarativePixmapReply(this, url, req_width, req_height);
- reply->addRef();
- reply->setLoading();
+ QDeclarativePixmapReply *reply = new QDeclarativePixmapReply(data);
+ reply->reader = this;
jobs.append(reply);
- if (jobs.count() == 1 && handler)
- QCoreApplication::postEvent(handler, new QEvent(QEvent::User));
+ // XXX
+ if (threadObject) threadObject->processJobs();
mutex.unlock();
return reply;
}
-void QDeclarativeImageReader::cancel(QDeclarativePixmapReply *reply)
+void QDeclarativePixmapReader::cancel(QDeclarativePixmapReply *reply)
{
mutex.lock();
- if (reply->isLoading()) {
- // Add to cancel list to be cancelled in reader thread.
+ if (reply->loading) {
cancelled.append(reply);
- if (cancelled.count() == 1 && handler)
- QCoreApplication::postEvent(handler, new QEvent(QEvent::User));
+ // XXX
+ if (threadObject) threadObject->processJobs();
+ } else {
+ jobs.removeAll(reply);
+ delete reply;
}
mutex.unlock();
}
-void QDeclarativeImageReader::run()
+void QDeclarativePixmapReader::run()
{
- readerMutex.lock();
- handler = new QDeclarativeImageRequestHandler(this, engine);
- readerMutex.unlock();
+ if (replyDownloadProgress == -1) {
+ const QMetaObject *nr = &QNetworkReply::staticMetaObject;
+ const QMetaObject *pr = &QDeclarativePixmapReply::staticMetaObject;
+ const QMetaObject *ir = &QDeclarativePixmapReader::staticMetaObject;
+ replyDownloadProgress = nr->indexOfSignal("downloadProgress(qint64,qint64)");
+ replyFinished = nr->indexOfSignal("finished()");
+ downloadProgress = pr->indexOfSignal("downloadProgress(qint64,qint64)");
+ thisNetworkRequestDone = ir->indexOfSlot("networkRequestDone()");
+ }
+ mutex.lock();
+ threadObject = new ThreadObject(this);
+ mutex.unlock();
+
+ processJobs();
exec();
- delete handler;
- handler = 0;
+ delete threadObject;
+ threadObject = 0;
}
-//===========================================================================
-
-/*!
- \internal
- \class QDeclarativePixmapCache
- \brief Enacapsultes a pixmap for QDeclarativeGraphics items.
+class QDeclarativePixmapKey
+{
+public:
+ const QUrl *url;
+ const QSize *size;
+};
- This class is NOT reentrant.
- */
+inline bool operator==(const QDeclarativePixmapKey &lhs, const QDeclarativePixmapKey &rhs)
+{
+ return *lhs.size == *rhs.size && *lhs.url == *rhs.url;
+}
-typedef QHash<QUrl, QDeclarativePixmapReply *> QDeclarativePixmapReplyHash;
-Q_GLOBAL_STATIC(QDeclarativePixmapReplyHash, qmlActivePixmapReplies);
+inline uint qHash(const QDeclarativePixmapKey &key)
+{
+ return qHash(*key.url) ^ key.size->width() ^ key.size->height();
+}
-class QDeclarativePixmapReplyPrivate : public QObjectPrivate
+class QDeclarativePixmapStore : public QObject
{
- Q_DECLARE_PUBLIC(QDeclarativePixmapReply)
+ Q_OBJECT
+public:
+ QDeclarativePixmapStore();
+
+ void unreferencePixmap(QDeclarativePixmapData *);
+ void referencePixmap(QDeclarativePixmapData *);
+
+protected:
+ virtual void timerEvent(QTimerEvent *);
public:
- QDeclarativePixmapReplyPrivate(QDeclarativeImageReader *r, const QUrl &u, int req_width, int req_height)
- : QObjectPrivate(), refCount(1), url(u), status(QDeclarativePixmapReply::Loading), loading(false), reader(r),
- forced_width(req_width), forced_height(req_height)
- {
- }
+ QHash<QDeclarativePixmapKey, QDeclarativePixmapData *> m_cache;
- int refCount;
- QUrl url;
- QPixmap pixmap; // ensure reference to pixmap so QPixmapCache does not discard
- QDeclarativePixmapReply::Status status;
- bool loading;
- QDeclarativeImageReader *reader;
- int forced_width, forced_height;
- QString errorString;
-};
+private:
+ QDeclarativePixmapData *m_unreferencedPixmaps;
+ QDeclarativePixmapData *m_lastUnreferencedPixmap;
+ int m_unreferencedCost;
+ int m_timerId;
+};
+Q_GLOBAL_STATIC(QDeclarativePixmapStore, pixmapStore);
-QDeclarativePixmapReply::QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url, int req_width, int req_height)
- : QObject(*new QDeclarativePixmapReplyPrivate(reader, url, req_width, req_height), 0)
+QDeclarativePixmapStore::QDeclarativePixmapStore()
+: m_unreferencedPixmaps(0), m_lastUnreferencedPixmap(0), m_unreferencedCost(0), m_timerId(-1)
{
}
-QDeclarativePixmapReply::~QDeclarativePixmapReply()
+void QDeclarativePixmapStore::unreferencePixmap(QDeclarativePixmapData *data)
{
+ Q_ASSERT(data->prevUnreferenced == 0);
+ Q_ASSERT(data->prevUnreferencedPtr == 0);
+ Q_ASSERT(data->nextUnreferenced == 0);
+
+ data->nextUnreferenced = m_unreferencedPixmaps;
+ data->prevUnreferencedPtr = &m_unreferencedPixmaps;
+
+ m_unreferencedPixmaps = data;
+ if (m_unreferencedPixmaps->nextUnreferenced) {
+ m_unreferencedPixmaps->nextUnreferenced->prevUnreferenced = m_unreferencedPixmaps;
+ m_unreferencedPixmaps->nextUnreferenced->prevUnreferencedPtr = &m_unreferencedPixmaps->nextUnreferenced;
+ }
+
+ if (!m_lastUnreferencedPixmap)
+ m_lastUnreferencedPixmap = data;
+
+ m_unreferencedCost += data->cost();
+
+ if (m_timerId == -1)
+ startTimer(CACHE_EXPIRE_TIME * 1000);
}
-const QUrl &QDeclarativePixmapReply::url() const
+void QDeclarativePixmapStore::referencePixmap(QDeclarativePixmapData *data)
{
- Q_D(const QDeclarativePixmapReply);
- return d->url;
+ Q_ASSERT(data->prevUnreferencedPtr);
+
+ *data->prevUnreferencedPtr = data->nextUnreferenced;
+ if (data->nextUnreferenced) {
+ data->nextUnreferenced->prevUnreferencedPtr = data->prevUnreferencedPtr;
+ data->nextUnreferenced->prevUnreferenced = data->prevUnreferenced;
+ }
+ if (m_lastUnreferencedPixmap == data)
+ m_lastUnreferencedPixmap = data->prevUnreferenced;
+
+ data->nextUnreferenced = 0;
+ data->prevUnreferencedPtr = 0;
+ data->prevUnreferenced = 0;
+
+ m_unreferencedCost -= data->cost();
}
-int QDeclarativePixmapReply::forcedWidth() const
+void QDeclarativePixmapStore::timerEvent(QTimerEvent *)
{
- Q_D(const QDeclarativePixmapReply);
- return d->forced_width;
+ int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION;
+
+ while (removalCost > 0 && m_lastUnreferencedPixmap) {
+ QDeclarativePixmapData *data = m_lastUnreferencedPixmap;
+ Q_ASSERT(data->nextUnreferenced == 0);
+
+ *data->prevUnreferencedPtr = 0;
+ m_lastUnreferencedPixmap = data->prevUnreferenced;
+ data->prevUnreferencedPtr = 0;
+ data->prevUnreferenced = 0;
+
+ removalCost -= data->cost();
+ data->removeFromCache();
+ delete data;
+ }
+
+ if (m_unreferencedPixmaps == 0) {
+ killTimer(m_timerId);
+ m_timerId = -1;
+ }
}
-int QDeclarativePixmapReply::forcedHeight() const
+QDeclarativePixmapReply::QDeclarativePixmapReply(QDeclarativePixmapData *d)
+: data(d), reader(0), loading(false), redirectCount(0)
{
- Q_D(const QDeclarativePixmapReply);
- return d->forced_height;
+ if (finishedIndex == -1) {
+ finishedIndex = QDeclarativePixmapReply::staticMetaObject.indexOfSignal("finished()");
+ downloadProgressIndex = QDeclarativePixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
+ }
}
-QSize QDeclarativePixmapReply::implicitSize() const
+QDeclarativePixmapReply::~QDeclarativePixmapReply()
{
- Q_D(const QDeclarativePixmapReply);
- QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(d->url);
- if (iter != qmlOriginalSizes()->end())
- return *iter;
- else
- return QSize();
}
bool QDeclarativePixmapReply::event(QEvent *event)
{
- Q_D(QDeclarativePixmapReply);
if (event->type() == QEvent::User) {
- d->loading = false;
- if (!release(true)) {
- QDeclarativeImageReaderEvent *de = static_cast<QDeclarativeImageReaderEvent*>(event);
- d->status = (de->error == QDeclarativeImageReaderEvent::NoError) ? Ready : Error;
- if (d->status == Ready)
- d->pixmap = QPixmap::fromImage(de->image);
- else
- d->errorString = de->errorString;
- QByteArray key = d->url.toEncoded(QUrl::FormattingOption(0x100));
- if (d->forced_width > 0 || d->forced_height > 0) {
- key += ':';
- key += QByteArray::number(d->forced_width);
- key += 'x';
- key += QByteArray::number(d->forced_height);
+
+ if (data) {
+ Event *de = static_cast<Event *>(event);
+ data->pixmapStatus = (de->error == NoError) ? QDeclarativePixmap::Ready : QDeclarativePixmap::Error;
+
+ if (data->pixmapStatus == QDeclarativePixmap::Ready) {
+ data->pixmap = QPixmap::fromImage(de->image);
+ data->implicitSize = de->implicitSize;
+ } else {
+ data->errorString = de->errorString;
+ data->removeFromCache(); // We don't continue to cache error'd pixmaps
}
- QString strKey = QString::fromLatin1(key.constData(), key.count());
- QPixmapCache::insert(strKey, d->pixmap); // note: may fail (returns false)
+
+ data->reply = 0;
emit finished();
}
+
+ delete this;
return true;
+ } else {
+ return QObject::event(event);
}
+}
- return QObject::event(event);
+int QDeclarativePixmapData::cost() const
+{
+ return pixmap.width() * pixmap.height() * pixmap.depth();
}
-QString QDeclarativePixmapReply::errorString() const
+void QDeclarativePixmapData::addref()
{
- Q_D(const QDeclarativePixmapReply);
- return d->errorString;
+ ++refCount;
+ if (prevUnreferencedPtr)
+ pixmapStore()->referencePixmap(this);
}
-QDeclarativePixmapReply::Status QDeclarativePixmapReply::status() const
+void QDeclarativePixmapData::release()
{
- Q_D(const QDeclarativePixmapReply);
- return d->status;
+ Q_ASSERT(refCount > 0);
+ --refCount;
+
+ if (refCount == 0) {
+ if (reply) {
+ reply->data = 0;
+ reply->reader->cancel(reply);
+ reply = 0;
+ }
+
+ if (pixmapStatus == QDeclarativePixmap::Ready) {
+ pixmapStore()->unreferencePixmap(this);
+ } else {
+ removeFromCache();
+ delete this;
+ }
+ }
}
-bool QDeclarativePixmapReply::isLoading() const
+void QDeclarativePixmapData::addToCache()
{
- Q_D(const QDeclarativePixmapReply);
- return d->loading;
+ if (!inCache) {
+ QDeclarativePixmapKey key = { &url, &requestSize };
+ pixmapStore()->m_cache.insert(key, this);
+ inCache = true;
+ }
}
-void QDeclarativePixmapReply::setLoading()
+void QDeclarativePixmapData::removeFromCache()
{
- Q_D(QDeclarativePixmapReply);
- d->loading = true;
+ if (inCache) {
+ QDeclarativePixmapKey key = { &url, &requestSize };
+ pixmapStore()->m_cache.remove(key);
+ inCache = false;
+ }
}
-void QDeclarativePixmapReply::addRef()
+struct QDeclarativePixmapNull {
+ QUrl url;
+ QPixmap pixmap;
+ QSize size;
+};
+Q_GLOBAL_STATIC(QDeclarativePixmapNull, nullPixmap);
+
+QDeclarativePixmap::QDeclarativePixmap()
+: d(0)
{
- Q_D(QDeclarativePixmapReply);
- ++d->refCount;
}
-bool QDeclarativePixmapReply::release(bool defer)
+QDeclarativePixmap::QDeclarativePixmap(QDeclarativeEngine *engine, const QUrl &url)
+: d(0)
{
- Q_D(QDeclarativePixmapReply);
- Q_ASSERT(d->refCount > 0);
- --d->refCount;
- if (d->refCount == 0) {
- qmlActivePixmapReplies()->remove(d->url);
- if (defer)
- deleteLater();
- else
- delete this;
- return true;
- } else if (d->refCount == 1 && d->loading) {
- // The only reference left is the reader thread.
- qmlActivePixmapReplies()->remove(d->url);
- d->reader->cancel(this);
+ load(engine, url);
+}
+
+QDeclarativePixmap::QDeclarativePixmap(QDeclarativeEngine *engine, const QUrl &url, const QSize &size)
+: d(0)
+{
+ load(engine, url, size);
+}
+
+QDeclarativePixmap::~QDeclarativePixmap()
+{
+ if (d) {
+ d->release();
+ d = 0;
}
+}
- return false;
+bool QDeclarativePixmap::isNull() const
+{
+ return d == 0;
}
-/*!
- 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.
+bool QDeclarativePixmap::isReady() const
+{
+ return status() == Ready;
+}
- Returns Ready, or Error if the image has been retrieved,
- otherwise the current retrieval status.
+bool QDeclarativePixmap::isError() const
+{
+ return status() == Error;
+}
- 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.
+bool QDeclarativePixmap::isLoading() const
+{
+ return status() == Loading;
+}
- If \a req_width and \a req_height are non-zero, they are used for
- the size of the rendered pixmap rather than the intrinsic size of the image.
- Different request sizes add different cache items.
+QString QDeclarativePixmap::error() const
+{
+ if (d)
+ return d->errorString;
+ else
+ return QString();
+}
- Note that images sourced from the network will always be loaded and
- decoded asynchonously.
-*/
-QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QPixmap *pixmap, QString *errorString, QSize *impsize, bool async, int req_width, int req_height)
+QDeclarativePixmap::Status QDeclarativePixmap::status() const
{
- QDeclarativePixmapReply::Status status = QDeclarativePixmapReply::Unrequested;
- QByteArray key = url.toEncoded(QUrl::FormattingOption(0x100));
+ if (d)
+ return d->pixmapStatus;
+ else
+ return Null;
+}
- if (req_width > 0 || req_height > 0) {
- key += ':';
- key += QByteArray::number(req_width);
- key += 'x';
- key += QByteArray::number(req_height);
- }
+const QUrl &QDeclarativePixmap::url() const
+{
+ if (d)
+ return d->url;
+ else
+ return nullPixmap()->url;
+}
- QString strKey = QString::fromLatin1(key.constData(), key.count());
+const QSize &QDeclarativePixmap::implicitSize() const
+{
+ if (d)
+ return d->implicitSize;
+ else
+ return nullPixmap()->size;
+}
+
+const QSize &QDeclarativePixmap::requestSize() const
+{
+ if (d)
+ return d->requestSize;
+ else
+ return nullPixmap()->size;
+}
+
+const QPixmap &QDeclarativePixmap::pixmap() const
+{
+ if (d)
+ return d->pixmap;
+ else
+ return nullPixmap()->pixmap;
+}
+
+void QDeclarativePixmap::setPixmap(const QPixmap &p)
+{
+ clear();
+
+ if (!p.isNull())
+ d = new QDeclarativePixmapData(p);
+}
+
+int QDeclarativePixmap::width() const
+{
+ if (d)
+ return d->pixmap.width();
+ else
+ return 0;
+}
+
+int QDeclarativePixmap::height() const
+{
+ if (d)
+ return d->pixmap.height();
+ else
+ return 0;
+}
+
+QRect QDeclarativePixmap::rect() const
+{
+ if (d)
+ return d->pixmap.rect();
+ else
+ return QRect();
+}
+
+void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url)
+{
+ load(engine, url, QSize(), false);
+}
+
+void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, bool async)
+{
+ load(engine, url, QSize(), async);
+}
+
+void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &size)
+{
+ load(engine, url, size, false);
+}
+
+void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, bool async)
+{
+ if (d) { d->release(); d = 0; }
+
+ QDeclarativePixmapKey key = { &url, &requestSize };
+ QDeclarativePixmapStore *store = pixmapStore();
+
+ QHash<QDeclarativePixmapKey, QDeclarativePixmapData *>::Iterator iter = store->m_cache.find(key);
+
+ if (iter == store->m_cache.end()) {
+ if (!async) {
+ QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
+ if (!localFile.isEmpty()) {
+ QFile f(localFile);
+ QSize readSize;
+ QString errorString;
-#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
- if (!async) {
- QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
- if (!lf.isEmpty()) {
- status = QDeclarativePixmapReply::Ready;
- if (!QPixmapCache::find(strKey,pixmap)) {
- QFile f(lf);
- QSize read_impsize;
if (f.open(QIODevice::ReadOnly)) {
QImage image;
- if (readImage(url, &f, &image, errorString, &read_impsize, req_width, req_height)) {
- *pixmap = QPixmap::fromImage(image);
- } else {
- *pixmap = QPixmap();
- status = QDeclarativePixmapReply::Error;
- }
+ if (readImage(url, &f, &image, &errorString, &readSize, requestSize)) {
+ d = new QDeclarativePixmapData(url, QPixmap::fromImage(image), readSize, requestSize);
+ d->addToCache();
+ return;
+ }
} else {
- if (errorString)
- *errorString = tr("Cannot open: %1").arg(url.toString());
- *pixmap = QPixmap();
- status = QDeclarativePixmapReply::Error;
- }
- if (status == QDeclarativePixmapReply::Ready) {
- QPixmapCache::insert(strKey, *pixmap);
- qmlOriginalSizes()->insert(url, read_impsize);
- }
- if (impsize)
- *impsize = read_impsize;
- } else {
- if (impsize) {
- QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(url);
- if (iter != qmlOriginalSizes()->end())
- *impsize = *iter;
+ errorString = tr("Cannot open: %1").arg(url.toString());
}
+
+ d = new QDeclarativePixmapData(url, requestSize, errorString);
+ return;
}
- return status;
- }
- }
-#endif
-
- QDeclarativePixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url);
- if (iter != qmlActivePixmapReplies()->end() && (*iter)->status() == QDeclarativePixmapReply::Ready) {
- // Must check this, since QPixmapCache::insert may have failed.
- *pixmap = (*iter)->d_func()->pixmap;
- status = (*iter)->status();
- (*iter)->release();
- } else if (QPixmapCache::find(strKey, pixmap)) {
- if (iter != qmlActivePixmapReplies()->end()) {
- status = (*iter)->status();
- if (errorString)
- *errorString = (*iter)->errorString();
- (*iter)->release();
- } else if (pixmap->isNull()) {
- status = QDeclarativePixmapReply::Error;
- if (errorString)
- *errorString = tr("Unknown Error loading %1").arg(url.toString());
- } else {
- status = QDeclarativePixmapReply::Ready;
- }
- } else if (iter != qmlActivePixmapReplies()->end()) {
- status = QDeclarativePixmapReply::Loading;
- }
- if (impsize) {
- QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(url);
- if (iter != qmlOriginalSizes()->end())
- *impsize = *iter;
- }
+ }
+
+ if (!engine)
+ return;
+
+ QDeclarativePixmapReader *reader = QDeclarativePixmapReader::instance(engine);
+
+ d = new QDeclarativePixmapData(url, requestSize);
+ d->addToCache();
- return status;
+ d->reply = reader->getImage(d);
+ } else {
+ d = *iter;
+ d->addref();
+ }
}
-/*!
- Starts a network request to load \a url.
+void QDeclarativePixmap::clear()
+{
+ if (d) {
+ d->release();
+ d = 0;
+ }
+}
- Returns a QDeclarativePixmapReply. Caller should connect to QDeclarativePixmapReply::finished()
- and call get() when the image is available.
+void QDeclarativePixmap::clear(QObject *obj)
+{
+ if (d) {
+ if (d->reply)
+ QObject::disconnect(d->reply, 0, obj, 0);
+ d->release();
+ d = 0;
+ }
+}
- The returned QDeclarativePixmapReply will be deleted when all request() calls are
- matched by a corresponding get() call.
-*/
-QDeclarativePixmapReply *QDeclarativePixmapCache::request(QDeclarativeEngine *engine, const QUrl &url, int req_width, int req_height)
+bool QDeclarativePixmap::connectFinished(QObject *object, const char *method)
{
- QDeclarativePixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url);
- if (iter == qmlActivePixmapReplies()->end()) {
- QDeclarativeImageReader *reader = QDeclarativeImageReader::instance(engine);
- QDeclarativePixmapReply *item = reader->getImage(url, req_width, req_height);
- iter = qmlActivePixmapReplies()->insert(url, item);
- } else {
- (*iter)->addRef();
+ if (!d || !d->reply) {
+ qWarning("QDeclarativePixmap: connectFinished() called when not loading.");
+ return false;
}
- return (*iter);
+ return QObject::connect(d->reply, SIGNAL(finished()), object, method);
}
-/*!
- Cancels a previous call to request().
+bool QDeclarativePixmap::connectFinished(QObject *object, int method)
+{
+ if (!d || !d->reply) {
+ qWarning("QDeclarativePixmap: connectFinished() called when not loading.");
+ return false;
+ }
- May also cancel loading (eg. if no other pending request).
+ return QMetaObject::connect(d->reply, QDeclarativePixmapReply::finishedIndex, object, method);
+}
- Any connections from the QDeclarativePixmapReply returned by request() to \a obj will be
- disconnected.
-*/
-void QDeclarativePixmapCache::cancel(const QUrl& url, QObject *obj)
+bool QDeclarativePixmap::connectDownloadProgress(QObject *object, const char *method)
{
- QDeclarativePixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url);
- if (iter == qmlActivePixmapReplies()->end())
- return;
+ if (!d || !d->reply) {
+ qWarning("QDeclarativePixmap: connectDownloadProgress() called when not loading.");
+ return false;
+ }
- QDeclarativePixmapReply *reply = *iter;
- if (obj)
- QObject::disconnect(reply, 0, obj, 0);
- reply->release();
+ return QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), object, method);
}
-/*!
- This function is mainly for test verification. It returns the number of
- requests that are still unfinished.
-*/
-int QDeclarativePixmapCache::pendingRequests()
+bool QDeclarativePixmap::connectDownloadProgress(QObject *object, int method)
{
- return qmlActivePixmapReplies()->count();
+ if (!d || !d->reply) {
+ qWarning("QDeclarativePixmap: connectDownloadProgress() called when not loading.");
+ return false;
+ }
+
+ return QMetaObject::connect(d->reply, QDeclarativePixmapReply::downloadProgressIndex, object, method);
}
QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativepixmapcache_p.h b/src/declarative/util/qdeclarativepixmapcache_p.h
index 33d9de1..8278c35 100644
--- a/src/declarative/util/qdeclarativepixmapcache_p.h
+++ b/src/declarative/util/qdeclarativepixmapcache_p.h
@@ -42,69 +42,70 @@
#ifndef QDECLARATIVEPIXMAPCACHE_H
#define QDECLARATIVEPIXMAPCACHE_H
-#include <QtCore/QString>
-#include <QtGui/QPixmap>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qstring.h>
+#include <QtGui/qpixmap.h>
#include <QtCore/qurl.h>
-#include <QtCore/QCoreApplication>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class QDeclarativeEngine;
-class QNetworkReply;
-class QDeclarativeImageReader;
-class QDeclarativePixmapReplyPrivate;
-class Q_DECLARATIVE_EXPORT QDeclarativePixmapReply : public QObject
+class QDeclarativeEngine;
+class QDeclarativePixmapData;
+class Q_AUTOTEST_EXPORT QDeclarativePixmap
{
- Q_OBJECT
+ Q_DECLARE_TR_FUNCTIONS(QDeclarativePixmap)
public:
- ~QDeclarativePixmapReply();
+ QDeclarativePixmap();
+ QDeclarativePixmap(QDeclarativeEngine *, const QUrl &);
+ QDeclarativePixmap(QDeclarativeEngine *, const QUrl &, const QSize &);
+ ~QDeclarativePixmap();
- enum Status { Ready, Error, Unrequested, Loading };
- Status status() const;
- QString errorString() const;
+ enum Status { Null, Ready, Error, Loading };
+ bool isNull() const;
+ bool isReady() const;
+ bool isError() const;
+ bool isLoading() const;
+
+ Status status() const;
+ QString error() const;
const QUrl &url() const;
- int forcedWidth() const;
- int forcedHeight() const;
- QSize implicitSize() const;
+ const QSize &implicitSize() const;
+ const QSize &requestSize() const;
+ const QPixmap &pixmap() const;
+ void setPixmap(const QPixmap &);
-Q_SIGNALS:
- void finished();
- void downloadProgress(qint64, qint64);
+ QRect rect() const;
+ int width() const;
+ int height() const;
+ inline operator const QPixmap &() const;
-protected:
- bool event(QEvent *event);
+ void load(QDeclarativeEngine *, const QUrl &);
+ void load(QDeclarativeEngine *, const QUrl &, bool);
+ void load(QDeclarativeEngine *, const QUrl &, const QSize &);
+ void load(QDeclarativeEngine *, const QUrl &, const QSize &, bool);
-private:
- void addRef();
- bool release(bool defer=false);
- bool isLoading() const;
- void setLoading();
+ void clear();
+ void clear(QObject *);
+
+ bool connectFinished(QObject *, const char *);
+ bool connectFinished(QObject *, int);
+ bool connectDownloadProgress(QObject *, const char *);
+ bool connectDownloadProgress(QObject *, int);
private:
- QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url, int req_width, int req_height);
- Q_DISABLE_COPY(QDeclarativePixmapReply)
- Q_DECLARE_PRIVATE(QDeclarativePixmapReply)
- friend class QDeclarativeImageRequestHandler;
- friend class QDeclarativeImageReader;
- friend class QDeclarativePixmapCache;
+ Q_DISABLE_COPY(QDeclarativePixmap);
+ QDeclarativePixmapData *d;
};
-class Q_DECLARATIVE_EXPORT QDeclarativePixmapCache
+inline QDeclarativePixmap::operator const QPixmap &() const
{
- Q_DECLARE_TR_FUNCTIONS(QDeclarativePixmapCache)
-public:
- static QDeclarativePixmapReply::Status get(const QUrl& url, QPixmap *pixmap, QString *errorString, QSize *impsize=0, bool async=false, int req_width=0, int req_height=0);
- static QDeclarativePixmapReply *request(QDeclarativeEngine *, const QUrl& url, int req_width=0, int req_height=0);
- static void cancel(const QUrl& url, QObject *obj);
- static int pendingRequests();
-};
-
-
+ return pixmap();
+}
QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativestyledtext.cpp b/src/declarative/util/qdeclarativestyledtext.cpp
index babd71b..91566bc 100644
--- a/src/declarative/util/qdeclarativestyledtext.cpp
+++ b/src/declarative/util/qdeclarativestyledtext.cpp
@@ -152,8 +152,6 @@ void QDeclarativeStyledTextPrivate::parse()
QTextCharFormat format;
if (formatStack.count())
format = formatStack.top();
- else
- format.setFont(baseFont);
if (parseTag(ch, text, drawText, format))
formatStack.push(format);
}
@@ -198,8 +196,10 @@ bool QDeclarativeStyledTextPrivate::parseTag(const QChar *&ch, const QString &te
if (char0 == QLatin1Char('b')) {
if (tagLength == 1)
format.setFontWeight(QFont::Bold);
- else if (tagLength == 2 && tag.at(1) == QLatin1Char('r'))
+ else if (tagLength == 2 && tag.at(1) == QLatin1Char('r')) {
textOut.append(QChar(QChar::LineSeparator));
+ return false;
+ }
} else if (char0 == QLatin1Char('i')) {
if (tagLength == 1)
format.setFontItalic(true);
diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp
index 0414e65..12a8d3a 100644
--- a/src/declarative/util/qdeclarativeview.cpp
+++ b/src/declarative/util/qdeclarativeview.cpp
@@ -611,7 +611,7 @@ void QDeclarativeView::timerEvent(QTimerEvent* e)
}
}
-/*! \reimp */
+/*! \internal */
bool QDeclarativeView::eventFilter(QObject *watched, QEvent *e)
{
Q_D(QDeclarativeView);
diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp
index 0692aaa..5583007 100644
--- a/src/declarative/util/qdeclarativexmllistmodel.cpp
+++ b/src/declarative/util/qdeclarativexmllistmodel.cpp
@@ -589,7 +589,7 @@ void QDeclarativeXmlListModelPrivate::clear_role(QDeclarativeListProperty<QDecla
with a combined value of all key roles that is not already present in
the model.
- \sa {declarative/rssnews}{RSS News demo}
+ \sa {demos/declarative/rssnews}{RSS News demo}
*/
QDeclarativeXmlListModel::QDeclarativeXmlListModel(QObject *parent)
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index f3cd481..a55e5f3 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -205,6 +205,7 @@ QTextDocumentPrivate::QTextDocumentPrivate()
undoEnabled = true;
inContentsChange = false;
+ inRemove = false;
defaultTextOption.setTabStop(80); // same as in qtextengine.cpp
defaultTextOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
@@ -669,7 +670,10 @@ void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operati
{
if (length == 0)
return;
+ inRemove = true;
move(pos, -1, length, op);
+ inRemove = false;
+ adjustDocumentChangesAndCursors(pos, -length, op);
}
void QTextDocumentPrivate::setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode)
@@ -1263,6 +1267,9 @@ void QTextDocumentPrivate::documentChange(int from, int length)
*/
void QTextDocumentPrivate::adjustDocumentChangesAndCursors(int from, int addedOrRemoved, QTextUndoCommand::Operation op)
{
+ if (inRemove) // postpone, will be called again from QTextDocumentPrivate::remove()
+ return;
+
if (!editBlock)
++revision;
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index d1bd698..06e0753 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -346,6 +346,7 @@ public:
int maximumBlockCount;
uint needsEnsureMaximumBlockCount : 1;
uint inContentsChange : 1;
+ uint inRemove : 1;
QSizeF pageSize;
QString title;
QString url;
diff --git a/src/imports/gestures/qdeclarativegesturearea.cpp b/src/imports/gestures/qdeclarativegesturearea.cpp
index e5647bd..243ba0f 100644
--- a/src/imports/gestures/qdeclarativegesturearea.cpp
+++ b/src/imports/gestures/qdeclarativegesturearea.cpp
@@ -130,7 +130,7 @@ public:
GestureArea is an invisible item: it is never painted.
- \sa Gesture, MouseArea, {declarative/touchinteraction/gestures}{Gestures example}
+ \sa MouseArea, {declarative/touchinteraction/gestures}{Gestures example}
*/
/*!
diff --git a/src/imports/particles/qdeclarativeparticles.cpp b/src/imports/particles/qdeclarativeparticles.cpp
index 630c068..a7c445d 100644
--- a/src/imports/particles/qdeclarativeparticles.cpp
+++ b/src/imports/particles/qdeclarativeparticles.cpp
@@ -437,7 +437,7 @@ public:
, lifeSpanDev(1000), fadeInDur(200), fadeOutDur(300)
, angle(0), angleDev(0), velocity(0), velocityDev(0), emissionCarry(0.)
, addParticleTime(0), addParticleCount(0), lastAdvTime(0)
- , motion(0), pendingPixmapCache(false), clock(this)
+ , motion(0), clock(this)
{
}
@@ -456,7 +456,7 @@ public:
void updateOpacity(QDeclarativeParticle &p, int age);
QUrl url;
- QPixmap image;
+ QDeclarativePixmap image;
int count;
int emissionRate;
qreal emissionVariance;
@@ -475,7 +475,6 @@ public:
QDeclarativeParticleMotion *motion;
QDeclarativeParticlesPainter *paintItem;
- bool pendingPixmapCache;
QList<QPair<int, int> > bursts;//countLeft, emissionRate pairs
QList<QDeclarativeParticle> particles;
@@ -709,9 +708,6 @@ QDeclarativeParticles::QDeclarativeParticles(QDeclarativeItem *parent)
QDeclarativeParticles::~QDeclarativeParticles()
{
- Q_D(QDeclarativeParticles);
- if (d->pendingPixmapCache)
- QDeclarativePixmapCache::cancel(d->url, this);
}
/*!
@@ -732,10 +728,8 @@ QUrl QDeclarativeParticles::source() const
void QDeclarativeParticles::imageLoaded()
{
Q_D(QDeclarativeParticles);
- d->pendingPixmapCache = false;
- QString errorString;
- if (QDeclarativePixmapCache::get(d->url, &d->image, &errorString)==QDeclarativePixmapReply::Error)
- qmlInfo(this) << errorString;
+ if (d->image.isError())
+ qmlInfo(this) << d->image.error();
d->paintItem->updateSize();
d->paintItem->update();
}
@@ -747,27 +741,20 @@ void QDeclarativeParticles::setSource(const QUrl &name)
if ((d->url.isEmpty() == name.isEmpty()) && name == d->url)
return;
- if (d->pendingPixmapCache) {
- QDeclarativePixmapCache::cancel(d->url, this);
- d->pendingPixmapCache = false;
- }
if (name.isEmpty()) {
d->url = name;
- d->image = QPixmap();
+ d->image.clear(this);
d->paintItem->updateSize();
d->paintItem->update();
} else {
d->url = name;
Q_ASSERT(!name.isRelative());
- QString errorString;
- QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->url, &d->image, &errorString);
- if (status != QDeclarativePixmapReply::Ready && status != QDeclarativePixmapReply::Error) {
- QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(this), d->url);
- connect(reply, SIGNAL(finished()), this, SLOT(imageLoaded()));
- d->pendingPixmapCache = true;
+ d->image.load(qmlEngine(this), d->url);
+ if (d->image.isLoading()) {
+ d->image.connectFinished(this, SLOT(imageLoaded()));
} else {
- if (status == QDeclarativePixmapReply::Error)
- qmlInfo(this) << errorString;
+ if (d->image.isError())
+ qmlInfo(this) << d->image.error();
//### unify with imageLoaded
d->paintItem->updateSize();
d->paintItem->update();