summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWarwick Allison <warwick.allison@nokia.com>2010-04-15 04:47:10 (GMT)
committerWarwick Allison <warwick.allison@nokia.com>2010-04-15 04:48:55 (GMT)
commitaad82abd84022f5401c6b79ab15d24abebf082af (patch)
treebe1bd4efd7f1b7b20b207696ee05a608f49efd27
parent35afac3d3a275aa69c74e174cfeb5e411816e94a (diff)
downloadQt-aad82abd84022f5401c6b79ab15d24abebf082af.zip
Qt-aad82abd84022f5401c6b79ab15d24abebf082af.tar.gz
Qt-aad82abd84022f5401c6b79ab15d24abebf082af.tar.bz2
Correctly resolve, and load, IMG tags in Text element.
Task-number: QTBUG-9900 Reviewed-by: Martin Jones
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext.cpp102
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext_p.h7
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext_p_p.h5
-rw-r--r--tests/auto/declarative/qdeclarativetext/data/embeddedImagesLocal.qml5
-rw-r--r--tests/auto/declarative/qdeclarativetext/data/embeddedImagesLocalError.qml5
-rw-r--r--tests/auto/declarative/qdeclarativetext/data/embeddedImagesRemote.qml5
-rw-r--r--tests/auto/declarative/qdeclarativetext/data/embeddedImagesRemoteError.qml5
-rw-r--r--tests/auto/declarative/qdeclarativetext/data/http/exists.pngbin0 -> 2738 bytes
-rw-r--r--tests/auto/declarative/qdeclarativetext/qdeclarativetext.pro7
-rw-r--r--tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp45
10 files changed, 176 insertions, 10 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp
index 3a35dd5..3b39fa4 100644
--- a/src/declarative/graphicsitems/qdeclarativetext.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetext.cpp
@@ -43,6 +43,7 @@
#include "private/qdeclarativetext_p_p.h"
#include <qdeclarativestyledtext_p.h>
#include <qdeclarativeinfo.h>
+#include <qdeclarativepixmapcache_p.h>
#include <QTextLayout>
#include <QTextLine>
@@ -55,6 +56,50 @@
QT_BEGIN_NAMESPACE
+class QTextDocumentWithImageResources : public QTextDocument {
+ Q_OBJECT
+
+public:
+ QTextDocumentWithImageResources(QDeclarativeText *parent) :
+ QTextDocument(parent),
+ outstanding(0)
+ {
+ }
+
+ 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;
+ QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(url, &pm, 0, true, 0, 0);
+ if (status == QDeclarativePixmapReply::Ready)
+ return pm;
+ if (status != QDeclarativePixmapReply::Error) {
+ QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(parent()), url);
+ connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
+ outstanding++;
+ static_cast<QDeclarativeText*>(parent())->reloadWithResources();
+ }
+ }
+
+ return QTextDocument::loadResource(type,url); // The *resolved* URL
+ }
+
+private slots:
+ void requestFinished()
+ {
+ outstanding--;
+ static_cast<QDeclarativeText*>(parent())->reloadWithResources();
+ }
+
+private:
+ int outstanding;
+};
+
/*!
\qmlclass Text QDeclarativeText
\since 4.7
@@ -77,6 +122,9 @@ QT_BEGIN_NAMESPACE
The \c elide property can alternatively be used to fit a single line of
plain text to a set width.
+ Note that the \l{Supported HTML Subset} is limited, and that if IMG tags
+ load remote images, the text reloads (see resourcesLoading).
+
Text provides read-only text. For editable text, see \l TextEdit.
*/
@@ -259,11 +307,10 @@ void QDeclarativeText::setText(const QString &n)
d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(n));
if (d->richText) {
- if (!d->doc) {
- d->doc = new QTextDocument(this);
- d->doc->setDocumentMargin(0);
+ if (isComponentComplete()) {
+ d->ensureDoc();
+ d->doc->setHtml(n);
}
- d->doc->setHtml(n);
}
d->text = n;
@@ -550,11 +597,10 @@ void QDeclarativeText::setTextFormat(TextFormat format)
d->updateLayout();
d->markImgDirty();
} else if (!wasRich && d->richText) {
- if (!d->doc) {
- d->doc = new QTextDocument(this);
- d->doc->setDocumentMargin(0);
+ if (isComponentComplete()) {
+ d->ensureDoc();
+ d->doc->setHtml(d->text);
}
- d->doc->setHtml(d->text);
d->updateLayout();
d->markImgDirty();
}
@@ -898,6 +944,39 @@ void QDeclarativeTextPrivate::checkImgCache()
imgDirty = false;
}
+void QDeclarativeTextPrivate::ensureDoc()
+{
+ if (!doc) {
+ Q_Q(QDeclarativeText);
+ doc = new QTextDocumentWithImageResources(q);
+ doc->setDocumentMargin(0);
+ }
+}
+
+void QDeclarativeText::reloadWithResources()
+{
+ Q_D(QDeclarativeText);
+ if (!d->richText)
+ return;
+ if (resourcesLoading()!=0)
+ return;
+ emit resourcesLoadingChanged();
+ d->doc->setHtml(d->text);
+ d->updateLayout();
+ d->markImgDirty();
+}
+
+/*!
+ \qmlproperty int Text::resourcesLoading
+ This property is the number of resources (images) that are being loaded asynchronously.
+*/
+int QDeclarativeText::resourcesLoading() const
+{
+ Q_D(const QDeclarativeText);
+ return d->doc ? d->doc->resourcesLoading() : 0;
+}
+
+
void QDeclarativeText::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
{
Q_D(QDeclarativeText);
@@ -1011,6 +1090,10 @@ void QDeclarativeText::componentComplete()
Q_D(QDeclarativeText);
QDeclarativeItem::componentComplete();
if (d->dirty) {
+ if (d->richText) {
+ d->ensureDoc();
+ d->doc->setHtml(d->text);
+ }
d->updateLayout();
d->dirty = false;
}
@@ -1061,4 +1144,7 @@ void QDeclarativeText::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if (!event->isAccepted())
QDeclarativeItem::mouseReleaseEvent(event);
}
+
QT_END_NAMESPACE
+
+#include "qdeclarativetext.moc"
diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h
index 871c833..fcad898 100644
--- a/src/declarative/graphicsitems/qdeclarativetext_p.h
+++ b/src/declarative/graphicsitems/qdeclarativetext_p.h
@@ -72,6 +72,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeText : public QDeclarativeItem
Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapModeChanged)
Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged)
Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode?
+ Q_PROPERTY(int resourcesLoading READ resourcesLoading NOTIFY resourcesLoadingChanged)
public:
QDeclarativeText(QDeclarativeItem *parent=0);
@@ -138,6 +139,8 @@ public:
virtual void componentComplete();
+ int resourcesLoading() const;
+
Q_SIGNALS:
void textChanged(const QString &text);
void linkActivated(const QString &link);
@@ -150,6 +153,7 @@ Q_SIGNALS:
void wrapModeChanged();
void textFormatChanged(TextFormat textFormat);
void elideModeChanged(TextElideMode mode);
+ void resourcesLoadingChanged();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
@@ -160,6 +164,9 @@ 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 cc5a9f2..332f99e 100644
--- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h
@@ -63,7 +63,7 @@
QT_BEGIN_NAMESPACE
class QTextLayout;
-class QTextDocument;
+class QTextDocumentWithImageResources;
class QDeclarativeTextPrivate : public QDeclarativeItemPrivate
{
@@ -84,6 +84,7 @@ public:
~QDeclarativeTextPrivate();
+ void ensureDoc();
void updateSize();
void updateLayout();
void markImgDirty() {
@@ -118,7 +119,7 @@ public:
bool richText:1;
bool singleline:1;
bool cache:1;
- QTextDocument *doc;
+ QTextDocumentWithImageResources *doc;
QTextLayout layout;
QSize cachedLayoutSize;
QDeclarativeText::TextFormat format;
diff --git a/tests/auto/declarative/qdeclarativetext/data/embeddedImagesLocal.qml b/tests/auto/declarative/qdeclarativetext/data/embeddedImagesLocal.qml
new file mode 100644
index 0000000..5aeea56
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetext/data/embeddedImagesLocal.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+Text {
+ text: "<img src='http/exists.png'>"
+}
diff --git a/tests/auto/declarative/qdeclarativetext/data/embeddedImagesLocalError.qml b/tests/auto/declarative/qdeclarativetext/data/embeddedImagesLocalError.qml
new file mode 100644
index 0000000..17bb21c
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetext/data/embeddedImagesLocalError.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+Text {
+ text: "<img src='http/notexists.png'>"
+}
diff --git a/tests/auto/declarative/qdeclarativetext/data/embeddedImagesRemote.qml b/tests/auto/declarative/qdeclarativetext/data/embeddedImagesRemote.qml
new file mode 100644
index 0000000..53b0266
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetext/data/embeddedImagesRemote.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+Text {
+ text: "<img src='http://127.0.0.1:14453/exists.png'>"
+}
diff --git a/tests/auto/declarative/qdeclarativetext/data/embeddedImagesRemoteError.qml b/tests/auto/declarative/qdeclarativetext/data/embeddedImagesRemoteError.qml
new file mode 100644
index 0000000..48c7a95
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetext/data/embeddedImagesRemoteError.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+Text {
+ text: "<img src='http://127.0.0.1:14453/notexists.png'>"
+}
diff --git a/tests/auto/declarative/qdeclarativetext/data/http/exists.png b/tests/auto/declarative/qdeclarativetext/data/http/exists.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetext/data/http/exists.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativetext/qdeclarativetext.pro b/tests/auto/declarative/qdeclarativetext/qdeclarativetext.pro
index 73c05b5..e70443e 100644
--- a/tests/auto/declarative/qdeclarativetext/qdeclarativetext.pro
+++ b/tests/auto/declarative/qdeclarativetext/qdeclarativetext.pro
@@ -1,8 +1,15 @@
load(qttest_p4)
contains(QT_CONFIG,declarative): QT += declarative gui
+QT += network
macx:CONFIG -= app_bundle
SOURCES += tst_qdeclarativetext.cpp
+INCLUDEPATH += ../shared/
+HEADERS += ../shared/testhttpserver.h
+SOURCES += ../shared/testhttpserver.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
+
CONFIG += parallel_test
diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp
index 6637415..53640d0 100644
--- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp
+++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp
@@ -48,6 +48,9 @@
#include <QGraphicsSceneMouseEvent>
#include <qmath.h>
+#include "../../../shared/util.h"
+#include "testhttpserver.h"
+
class tst_qdeclarativetext : public QObject
{
@@ -62,6 +65,9 @@ private slots:
void elide();
void textFormat();
+ void embeddedImages_data();
+ void embeddedImages();
+
// ### these tests may be trivial
void horizontalAlignment();
void verticalAlignment();
@@ -859,6 +865,45 @@ void tst_qdeclarativetext::clickLink()
}
}
+void tst_qdeclarativetext::embeddedImages_data()
+{
+ QTest::addColumn<QUrl>("qmlfile");
+ QTest::addColumn<QString>("error");
+ QTest::newRow("local") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesLocal.qml") << "";
+ QTest::newRow("local-error") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesLocalError.qml")
+ << "\"Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/http/notexists.png").toString() + "\" ";
+ QTest::newRow("remote") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesRemote.qml") << "";
+ QTest::newRow("remote-error") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesRemoteError.qml")
+ << "\"Error downloading http://127.0.0.1:14453/notexists.png - server replied: Not found\" ";
+}
+
+void tst_qdeclarativetext::embeddedImages()
+{
+ // Tests QTBUG-9900
+
+ QFETCH(QUrl, qmlfile);
+ QFETCH(QString, error);
+
+ TestHTTPServer server(14453);
+ server.serveDirectory(SRCDIR "/data/http");
+
+ if (!error.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, error.toLatin1());
+
+ QDeclarativeComponent textComponent(&engine, qmlfile);
+ QDeclarativeText *textObject = qobject_cast<QDeclarativeText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+
+ QTRY_COMPARE(textObject->resourcesLoading(), 0);
+
+ if (error.isEmpty()) {
+ QPixmap pm(SRCDIR "/data/http/exists.png");
+ QCOMPARE(textObject->width(), double(pm.width()));
+ QCOMPARE(textObject->height(), double(pm.height()));
+ }
+}
+
QTEST_MAIN(tst_qdeclarativetext)
#include "tst_qdeclarativetext.moc"