aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Bodson <yann.bodson@nokia.com>2011-11-28 11:26:40 +1000
committerQt by Nokia <qt-info@nokia.com>2012-02-02 11:11:53 +0100
commit8872c0716fb33e33311a78e693b61d3dd6b656c1 (patch)
tree01b970d0cc196cb99b971f9905d3a002a1a97190
parent76ed62fb836ea3e3e5236f8ed567f7ac64dd63fc (diff)
Support inline images with <img> tag in StyledText
Task-number: QTBUG-21793 Change-Id: Ie7b9f293c6c9a949c1899152c38b61251b0069d3 Reviewed-by: Yann Bodson <yann.bodson@nokia.com>
-rw-r--r--examples/declarative/text/imgtag/TextWithImage.qml55
-rw-r--r--examples/declarative/text/imgtag/images/face-sad.pngbin0 -> 6148 bytes
-rw-r--r--examples/declarative/text/imgtag/images/face-smile-big.pngbin0 -> 6058 bytes
-rw-r--r--examples/declarative/text/imgtag/images/face-smile.pngbin0 -> 6446 bytes
-rw-r--r--examples/declarative/text/imgtag/images/heart200.pngbin0 -> 8248 bytes
-rw-r--r--examples/declarative/text/imgtag/images/qtlogo.pngbin0 -> 6450 bytes
-rw-r--r--examples/declarative/text/imgtag/images/starfish_2.pngbin0 -> 18243 bytes
-rw-r--r--examples/declarative/text/imgtag/imgtag.qml101
-rw-r--r--examples/declarative/text/styledtext-layout.qml55
-rw-r--r--src/quick/items/qquicktext.cpp151
-rw-r--r--src/quick/items/qquicktext_p.h3
-rw-r--r--src/quick/items/qquicktext_p_p.h7
-rw-r--r--src/quick/util/qdeclarativestyledtext.cpp98
-rw-r--r--src/quick/util/qdeclarativestyledtext_p.h46
-rw-r--r--tests/auto/qtquick2/qdeclarativestyledtext/tst_qdeclarativestyledtext.cpp7
-rw-r--r--tests/auto/qtquick2/qquicktext/data/images/face-sad.pngbin0 -> 6148 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/images/heart200.pngbin0 -> 8248 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/images/starfish_2.pngbin0 -> 18243 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/imgTagsElide.qml24
-rw-r--r--tests/auto/qtquick2/qquicktext/data/imgTagsUpdates.qml12
-rw-r--r--tests/auto/qtquick2/qquicktext/tst_qquicktext.cpp120
21 files changed, 620 insertions, 59 deletions
diff --git a/examples/declarative/text/imgtag/TextWithImage.qml b/examples/declarative/text/imgtag/TextWithImage.qml
new file mode 100644
index 0000000000..bc09aa2a52
--- /dev/null
+++ b/examples/declarative/text/imgtag/TextWithImage.qml
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Text {
+ width: parent.width
+ font.pointSize: 14
+ wrapMode: Text.WordWrap
+ textFormat: Text.StyledText
+ horizontalAlignment: main.hAlign
+
+ Rectangle {
+ border.color: "#efefef"
+ color: "transparent"
+ anchors.fill: parent
+ }
+}
diff --git a/examples/declarative/text/imgtag/images/face-sad.png b/examples/declarative/text/imgtag/images/face-sad.png
new file mode 100644
index 0000000000..24188b7985
--- /dev/null
+++ b/examples/declarative/text/imgtag/images/face-sad.png
Binary files differ
diff --git a/examples/declarative/text/imgtag/images/face-smile-big.png b/examples/declarative/text/imgtag/images/face-smile-big.png
new file mode 100644
index 0000000000..d05e0bf21e
--- /dev/null
+++ b/examples/declarative/text/imgtag/images/face-smile-big.png
Binary files differ
diff --git a/examples/declarative/text/imgtag/images/face-smile.png b/examples/declarative/text/imgtag/images/face-smile.png
new file mode 100644
index 0000000000..e5e1d1353c
--- /dev/null
+++ b/examples/declarative/text/imgtag/images/face-smile.png
Binary files differ
diff --git a/examples/declarative/text/imgtag/images/heart200.png b/examples/declarative/text/imgtag/images/heart200.png
new file mode 100644
index 0000000000..cedd3ea608
--- /dev/null
+++ b/examples/declarative/text/imgtag/images/heart200.png
Binary files differ
diff --git a/examples/declarative/text/imgtag/images/qtlogo.png b/examples/declarative/text/imgtag/images/qtlogo.png
new file mode 100644
index 0000000000..996719a4c6
--- /dev/null
+++ b/examples/declarative/text/imgtag/images/qtlogo.png
Binary files differ
diff --git a/examples/declarative/text/imgtag/images/starfish_2.png b/examples/declarative/text/imgtag/images/starfish_2.png
new file mode 100644
index 0000000000..132c20ffd0
--- /dev/null
+++ b/examples/declarative/text/imgtag/images/starfish_2.png
Binary files differ
diff --git a/examples/declarative/text/imgtag/imgtag.qml b/examples/declarative/text/imgtag/imgtag.qml
new file mode 100644
index 0000000000..7f0d1dcfa3
--- /dev/null
+++ b/examples/declarative/text/imgtag/imgtag.qml
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: main
+ width: 640; height: 800
+ focus: true
+
+ property var hAlign: Text.AlignLeft
+
+ Flickable {
+ anchors.fill: parent
+ contentWidth: parent.width
+ contentHeight: col.height + 20
+
+ Column {
+ id: col
+ x: 10; y: 10
+ spacing: 20
+ width: parent.width - 20
+
+ TextWithImage {
+ text: "This is a <b>happy</b> face<img src=\"images/face-smile.png\">"
+ }
+ TextWithImage {
+ text: "This is a <b>very<img src=\"images/face-smile-big.png\" align=\"middle\"/>happy</b> face aligned in the middle."
+ }
+ TextWithImage {
+ elide: Text.ElideRight
+ maximumLineCount: 2
+ text: "This is a sad face aligned to the top. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc rutrum dui pretium ipsum malesuada venenatis. Nulla sed turpis risus. Integer sit amet odio quis mauris varius venenatis<img src=\"images/face-sad.png\" align=\"top\">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc rutrum dui pretium ipsum malesuada venenatis. Nulla sed turpis risus. Integer sit amet odio quis mauris varius venenatis."
+ }
+ TextWithImage {
+ text: "This is a tiny<img src=\"images/face-smile.png\" width=\"15\" height=\"15\">happy face."
+ }
+ TextWithImage {
+ text: "This is a starfish<img src=\"images/starfish_2.png\" width=\"50\" height=\"50\" align=\"top\">aligned to the top and another one<img src=\"images/heart200.png\" width=\"50\" height=\"50\">aligned to the bottom."
+ }
+ TextWithImage {
+ text: "Qt logos<img src=\"images/qtlogo.png\" width=\"55\" height=\"60\" align=\"middle\"><img src=\"images/qtlogo.png\" width=\"37\" height=\"40\" align=\"middle\"><img src=\"images/qtlogo.png\" width=\"18\" height=\"20\" align=\"middle\">aligned in the middle with different sizes."
+ }
+ TextWithImage {
+ text: "Some hearts<img src=\"images/heart200.png\" width=\"20\" height=\"20\" align=\"bottom\"><img src=\"images/heart200.png\" width=\"30\" height=\"30\" align=\"bottom\"> <img src=\"images/heart200.png\" width=\"40\" height=\"40\"><img src=\"images/heart200.png\" width=\"50\" height=\"50\" align=\"bottom\">with different sizes."
+ }
+ TextWithImage {
+ text: "Resized image<img width=\"80\" height=\"76\" align=\"middle\" src=\"http://files.app4mobile.com/wp-content/uploads/2011/08/nokia-n9-price-specification-features-us-europe-india.jpg\">from the internet."
+ }
+ TextWithImage {
+ text: "Image<img align=\"middle\" src=\"http://qt.gitorious.org/images/sites/qt/logo.png\">from the internet."
+ }
+ TextWithImage {
+ height: 120
+ verticalAlignment: Text.AlignVCenter
+ text: "This is a <b>happy</b> face<img src=\"images/face-smile.png\"> with an explicit height."
+ }
+ }
+ }
+
+ Keys.onUpPressed: main.hAlign = Text.AlignHCenter
+ Keys.onLeftPressed: main.hAlign = Text.AlignLeft
+ Keys.onRightPressed: main.hAlign = Text.AlignRight
+}
diff --git a/examples/declarative/text/styledtext-layout.qml b/examples/declarative/text/styledtext-layout.qml
index c76dd44f40..291d75f109 100644
--- a/examples/declarative/text/styledtext-layout.qml
+++ b/examples/declarative/text/styledtext-layout.qml
@@ -3,37 +3,36 @@
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
+** This file is part of the examples of the Qt Toolkit.
**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 16fbc85b77..e7673478bd 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -58,12 +58,13 @@
#include <QtGui/qguiapplication.h>
#include <QtGui/qinputpanel.h>
-#include <private/qdeclarativestyledtext_p.h>
#include <QtQuick/private/qdeclarativepixmapcache_p.h>
#include <qmath.h>
#include <limits.h>
+DEFINE_BOOL_CONFIG_OPTION(qmlTextDebug, QML_TEXT_DEBUG)
+
QT_BEGIN_NAMESPACE
extern Q_GUI_EXPORT bool qt_applefontsmoothing_enabled;
@@ -85,12 +86,12 @@ QQuickTextPrivate::QQuickTextPrivate()
disableDistanceField(false), internalWidthUpdate(false),
requireImplicitWidth(false), truncated(false), hAlignImplicit(true), rightToLeftText(false),
layoutTextElided(false), richTextAsImage(false), textureImageCacheDirty(false), textHasChanged(true),
- naturalWidth(0), doc(0), elipsisLayout(0), textLine(0), nodeType(NodeIsNull), updateType(UpdatePaintNode)
+ needToUpdateLayout(false), naturalWidth(0), doc(0), elipsisLayout(0), textLine(0), nodeType(NodeIsNull),
+ updateType(UpdatePaintNode), nbActiveDownloads(0)
#if defined(Q_OS_MAC)
, layoutThread(0), paintingThread(0)
#endif
-
{
cacheAllTextAsImage = enableImageCache();
disableDistanceField = qmlDisableDistanceField();
@@ -266,6 +267,8 @@ QQuickTextPrivate::~QQuickTextPrivate()
delete elipsisLayout;
delete textLine; textLine = 0;
delete imageCache;
+ qDeleteAll(imgTags);
+ imgTags.clear();
}
qreal QQuickTextPrivate::getImplicitWidth() const
@@ -295,6 +298,11 @@ void QQuickTextPrivate::updateLayout()
}
updateOnComponentComplete = false;
layoutTextElided = false;
+
+ if (!visibleImgTags.isEmpty())
+ visibleImgTags.clear();
+ needToUpdateLayout = false;
+
// Setup instance of QTextLayout for all cases other than richtext
if (!richText) {
if (elipsisLayout) {
@@ -329,7 +337,7 @@ void QQuickTextPrivate::updateLayout()
} else {
singleline = false;
if (textHasChanged) {
- QDeclarativeStyledText::parse(text, layout);
+ QDeclarativeStyledText::parse(text, layout, imgTags, qmlContext(q), !maximumLineCountValid);
textHasChanged = false;
}
}
@@ -346,6 +354,41 @@ void QQuickTextPrivate::updateLayout()
}
updateSize();
+
+ if (needToUpdateLayout) {
+ needToUpdateLayout = false;
+ textHasChanged = true;
+ updateLayout();
+ }
+}
+
+void QQuickText::imageDownloadFinished()
+{
+ Q_D(QQuickText);
+
+ (d->nbActiveDownloads)--;
+
+ // when all the remote images have been downloaded,
+ // if one of the sizes was not specified at parsing time
+ // we use the implicit size from pixmapcache and re-layout.
+
+ if (d->nbActiveDownloads == 0) {
+ bool needToUpdateLayout = false;
+ foreach (QDeclarativeStyledTextImgTag *img, d->visibleImgTags) {
+ if (!img->size.isValid()) {
+ img->size = img->pix->implicitSize();
+ needToUpdateLayout = true;
+ }
+ }
+
+ if (needToUpdateLayout) {
+ d->textHasChanged = true;
+ d->updateLayout();
+ } else {
+ d->updateType = QQuickTextPrivate::UpdatePaintNode;
+ update();
+ }
+ }
}
void QQuickTextPrivate::updateSize()
@@ -659,6 +702,7 @@ QRect QQuickTextPrivate::setupTextLayout()
lineWidth = INT_MAX;
int linesLeft = maximumLineCount;
int visibleTextLength = 0;
+
forever {
QTextLine line = layout.createLine();
if (!line.isValid())
@@ -667,13 +711,10 @@ QRect QQuickTextPrivate::setupTextLayout()
visibleCount++;
qreal preLayoutHeight = height;
- if (customLayout) {
+ if (customLayout)
setupCustomLineGeometry(line, height);
- } else if (lineWidth) {
- line.setLineWidth(lineWidth);
- line.setPosition(QPointF(line.position().x(), height));
- height += (lineHeightMode == QQuickText::FixedHeight) ? lineHeight : line.height() * lineHeight;
- }
+ else if (lineWidth)
+ setLineGeometry(line, lineWidth, height);
bool elide = false;
if (multilineElideEnabled && q->heightValid() && height > q->height()) {
@@ -682,7 +723,7 @@ QRect QQuickTextPrivate::setupTextLayout()
if (visibleCount > 1) {
--visibleCount;
height = preLayoutHeight;
- line.setLineWidth(0.0);
+ setLineGeometry(line, 0.0, height);
line.setPosition(QPointF(FLT_MAX,FLT_MAX));
line = layout.lineAt(visibleCount-1);
}
@@ -693,13 +734,14 @@ QRect QQuickTextPrivate::setupTextLayout()
if (elide || (maximumLineCountValid && --linesLeft == 0)) {
if (visibleTextLength < text.length()) {
truncate = true;
+ height = preLayoutHeight;
if (multilineElideEnabled) {
qreal elideWidth = fm.width(elideChar);
// Need to correct for alignment
if (customLayout)
setupCustomLineGeometry(line, height, elideWidth);
else
- line.setLineWidth(lineWidth - elideWidth);
+ setLineGeometry(line, lineWidth - elideWidth, height);
if (layout.text().mid(line.textStart(), line.textLength()).isRightToLeft()) {
line.setPosition(QPointF(line.position().x() + elideWidth, line.position().y()));
elidePos.setX(line.naturalTextRect().left() - elideWidth);
@@ -722,6 +764,7 @@ QRect QQuickTextPrivate::setupTextLayout()
br = br.united(line.naturalTextRect());
}
layout.endLayout();
+ br.moveTop(0);
//Update truncated
if (truncated != truncate) {
@@ -740,10 +783,71 @@ QRect QQuickTextPrivate::setupTextLayout()
lineCount = visibleCount;
emit q->lineCountChanged();
}
-
return QRect(qRound(br.x()), qRound(br.y()), qCeil(br.width()), qCeil(br.height()));
}
+void QQuickTextPrivate::setLineGeometry(QTextLine &line, qreal lineWidth, qreal &height)
+{
+ Q_Q(QQuickText);
+ line.setLineWidth(lineWidth);
+
+ if (imgTags.isEmpty()) {
+ line.setPosition(QPointF(line.position().x(), height));
+ height += (lineHeightMode == QQuickText::FixedHeight) ? lineHeight : line.height() * lineHeight;
+ return;
+ }
+
+ qreal textTop = 0;
+ qreal textHeight = line.height();
+ qreal totalLineHeight = textHeight;
+
+ QList<QDeclarativeStyledTextImgTag *> imagesInLine;
+
+ foreach (QDeclarativeStyledTextImgTag *image, imgTags) {
+ if (image->position >= line.textStart() &&
+ image->position < line.textStart() + line.textLength()) {
+
+ if (!image->pix) {
+ QUrl url = qmlContext(q)->resolvedUrl(image->url);
+ image->pix = new QDeclarativePixmap(qmlEngine(q), url, image->size);
+ if (image->pix->isLoading()) {
+ image->pix->connectFinished(q, SLOT(imageDownloadFinished()));
+ nbActiveDownloads++;
+ } else if (image->pix->isReady()) {
+ if (!image->size.isValid()) {
+ image->size = image->pix->implicitSize();
+ // if the size of the image was not explicitly set, we need to
+ // call updateLayout() once again.
+ needToUpdateLayout = true;
+ }
+ } else if (image->pix->isError()) {
+ qmlInfo(q) << image->pix->error();
+ }
+ }
+
+ qreal ih = qreal(image->size.height());
+ if (image->align == QDeclarativeStyledTextImgTag::Top)
+ image->pos.setY(0);
+ else if (image->align == QDeclarativeStyledTextImgTag::Middle)
+ image->pos.setY((textHeight / 2.0) - (ih / 2.0));
+ else
+ image->pos.setY(textHeight - ih);
+ imagesInLine << image;
+ textTop = qMax(textTop, qAbs(image->pos.y()));
+ }
+ }
+
+ foreach (QDeclarativeStyledTextImgTag *image, imagesInLine) {
+ totalLineHeight = qMax(totalLineHeight, textTop + image->pos.y() + image->size.height());
+ image->pos.setX(line.cursorToX(image->position));
+ image->pos.setY(image->pos.y() + height + textTop);
+ visibleImgTags << image;
+ }
+
+ line.setPosition(QPointF(line.position().x(), height + textTop));
+ height += (lineHeightMode == QQuickText::FixedHeight) ? lineHeight : totalLineHeight * lineHeight;
+}
+
/*!
Returns a painted version of the QQuickTextPrivate::layout QTextLayout.
If \a drawStyle is true, the style color overrides all colors in the document.
@@ -1251,6 +1355,8 @@ void QQuickText::setText(const QString &n)
d->determineHorizontalAlignment();
}
d->textHasChanged = true;
+ qDeleteAll(d->imgTags);
+ d->imgTags.clear();
d->updateLayout();
emit textChanged(d->text);
}
@@ -1629,6 +1735,7 @@ void QQuickText::resetMaximumLineCount()
<font color="color_name" size="1-7"></font>
<h1> to <h6> - headers
<a href=""> - anchor
+ <img src="" align="top,middle,bottom" width="" height=""> - inline images
<ol type="">, <ul type=""> and <li> - ordered and unordered lists
<pre></pre> - preformatted
&gt; &lt; &amp;
@@ -1947,6 +2054,24 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
node->addTextLayout(QPoint(0, bounds.y()), d->elipsisLayout, d->color, d->style, d->styleColor);
}
+ foreach (QDeclarativeStyledTextImgTag *img, d->visibleImgTags) {
+ if (qmlTextDebug()) {
+ QSGRectangleNode *rectangle = d->sceneGraphContext()->createRectangleNode();
+ rectangle->setRect(QRectF(img->pos.x(), img->pos.y() + bounds.y(),img->size.width(), img->size.height()));
+ rectangle->setColor(QColor("red"));
+ rectangle->update();
+ node->appendChildNode(rectangle);
+ }
+ QDeclarativePixmap *pix = img->pix;
+ if (pix && pix->isReady()) {
+ QSGTexture *texture = d->sceneGraphContext()->textureForFactory(pix->textureFactory());
+ QSGImageNode *imgnode = d->sceneGraphContext()->createImageNode();
+ imgnode->setTexture(texture);
+ imgnode->setTargetRect(QRectF(img->pos.x(), img->pos.y() + bounds.y(), pix->width(), pix->height()));
+ node->appendChildNode(imgnode);
+ imgnode->update();
+ }
+ }
return node;
}
}
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index 0725f53c66..ddc9d38c75 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -44,9 +44,7 @@
#define QQUICKTEXT_P_H
#include "qquickimplicitsizeitem_p.h"
-
#include <private/qtquickglobal_p.h>
-
#include <QtGui/qtextoption.h>
QT_BEGIN_HEADER
@@ -212,6 +210,7 @@ protected:
private Q_SLOTS:
void q_imagesLoaded();
void triggerPreprocess();
+ void imageDownloadFinished();
private:
Q_DISABLE_COPY(QQuickText)
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index 40c50378f0..e7b0478e21 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -60,6 +60,7 @@
#include <QtDeclarative/qdeclarative.h>
#include <QtGui/qabstracttextdocumentlayout.h>
#include <QtGui/qtextlayout.h>
+#include <private/qdeclarativestyledtext_p.h>
QT_BEGIN_NAMESPACE
@@ -82,6 +83,7 @@ public:
void mirrorChange();
QTextDocument *textDocument();
bool isLineLaidOutConnected();
+ void setLineGeometry(QTextLine &line, qreal lineWidth, qreal &height);
QString text;
QUrl baseUrl;
@@ -127,6 +129,7 @@ public:
bool richTextAsImage:1;
bool textureImageCacheDirty:1;
bool textHasChanged:1;
+ bool needToUpdateLayout:1;
QRect layedOutTextRect;
QSize paintedSize;
@@ -168,6 +171,10 @@ public:
};
UpdateType updateType;
+ QList<QDeclarativeStyledTextImgTag*> imgTags;
+ QList<QDeclarativeStyledTextImgTag*> visibleImgTags;
+ int nbActiveDownloads;
+
#if defined(Q_OS_MAC)
QList<QRectF> linesRects;
QThread *layoutThread;
diff --git a/src/quick/util/qdeclarativestyledtext.cpp b/src/quick/util/qdeclarativestyledtext.cpp
index d34601d09f..39ea6b1a22 100644
--- a/src/quick/util/qdeclarativestyledtext.cpp
+++ b/src/quick/util/qdeclarativestyledtext.cpp
@@ -46,6 +46,7 @@
#include <QDebug>
#include <qmath.h>
#include "qdeclarativestyledtext_p.h"
+#include <QDeclarativeContext>
/*
QDeclarativeStyledText supports few tags:
@@ -61,6 +62,7 @@
<a href=""> - anchor
<ol type="">, <ul type=""> and <li> - ordered and unordered lists
<pre></pre> - preformated
+ <img src=""> - images
The opening and closing tags must be correctly nested.
*/
@@ -79,9 +81,12 @@ public:
ListFormat format;
};
- QDeclarativeStyledTextPrivate(const QString &t, QTextLayout &l)
- : text(t), layout(l), baseFont(layout.font()), hasNewLine(false)
- , preFormat(false), prependSpace(false), hasSpace(true)
+ QDeclarativeStyledTextPrivate(const QString &t, QTextLayout &l,
+ QList<QDeclarativeStyledTextImgTag*> &imgTags,
+ QDeclarativeContext *context,
+ bool preloadImages)
+ : text(t), layout(l), imgTags(&imgTags), baseFont(layout.font()), hasNewLine(false), nbImages(0), updateImagePositions(false)
+ , preFormat(false), prependSpace(false), hasSpace(true), preloadImages(preloadImages), context(context)
{
}
@@ -94,6 +99,7 @@ public:
bool parseOrderedListAttributes(const QChar *&ch, const QString &textIn);
bool parseUnorderedListAttributes(const QChar *&ch, const QString &textIn);
bool parseAnchorAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format);
+ void parseImageAttributes(const QChar *&ch, const QString &textIn, QString &textOut);
QPair<QStringRef,QStringRef> parseAttribute(const QChar *&ch, const QString &textIn);
QStringRef parseValue(const QChar *&ch, const QString &textIn);
@@ -108,12 +114,17 @@ public:
QString text;
QTextLayout &layout;
+ QList<QDeclarativeStyledTextImgTag*> *imgTags;
QFont baseFont;
QStack<List> listStack;
bool hasNewLine;
+ int nbImages;
+ bool updateImagePositions;
bool preFormat;
bool prependSpace;
bool hasSpace;
+ bool preloadImages;
+ QDeclarativeContext *context;
static const QChar lessThan;
static const QChar greaterThan;
@@ -143,8 +154,10 @@ const QChar QDeclarativeStyledTextPrivate::square(0x25a1);
const QChar QDeclarativeStyledTextPrivate::lineFeed(QLatin1Char('\n'));
const QChar QDeclarativeStyledTextPrivate::space(QLatin1Char(' '));
-QDeclarativeStyledText::QDeclarativeStyledText(const QString &string, QTextLayout &layout)
-: d(new QDeclarativeStyledTextPrivate(string, layout))
+QDeclarativeStyledText::QDeclarativeStyledText(const QString &string, QTextLayout &layout,
+ QList<QDeclarativeStyledTextImgTag*> &imgTags, QDeclarativeContext *context,
+ bool preloadImages)
+ : d(new QDeclarativeStyledTextPrivate(string, layout, imgTags, context, preloadImages))
{
}
@@ -153,11 +166,13 @@ QDeclarativeStyledText::~QDeclarativeStyledText()
delete d;
}
-void QDeclarativeStyledText::parse(const QString &string, QTextLayout &layout)
+void QDeclarativeStyledText::parse(const QString &string, QTextLayout &layout,
+ QList<QDeclarativeStyledTextImgTag*> &imgTags, QDeclarativeContext *context,
+ bool preloadImages)
{
if (string.isEmpty())
return;
- QDeclarativeStyledText styledText(string, layout);
+ QDeclarativeStyledText styledText(string, layout, imgTags, context, preloadImages);
styledText.d->parse();
}
@@ -169,6 +184,8 @@ void QDeclarativeStyledTextPrivate::parse()
QString drawText;
drawText.reserve(text.count());
+ updateImagePositions = !imgTags->isEmpty();
+
int textStart = 0;
int textLength = 0;
int rangeStart = 0;
@@ -401,6 +418,10 @@ bool QDeclarativeStyledTextPrivate::parseTag(const QChar *&ch, const QString &te
if (tag == QLatin1String("a")) {
return parseAnchorAttributes(ch, textIn, format);
}
+ if (tag == QLatin1String("img")) {
+ parseImageAttributes(ch, textIn, textOut);
+ return false;
+ }
if (*ch == greaterThan || ch->isNull())
continue;
} else if (*ch != slash) {
@@ -606,6 +627,69 @@ bool QDeclarativeStyledTextPrivate::parseAnchorAttributes(const QChar *&ch, cons
return valid;
}
+void QDeclarativeStyledTextPrivate::parseImageAttributes(const QChar *&ch, const QString &textIn, QString &textOut)
+{
+ qreal imgWidth = 0.0;
+
+ if (!updateImagePositions) {
+ QDeclarativeStyledTextImgTag *image = new QDeclarativeStyledTextImgTag;
+ image->position = textOut.length() + 1;
+
+ QPair<QStringRef,QStringRef> attr;
+ do {
+ attr = parseAttribute(ch, textIn);
+ if (attr.first == QLatin1String("src")) {
+ image->url = QUrl(attr.second.toString());
+ } else if (attr.first == QLatin1String("width")) {
+ image->size.setWidth(attr.second.toString().toInt());
+ } else if (attr.first == QLatin1String("height")) {
+ image->size.setHeight(attr.second.toString().toInt());
+ } else if (attr.first == QLatin1String("align")) {
+ if (attr.second.toString() == QLatin1String("top")) {
+ image->align = QDeclarativeStyledTextImgTag::Top;
+ } else if (attr.second.toString() == QLatin1String("middle")) {
+ image->align = QDeclarativeStyledTextImgTag::Middle;
+ }
+ }
+ } while (!ch->isNull() && !attr.first.isEmpty());
+
+ if (preloadImages && !image->size.isValid()) {
+ // if we don't know its size but the image is a local image,
+ // we load it in the pixmap cache and save its implicit size
+ // to avoid a relayout later on.
+ QUrl url = context->resolvedUrl(image->url);
+ if (url.isLocalFile()) {
+ QDeclarativePixmap *pix = new QDeclarativePixmap(context->engine(), url, image->size);
+ if (pix && pix->isReady()) {
+ image->size = pix->implicitSize();
+ image->pix = pix;
+ }
+ }
+ }
+
+ imgWidth = image->size.width();
+ imgTags->append(image);
+
+ } else {
+ // if we already have a list of img tags for this text
+ // we only want to update the positions of these tags.
+ QDeclarativeStyledTextImgTag *image = imgTags->value(nbImages);
+ image->position = textOut.length() + 1;
+ imgWidth = image->size.width();
+ QPair<QStringRef,QStringRef> attr;
+ do {
+ attr = parseAttribute(ch, textIn);
+ } while (!ch->isNull() && !attr.first.isEmpty());
+ nbImages++;
+ }
+
+ QFontMetricsF fm(layout.font());
+ QString padding(qFloor(imgWidth / fm.width(QChar::Nbsp)), QChar::Nbsp);
+ textOut += QChar(' ');
+ textOut += padding;
+ textOut += QChar(' ');
+}
+
QPair<QStringRef,QStringRef> QDeclarativeStyledTextPrivate::parseAttribute(const QChar *&ch, const QString &textIn)
{
skipSpace(ch);
diff --git a/src/quick/util/qdeclarativestyledtext_p.h b/src/quick/util/qdeclarativestyledtext_p.h
index f3e9fef457..1c9086e7d1 100644
--- a/src/quick/util/qdeclarativestyledtext_p.h
+++ b/src/quick/util/qdeclarativestyledtext_p.h
@@ -42,23 +42,55 @@
#ifndef QDECLARATIVESTYLEDTEXT_H
#define QDECLARATIVESTYLEDTEXT_H
-#include <QSizeF>
+#include <QSize>
+#include <QPointF>
+#include <QList>
+#include <QUrl>
+#include <QtQuick/private/qdeclarativepixmapcache_p.h>
QT_BEGIN_NAMESPACE
-class QPainter;
-class QPointF;
-class QString;
+class QDeclarativeStyledTextImgTag;
class QDeclarativeStyledTextPrivate;
-class QTextLayout;
+class QString;
+class QDeclarativeContext;
+
+class Q_AUTOTEST_EXPORT QDeclarativeStyledTextImgTag
+{
+public:
+ QDeclarativeStyledTextImgTag()
+ : position(0), align(QDeclarativeStyledTextImgTag::Bottom), pix(0)
+ { }
+
+ ~QDeclarativeStyledTextImgTag() { delete pix; }
+
+ enum Align {
+ Bottom,
+ Middle,
+ Top
+ };
+
+ QUrl url;
+ QPointF pos;
+ QSize size;
+ int position;
+ Align align;
+ QDeclarativePixmap *pix;
+};
class Q_AUTOTEST_EXPORT QDeclarativeStyledText
{
public:
- static void parse(const QString &string, QTextLayout &layout);
+ static void parse(const QString &string, QTextLayout &layout,
+ QList<QDeclarativeStyledTextImgTag*> &imgTags,
+ QDeclarativeContext *context,
+ bool preloadImages);
private:
- QDeclarativeStyledText(const QString &string, QTextLayout &layout);
+ QDeclarativeStyledText(const QString &string, QTextLayout &layout,
+ QList<QDeclarativeStyledTextImgTag*> &imgTags,
+ QDeclarativeContext *context,
+ bool preloadImages);
~QDeclarativeStyledText();
QDeclarativeStyledTextPrivate *d;
diff --git a/tests/auto/qtquick2/qdeclarativestyledtext/tst_qdeclarativestyledtext.cpp b/tests/auto/qtquick2/qdeclarativestyledtext/tst_qdeclarativestyledtext.cpp
index 46acbb2db3..b4e0ba1b7a 100644
--- a/tests/auto/qtquick2/qdeclarativestyledtext/tst_qdeclarativestyledtext.cpp
+++ b/tests/auto/qtquick2/qdeclarativestyledtext/tst_qdeclarativestyledtext.cpp
@@ -41,7 +41,8 @@
#include <qtest.h>
#include <QtTest/QtTest>
#include <QtGui/QTextLayout>
-#include <private/qdeclarativestyledtext_p.h>
+#include <QtCore/QList>
+#include <QtQuick/private/qdeclarativestyledtext_p.h>
class tst_qdeclarativestyledtext : public QObject
{
@@ -148,6 +149,7 @@ void tst_qdeclarativestyledtext::textOutput_data()
QTest::newRow("space before bold") << "this is <b>bold</b>" << "this is bold" << (FormatList() << Format(Format::Bold, 8, 4));
QTest::newRow("space leading bold") << "this is<b> bold</b>" << "this is bold" << (FormatList() << Format(Format::Bold, 7, 5));
QTest::newRow("space trailing bold") << "this is <b>bold </b>" << "this is bold " << (FormatList() << Format(Format::Bold, 8, 5));
+ QTest::newRow("img") << "a<img src=\"blah.png\"/>b" << "a b" << FormatList();
}
void tst_qdeclarativestyledtext::textOutput()
@@ -157,7 +159,8 @@ void tst_qdeclarativestyledtext::textOutput()
QFETCH(FormatList, formats);
QTextLayout layout;
- QDeclarativeStyledText::parse(input, layout);
+ QList<QDeclarativeStyledTextImgTag*> imgTags;
+ QDeclarativeStyledText::parse(input, layout, imgTags, 0, false);
QCOMPARE(layout.text(), output);
diff --git a/tests/auto/qtquick2/qquicktext/data/images/face-sad.png b/tests/auto/qtquick2/qquicktext/data/images/face-sad.png
new file mode 100644
index 0000000000..24188b7985
--- /dev/null
+++ b/tests/auto/qtquick2/qquicktext/data/images/face-sad.png
Binary files differ
diff --git a/tests/auto/qtquick2/qquicktext/data/images/heart200.png b/tests/auto/qtquick2/qquicktext/data/images/heart200.png
new file mode 100644
index 0000000000..cedd3ea608
--- /dev/null
+++ b/tests/auto/qtquick2/qquicktext/data/images/heart200.png
Binary files differ
diff --git a/tests/auto/qtquick2/qquicktext/data/images/starfish_2.png b/tests/auto/qtquick2/qquicktext/data/images/starfish_2.png
new file mode 100644
index 0000000000..132c20ffd0
--- /dev/null
+++ b/tests/auto/qtquick2/qquicktext/data/images/starfish_2.png
Binary files differ
diff --git a/tests/auto/qtquick2/qquicktext/data/imgTagsElide.qml b/tests/auto/qtquick2/qquicktext/data/imgTagsElide.qml
new file mode 100644
index 0000000000..fbd64cc5bf
--- /dev/null
+++ b/tests/auto/qtquick2/qquicktext/data/imgTagsElide.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.0
+
+Item {
+ width: 300
+ height: 200
+
+ Text {
+ id: myText
+ objectName: "myText"
+ elide: Text.ElideRight
+ maximumLineCount: 2
+ width: 200
+ wrapMode: Text.WordWrap
+ text: "This is a sad face aligned to the top. Lorem ipsum dolor sit amet. Nulla sed turpis risus. Integer sit amet odio quis mauris varius venenatis<img src=\"images/face-sad.png\" width=\"30\" height=\"30\" align=\"top\">Lorem ipsum dolor sit amet. Nulla sed turpis risus. Integer sit amet odio quis mauris varius venenatis. Lorem ipsum dolor sit amet. Nulla sed turpis risus.Lorem ipsum dolor sit amet. Nulla sed turpis risus. Lorem ipsum dolor sit amet. Nulla sed turpis risus.Lorem ipsum dolor sit amet. Nulla sed turpis risus."
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: myText.width = 400
+
+ }
+}
+
+
diff --git a/tests/auto/qtquick2/qquicktext/data/imgTagsUpdates.qml b/tests/auto/qtquick2/qquicktext/data/imgTagsUpdates.qml
new file mode 100644
index 0000000000..baf5113e52
--- /dev/null
+++ b/tests/auto/qtquick2/qquicktext/data/imgTagsUpdates.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.0
+
+Rectangle {
+ id: main
+ width: 300; height: 400
+
+ Text {
+ id: myText
+ objectName: "myText"
+ text: ""
+ }
+}
diff --git a/tests/auto/qtquick2/qquicktext/tst_qquicktext.cpp b/tests/auto/qtquick2/qquicktext/tst_qquicktext.cpp
index 706276c52f..cac65196eb 100644
--- a/tests/auto/qtquick2/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/qtquick2/qquicktext/tst_qquicktext.cpp
@@ -107,6 +107,12 @@ private slots:
void lineLaidOut();
+ void imgTagsAlign_data();
+ void imgTagsAlign();
+ void imgTagsMultipleImages();
+ void imgTagsElide();
+ void imgTagsUpdates();
+ void imgTagsError();
private:
QStringList standard;
@@ -1478,6 +1484,120 @@ void tst_qquicktext::lineLaidOut()
delete canvas;
}
+void tst_qquicktext::imgTagsAlign_data()
+{
+ QTest::addColumn<QString>("src");
+ QTest::addColumn<int>("imgHeight");
+ QTest::addColumn<QString>("align");
+ QTest::newRow("heart-bottom") << "data/images/heart200.png" << 181 << "bottom";
+ QTest::newRow("heart-middle") << "data/images/heart200.png" << 181 << "middle";
+ QTest::newRow("heart-top") << "data/images/heart200.png" << 181 << "top";
+ QTest::newRow("starfish-bottom") << "data/images/starfish_2.png" << 217 << "bottom";
+ QTest::newRow("starfish-middle") << "data/images/starfish_2.png" << 217 << "middle";
+ QTest::newRow("starfish-top") << "data/images/starfish_2.png" << 217 << "top";
+}
+
+void tst_qquicktext::imgTagsAlign()
+{
+ QFETCH(QString, src);
+ QFETCH(int, imgHeight);
+ QFETCH(QString, align);
+ QString componentStr = "import QtQuick 2.0\nText { text: \"This is a test <img src=\\\"" + src + "\\\" align=\\\"" + align + "\\\"> of image.\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->height() == imgHeight);
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
+ QVERIFY(textPrivate != 0);
+
+ QRectF br = textPrivate->layout.boundingRect();
+ if (align == "bottom")
+ QVERIFY(br.y() == imgHeight - br.height());
+ else if (align == "middle")
+ QVERIFY(br.y() == imgHeight / 2.0 - br.height() / 2.0);
+ else if (align == "top")
+ QVERIFY(br.y() == 0);
+
+ delete textObject;
+}
+
+void tst_qquicktext::imgTagsMultipleImages()
+{
+ QString componentStr = "import QtQuick 2.0\nText { text: \"This is a starfish<img src=\\\"data/images/starfish_2.png\\\" width=\\\"60\\\" height=\\\"60\\\" > and another one<img src=\\\"data/images/heart200.png\\\" width=\\\"85\\\" height=\\\"85\\\">.\" }";
+
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->height() == 85);
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
+ QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate->visibleImgTags.count() == 2);
+
+ delete textObject;
+}
+
+void tst_qquicktext::imgTagsElide()
+{
+ QQuickView *canvas = createView(testFile("imgTagsElide.qml"));
+ QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
+ QVERIFY(myText != 0);
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
+ QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate->visibleImgTags.count() == 0);
+ myText->setMaximumLineCount(20);
+ QTRY_VERIFY(textPrivate->visibleImgTags.count() == 1);
+
+ delete myText;
+ delete canvas;
+}
+
+void tst_qquicktext::imgTagsUpdates()
+{
+ QQuickView *canvas = createView(testFile("imgTagsUpdates.qml"));
+ QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
+ QVERIFY(myText != 0);
+
+ QSignalSpy spy(myText, SIGNAL(paintedSizeChanged()));
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
+ QVERIFY(textPrivate != 0);
+
+ myText->setText("This is a heart<img src=\"images/heart200.png\">.");
+ QVERIFY(textPrivate->visibleImgTags.count() == 1);
+ QVERIFY(spy.count() == 1);
+
+ myText->setMaximumLineCount(2);
+ myText->setText("This is another heart<img src=\"images/heart200.png\">.");
+ QTRY_VERIFY(textPrivate->visibleImgTags.count() == 1);
+
+ // if maximumLineCount is set and the img tag doesn't have an explicit size
+ // we relayout twice.
+ QVERIFY(spy.count() == 3);
+
+ delete myText;
+ delete canvas;
+}
+
+void tst_qquicktext::imgTagsError()
+{
+ QString componentStr = "import QtQuick 2.0\nText { text: \"This is a starfish<img src=\\\"data/images/starfish_2.pn\\\" width=\\\"60\\\" height=\\\"60\\\">.\" }";
+
+ QDeclarativeComponent textComponent(&engine);
+ QTest::ignoreMessage(QtWarningMsg, "file::2:1: QML Text: Cannot open: file:data/images/starfish_2.pn");
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ delete textObject;
+}
+
QTEST_MAIN(tst_qquicktext)
#include "tst_qquicktext.moc"