diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2010-07-05 04:20:14 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2010-07-05 08:31:07 (GMT) |
commit | 09f07b98dfdaec2e48749768b967a48e588d3f7f (patch) | |
tree | afb3d254883bef441614a2c9453be8ac9bf51e5f /src/declarative/graphicsitems/qdeclarativetext.cpp | |
parent | b2aedd1d57a5a681b1185bf8908683ff563de4d6 (diff) | |
download | Qt-09f07b98dfdaec2e48749768b967a48e588d3f7f.zip Qt-09f07b98dfdaec2e48749768b967a48e588d3f7f.tar.gz Qt-09f07b98dfdaec2e48749768b967a48e588d3f7f.tar.bz2 |
Make declarative pixmap cache easier to use
The QDeclarativePixmapCache was both slow, and very trickey to use correctly.
Many QML elements did not correctly cancel outstanding requests, which leads
to pixmaps leaking indefinately. Other elements, such as Text, were
subject to race conditions that meant they may never actually load all their
images.
QDeclarativePixmap is a single class than encapsulates the action of
fetching a pixmap, as well as the pixmap itself and the responsibility of
canceling outstanding requests. Rather than relying on Qt's pixmap cache
that doesn't cache all the information QML needs, QDeclarativePixmap
implements its own cache, that correctly degrades over time (unlike
QPixmapCache that can stop expiring items in some conditions).
Reviewed-by: Warwick Allison
Diffstat (limited to 'src/declarative/graphicsitems/qdeclarativetext.cpp')
-rw-r--r-- | src/declarative/graphicsitems/qdeclarativetext.cpp | 148 |
1 files changed, 85 insertions, 63 deletions
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; |