3607 lines
139 KiB
C++
3607 lines
139 KiB
C++
/****************************************************************************
|
|
**
|
|
** 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.
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
#include <qtest.h>
|
|
#include <QtTest/QSignalSpy>
|
|
#include <QTextDocument>
|
|
#include <QtQml/qqmlengine.h>
|
|
#include <QtQml/qqmlcomponent.h>
|
|
#include <QtQuick/private/qquicktext_p.h>
|
|
#include <private/qquicktext_p_p.h>
|
|
#include <private/qquickvaluetypes_p.h>
|
|
#include <QFontMetrics>
|
|
#include <qmath.h>
|
|
#include <QtQuick/QQuickView>
|
|
#include <private/qguiapplication_p.h>
|
|
#include <limits.h>
|
|
#include <QtGui/QMouseEvent>
|
|
#include "../../shared/util.h"
|
|
#include "testhttpserver.h"
|
|
|
|
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
|
|
|
|
#define SERVER_PORT 14459
|
|
#define SERVER_ADDR "http://127.0.0.1:14459"
|
|
|
|
Q_DECLARE_METATYPE(QQuickText::TextFormat)
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
extern void qt_setQtEnableTestFont(bool value);
|
|
QT_END_NAMESPACE
|
|
|
|
class tst_qquicktext : public QQmlDataTest
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
tst_qquicktext();
|
|
|
|
private slots:
|
|
void text();
|
|
void width();
|
|
void wrap();
|
|
void elide();
|
|
void multilineElide_data();
|
|
void multilineElide();
|
|
void implicitElide_data();
|
|
void implicitElide();
|
|
void textFormat();
|
|
|
|
void alignments_data();
|
|
void alignments();
|
|
|
|
void baseUrl();
|
|
void embeddedImages_data();
|
|
void embeddedImages();
|
|
|
|
void lineCount();
|
|
void lineHeight();
|
|
|
|
// ### these tests may be trivial
|
|
void horizontalAlignment();
|
|
void horizontalAlignment_RightToLeft();
|
|
void verticalAlignment();
|
|
void hAlignImplicitWidth();
|
|
void font();
|
|
void style();
|
|
void color();
|
|
void smooth();
|
|
|
|
// QQuickFontValueType
|
|
void weight();
|
|
void underline();
|
|
void overline();
|
|
void strikeout();
|
|
void capitalization();
|
|
void letterSpacing();
|
|
void wordSpacing();
|
|
|
|
void clickLink_data();
|
|
void clickLink();
|
|
|
|
void implicitSize_data();
|
|
void implicitSize();
|
|
void contentSize();
|
|
void implicitSizeBinding_data();
|
|
void implicitSizeBinding();
|
|
void geometryChanged();
|
|
|
|
void boundingRect_data();
|
|
void boundingRect();
|
|
void clipRect();
|
|
void lineLaidOut();
|
|
void lineLaidOutRelayout();
|
|
|
|
void imgTagsBaseUrl_data();
|
|
void imgTagsBaseUrl();
|
|
void imgTagsAlign_data();
|
|
void imgTagsAlign();
|
|
void imgTagsMultipleImages();
|
|
void imgTagsElide();
|
|
void imgTagsUpdates();
|
|
void imgTagsError();
|
|
void fontSizeMode_data();
|
|
void fontSizeMode();
|
|
void fontSizeModeMultiline_data();
|
|
void fontSizeModeMultiline();
|
|
void multilengthStrings_data();
|
|
void multilengthStrings();
|
|
void fontFormatSizes_data();
|
|
void fontFormatSizes();
|
|
|
|
void baselineOffset_data();
|
|
void baselineOffset();
|
|
|
|
void htmlLists();
|
|
void htmlLists_data();
|
|
|
|
private:
|
|
QStringList standard;
|
|
QStringList richText;
|
|
|
|
QStringList horizontalAlignmentmentStrings;
|
|
QStringList verticalAlignmentmentStrings;
|
|
|
|
QList<Qt::Alignment> verticalAlignmentments;
|
|
QList<Qt::Alignment> horizontalAlignmentments;
|
|
|
|
QStringList styleStrings;
|
|
QList<QQuickText::TextStyle> styles;
|
|
|
|
QStringList colorStrings;
|
|
|
|
QQmlEngine engine;
|
|
|
|
QQuickView *createView(const QString &filename);
|
|
int numberOfNonWhitePixels(int fromX, int toX, const QImage &image);
|
|
};
|
|
|
|
tst_qquicktext::tst_qquicktext()
|
|
{
|
|
standard << "the quick brown fox jumped over the lazy dog"
|
|
<< "the quick brown fox\n jumped over the lazy dog";
|
|
|
|
richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
|
|
<< "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
|
|
|
|
horizontalAlignmentmentStrings << "AlignLeft"
|
|
<< "AlignRight"
|
|
<< "AlignHCenter";
|
|
|
|
verticalAlignmentmentStrings << "AlignTop"
|
|
<< "AlignBottom"
|
|
<< "AlignVCenter";
|
|
|
|
horizontalAlignmentments << Qt::AlignLeft
|
|
<< Qt::AlignRight
|
|
<< Qt::AlignHCenter;
|
|
|
|
verticalAlignmentments << Qt::AlignTop
|
|
<< Qt::AlignBottom
|
|
<< Qt::AlignVCenter;
|
|
|
|
styleStrings << "Normal"
|
|
<< "Outline"
|
|
<< "Raised"
|
|
<< "Sunken";
|
|
|
|
styles << QQuickText::Normal
|
|
<< QQuickText::Outline
|
|
<< QQuickText::Raised
|
|
<< QQuickText::Sunken;
|
|
|
|
colorStrings << "aliceblue"
|
|
<< "antiquewhite"
|
|
<< "aqua"
|
|
<< "darkkhaki"
|
|
<< "darkolivegreen"
|
|
<< "dimgray"
|
|
<< "palevioletred"
|
|
<< "lightsteelblue"
|
|
<< "#000000"
|
|
<< "#AAAAAA"
|
|
<< "#FFFFFF"
|
|
<< "#2AC05F";
|
|
//
|
|
// need a different test to do alpha channel test
|
|
// << "#AA0011DD"
|
|
// << "#00F16B11";
|
|
//
|
|
qt_setQtEnableTestFont(true);
|
|
}
|
|
|
|
QQuickView *tst_qquicktext::createView(const QString &filename)
|
|
{
|
|
QQuickView *window = new QQuickView(0);
|
|
|
|
window->setSource(QUrl::fromLocalFile(filename));
|
|
return window;
|
|
}
|
|
|
|
void tst_qquicktext::text()
|
|
{
|
|
{
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->text(), QString(""));
|
|
QVERIFY(textObject->width() == 0);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
for (int i = 0; i < standard.size(); i++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->text(), standard.at(i));
|
|
QVERIFY(textObject->width() > 0);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
for (int i = 0; i < richText.size(); i++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QString expected = richText.at(i);
|
|
QCOMPARE(textObject->text(), expected.replace("\\\"", "\""));
|
|
QVERIFY(textObject->width() > 0);
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::width()
|
|
{
|
|
// uses Font metrics to find the width for standard and document to find the width for rich
|
|
{
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->width(), 0.);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
bool requiresUnhintedMetrics = !qmlDisableDistanceField();
|
|
|
|
for (int i = 0; i < standard.size(); i++)
|
|
{
|
|
QVERIFY(!Qt::mightBeRichText(standard.at(i))); // self-test
|
|
|
|
QFont f;
|
|
qreal metricWidth = 0.0;
|
|
|
|
if (requiresUnhintedMetrics) {
|
|
QString s = standard.at(i);
|
|
s.replace(QLatin1Char('\n'), QChar::LineSeparator);
|
|
|
|
QTextLayout layout(s);
|
|
layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic);
|
|
{
|
|
QTextOption option;
|
|
option.setUseDesignMetrics(true);
|
|
layout.setTextOption(option);
|
|
}
|
|
|
|
layout.beginLayout();
|
|
forever {
|
|
QTextLine line = layout.createLine();
|
|
if (!line.isValid())
|
|
break;
|
|
}
|
|
|
|
layout.endLayout();
|
|
|
|
metricWidth = layout.boundingRect().width();
|
|
} else {
|
|
QFontMetricsF fm(f);
|
|
metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
|
|
}
|
|
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QVERIFY(textObject->boundingRect().width() > 0);
|
|
QCOMPARE(textObject->width(), qreal(metricWidth));
|
|
QVERIFY(textObject->textFormat() == QQuickText::AutoText); // setting text doesn't change format
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
for (int i = 0; i < richText.size(); i++)
|
|
{
|
|
QVERIFY(Qt::mightBeRichText(richText.at(i))); // self-test
|
|
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\"; textFormat: Text.RichText }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
QVERIFY(textObject != 0);
|
|
|
|
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
|
|
QVERIFY(textPrivate != 0);
|
|
QVERIFY(textPrivate->extra.isAllocated());
|
|
|
|
QTextDocument *doc = textPrivate->extra->doc;
|
|
QVERIFY(doc != 0);
|
|
|
|
QCOMPARE(int(textObject->width()), int(doc->idealWidth()));
|
|
QVERIFY(textObject->textFormat() == QQuickText::RichText);
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::wrap()
|
|
{
|
|
int textHeight = 0;
|
|
// for specified width and wrap set true
|
|
{
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; wrapMode: Text.WordWrap; width: 300 }", QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
textHeight = textObject->height();
|
|
|
|
QVERIFY(textObject != 0);
|
|
QVERIFY(textObject->wrapMode() == QQuickText::WordWrap);
|
|
QCOMPARE(textObject->width(), 300.);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
for (int i = 0; i < standard.size(); i++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + standard.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->width(), 30.);
|
|
QVERIFY(textObject->height() > textHeight);
|
|
|
|
int oldHeight = textObject->height();
|
|
textObject->setWidth(100);
|
|
QVERIFY(textObject->height() < oldHeight);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
for (int i = 0; i < richText.size(); i++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + richText.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->width(), 30.);
|
|
QVERIFY(textObject->height() > textHeight);
|
|
|
|
qreal oldHeight = textObject->height();
|
|
textObject->setWidth(100);
|
|
QVERIFY(textObject->height() < oldHeight);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
// richtext again with a fixed height
|
|
for (int i = 0; i < richText.size(); i++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; height: 50; text: \"" + richText.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->width(), 30.);
|
|
QVERIFY(textObject->implicitHeight() > textHeight);
|
|
|
|
qreal oldHeight = textObject->implicitHeight();
|
|
textObject->setWidth(100);
|
|
QVERIFY(textObject->implicitHeight() < oldHeight);
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::elide()
|
|
{
|
|
for (QQuickText::TextElideMode m = QQuickText::ElideLeft; m<=QQuickText::ElideNone; m=QQuickText::TextElideMode(int(m)+1)) {
|
|
const char* elidename[]={"ElideLeft", "ElideRight", "ElideMiddle", "ElideNone"};
|
|
QString elide = "elide: Text." + QString(elidename[int(m)]) + ";";
|
|
|
|
// XXX Poor coverage.
|
|
|
|
{
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(("import QtQuick 2.0\nText { text: \"\"; "+elide+" width: 100 }").toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->elideMode(), m);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
for (int i = 0; i < standard.size(); i++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + standard.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->elideMode(), m);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
|
|
if (m != QQuickText::ElideNone && !standard.at(i).contains('\n'))
|
|
QVERIFY(textObject->contentWidth() <= textObject->width());
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
for (int i = 0; i < richText.size(); i++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + richText.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->elideMode(), m);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
|
|
if (m != QQuickText::ElideNone && standard.at(i).contains("<br>"))
|
|
QVERIFY(textObject->contentWidth() <= textObject->width());
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::multilineElide_data()
|
|
{
|
|
QTest::addColumn<QQuickText::TextFormat>("format");
|
|
QTest::newRow("plain") << QQuickText::PlainText;
|
|
QTest::newRow("styled") << QQuickText::StyledText;
|
|
}
|
|
|
|
void tst_qquicktext::multilineElide()
|
|
{
|
|
QFETCH(QQuickText::TextFormat, format);
|
|
QQuickView *window = createView(testFile("multilineelide.qml"));
|
|
|
|
QQuickText *myText = qobject_cast<QQuickText*>(window->rootObject());
|
|
QVERIFY(myText != 0);
|
|
myText->setTextFormat(format);
|
|
|
|
QCOMPARE(myText->lineCount(), 3);
|
|
QCOMPARE(myText->truncated(), true);
|
|
|
|
qreal lineHeight = myText->contentHeight() / 3.;
|
|
|
|
// Set a valid height greater than the truncated content height and ensure the line count is
|
|
// unchanged.
|
|
myText->setHeight(200);
|
|
QCOMPARE(myText->lineCount(), 3);
|
|
QCOMPARE(myText->truncated(), true);
|
|
|
|
// reduce size and ensure fewer lines are drawn
|
|
myText->setHeight(lineHeight * 2);
|
|
QCOMPARE(myText->lineCount(), 2);
|
|
|
|
myText->setHeight(lineHeight);
|
|
QCOMPARE(myText->lineCount(), 1);
|
|
|
|
myText->setHeight(5);
|
|
QCOMPARE(myText->lineCount(), 1);
|
|
|
|
myText->setHeight(lineHeight * 3);
|
|
QCOMPARE(myText->lineCount(), 3);
|
|
|
|
// remove max count and show all lines.
|
|
myText->setHeight(1000);
|
|
myText->resetMaximumLineCount();
|
|
|
|
QCOMPARE(myText->truncated(), false);
|
|
|
|
// reduce size again
|
|
myText->setHeight(lineHeight * 2);
|
|
QCOMPARE(myText->lineCount(), 2);
|
|
QCOMPARE(myText->truncated(), true);
|
|
|
|
// change line height
|
|
myText->setLineHeight(1.1);
|
|
QCOMPARE(myText->lineCount(), 1);
|
|
|
|
delete window;
|
|
}
|
|
|
|
void tst_qquicktext::implicitElide_data()
|
|
{
|
|
QTest::addColumn<QString>("width");
|
|
QTest::addColumn<QString>("initialText");
|
|
QTest::addColumn<QString>("text");
|
|
|
|
QTest::newRow("maximum width, empty")
|
|
<< "Math.min(implicitWidth, 100)"
|
|
<< "";
|
|
QTest::newRow("maximum width, short")
|
|
<< "Math.min(implicitWidth, 100)"
|
|
<< "the";
|
|
QTest::newRow("maximum width, long")
|
|
<< "Math.min(implicitWidth, 100)"
|
|
<< "the quick brown fox jumped over the lazy dog";
|
|
QTest::newRow("reset width, empty")
|
|
<< "implicitWidth > 100 ? 100 : undefined"
|
|
<< "";
|
|
QTest::newRow("reset width, short")
|
|
<< "implicitWidth > 100 ? 100 : undefined"
|
|
<< "the";
|
|
QTest::newRow("reset width, long")
|
|
<< "implicitWidth > 100 ? 100 : undefined"
|
|
<< "the quick brown fox jumped over the lazy dog";
|
|
}
|
|
|
|
void tst_qquicktext::implicitElide()
|
|
{
|
|
QFETCH(QString, width);
|
|
QFETCH(QString, initialText);
|
|
|
|
QString componentStr =
|
|
"import QtQuick 2.0\n"
|
|
"Text {\n"
|
|
"width: " + width + "\n"
|
|
"text: \"" + initialText + "\"\n"
|
|
"elide: Text.ElideRight\n"
|
|
"}";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject->contentWidth() <= textObject->width());
|
|
|
|
textObject->setText("the quick brown fox jumped over");
|
|
|
|
QVERIFY(textObject->contentWidth() > 0);
|
|
QVERIFY(textObject->contentWidth() <= textObject->width());
|
|
}
|
|
|
|
void tst_qquicktext::textFormat()
|
|
{
|
|
{
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QVERIFY(textObject->textFormat() == QQuickText::RichText);
|
|
|
|
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
|
|
QVERIFY(textPrivate != 0);
|
|
QVERIFY(textPrivate->richText == true);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\" }", QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QVERIFY(textObject->textFormat() == QQuickText::AutoText);
|
|
|
|
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
|
|
QVERIFY(textPrivate != 0);
|
|
QVERIFY(textPrivate->styledText == true);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QVERIFY(textObject->textFormat() == QQuickText::PlainText);
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
|
|
void tst_qquicktext::alignments_data()
|
|
{
|
|
QTest::addColumn<int>("hAlign");
|
|
QTest::addColumn<int>("vAlign");
|
|
QTest::addColumn<QString>("expectfile");
|
|
|
|
QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << testFile("alignments_lt.png");
|
|
QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << testFile("alignments_rt.png");
|
|
QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << testFile("alignments_ct.png");
|
|
|
|
QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << testFile("alignments_lb.png");
|
|
QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << testFile("alignments_rb.png");
|
|
QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << testFile("alignments_cb.png");
|
|
|
|
QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << testFile("alignments_lc.png");
|
|
QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << testFile("alignments_rc.png");
|
|
QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << testFile("alignments_cc.png");
|
|
}
|
|
|
|
|
|
void tst_qquicktext::alignments()
|
|
{
|
|
QSKIP("Text alignment pixmap comparison tests will not work with scenegraph");
|
|
#if (0)// No widgets in scenegraph
|
|
QFETCH(int, hAlign);
|
|
QFETCH(int, vAlign);
|
|
QFETCH(QString, expectfile);
|
|
|
|
QQuickView *window = createView(testFile("alignments.qml"));
|
|
window->show();
|
|
window->requestActivateWindow();
|
|
QTest::qWait(50);
|
|
QTRY_COMPARE(QGuiApplication::activeWindow(), static_cast<QWidget *>(window));
|
|
|
|
QObject *ob = window->rootObject();
|
|
QVERIFY(ob != 0);
|
|
ob->setProperty("horizontalAlignment",hAlign);
|
|
ob->setProperty("verticalAlignment",vAlign);
|
|
QTRY_COMPARE(ob->property("running").toBool(),false);
|
|
QImage actual(window->width(), window->height(), QImage::Format_RGB32);
|
|
actual.fill(qRgb(255,255,255));
|
|
QPainter p(&actual);
|
|
window->render(&p);
|
|
|
|
QImage expect(expectfile);
|
|
if (QGuiApplicationPrivate::graphics_system_name == "raster" || QGuiApplicationPrivate::graphics_system_name == "") {
|
|
QCOMPARE(actual,expect);
|
|
}
|
|
delete window;
|
|
#endif
|
|
}
|
|
|
|
//the alignment tests may be trivial o.oa
|
|
void tst_qquicktext::horizontalAlignment()
|
|
{
|
|
//test one align each, and then test if two align fails.
|
|
|
|
for (int i = 0; i < standard.size(); i++)
|
|
{
|
|
for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < richText.size(); i++)
|
|
{
|
|
for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void tst_qquicktext::horizontalAlignment_RightToLeft()
|
|
{
|
|
QQuickView *window = createView(testFile("horizontalAlignment_RightToLeft.qml"));
|
|
QQuickText *text = window->rootObject()->findChild<QQuickText*>("text");
|
|
QVERIFY(text != 0);
|
|
window->show();
|
|
|
|
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(text);
|
|
QVERIFY(textPrivate != 0);
|
|
|
|
QTRY_VERIFY(textPrivate->layout.lineCount());
|
|
|
|
// implicit alignment should follow the reading direction of RTL text
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignRight);
|
|
QCOMPARE(text->effectiveHAlign(), text->hAlign());
|
|
QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > window->width()/2);
|
|
|
|
// explicitly left aligned text
|
|
text->setHAlign(QQuickText::AlignLeft);
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
|
|
QCOMPARE(text->effectiveHAlign(), text->hAlign());
|
|
QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < window->width()/2);
|
|
|
|
// explicitly right aligned text
|
|
text->setHAlign(QQuickText::AlignRight);
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignRight);
|
|
QCOMPARE(text->effectiveHAlign(), text->hAlign());
|
|
QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > window->width()/2);
|
|
|
|
// change to rich text
|
|
QString textString = text->text();
|
|
text->setText(QString("<i>") + textString + QString("</i>"));
|
|
text->setTextFormat(QQuickText::RichText);
|
|
text->resetHAlign();
|
|
|
|
// implicitly aligned rich text should follow the reading direction of text
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignRight);
|
|
QCOMPARE(text->effectiveHAlign(), text->hAlign());
|
|
QVERIFY(textPrivate->extra.isAllocated());
|
|
QVERIFY(textPrivate->extra->doc->defaultTextOption().alignment() & Qt::AlignLeft);
|
|
|
|
// explicitly left aligned rich text
|
|
text->setHAlign(QQuickText::AlignLeft);
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
|
|
QCOMPARE(text->effectiveHAlign(), text->hAlign());
|
|
QVERIFY(textPrivate->extra->doc->defaultTextOption().alignment() & Qt::AlignRight);
|
|
|
|
// explicitly right aligned rich text
|
|
text->setHAlign(QQuickText::AlignRight);
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignRight);
|
|
QCOMPARE(text->effectiveHAlign(), text->hAlign());
|
|
QVERIFY(textPrivate->extra->doc->defaultTextOption().alignment() & Qt::AlignLeft);
|
|
|
|
text->setText(textString);
|
|
text->setTextFormat(QQuickText::PlainText);
|
|
|
|
// explicitly center aligned
|
|
text->setHAlign(QQuickText::AlignHCenter);
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignHCenter);
|
|
QCOMPARE(text->effectiveHAlign(), text->hAlign());
|
|
QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < window->width()/2);
|
|
QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().right() > window->width()/2);
|
|
|
|
// reseted alignment should go back to following the text reading direction
|
|
text->resetHAlign();
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignRight);
|
|
QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > window->width()/2);
|
|
|
|
// mirror the text item
|
|
QQuickItemPrivate::get(text)->setLayoutMirror(true);
|
|
|
|
// mirrored implicit alignment should continue to follow the reading direction of the text
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignRight);
|
|
QCOMPARE(text->effectiveHAlign(), QQuickText::AlignRight);
|
|
QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > window->width()/2);
|
|
|
|
// mirrored explicitly right aligned behaves as left aligned
|
|
text->setHAlign(QQuickText::AlignRight);
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignRight);
|
|
QCOMPARE(text->effectiveHAlign(), QQuickText::AlignLeft);
|
|
QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < window->width()/2);
|
|
|
|
// mirrored explicitly left aligned behaves as right aligned
|
|
text->setHAlign(QQuickText::AlignLeft);
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
|
|
QCOMPARE(text->effectiveHAlign(), QQuickText::AlignRight);
|
|
QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > window->width()/2);
|
|
|
|
// disable mirroring
|
|
QQuickItemPrivate::get(text)->setLayoutMirror(false);
|
|
text->resetHAlign();
|
|
|
|
// English text should be implicitly left aligned
|
|
text->setText("Hello world!");
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
|
|
QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < window->width()/2);
|
|
|
|
// empty text with implicit alignment follows the system locale-based
|
|
// keyboard input direction from QInputMethod::inputDirection()
|
|
text->setText("");
|
|
QCOMPARE(text->hAlign(), qApp->inputMethod()->inputDirection() == Qt::LeftToRight ?
|
|
QQuickText::AlignLeft : QQuickText::AlignRight);
|
|
text->setHAlign(QQuickText::AlignRight);
|
|
QCOMPARE(text->hAlign(), QQuickText::AlignRight);
|
|
|
|
delete window;
|
|
|
|
// alignment of Text with no text set to it
|
|
QString componentStr = "import QtQuick 2.0\nText {}";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
QCOMPARE(textObject->hAlign(), qApp->inputMethod()->inputDirection() == Qt::LeftToRight ?
|
|
QQuickText::AlignLeft : QQuickText::AlignRight);
|
|
delete textObject;
|
|
}
|
|
|
|
int tst_qquicktext::numberOfNonWhitePixels(int fromX, int toX, const QImage &image)
|
|
{
|
|
int pixels = 0;
|
|
for (int x = fromX; x < toX; ++x) {
|
|
for (int y = 0; y < image.height(); ++y) {
|
|
if (image.pixel(x, y) != qRgb(255, 255, 255))
|
|
pixels++;
|
|
}
|
|
}
|
|
return pixels;
|
|
}
|
|
|
|
void tst_qquicktext::hAlignImplicitWidth()
|
|
{
|
|
QQuickView view(testFileUrl("hAlignImplicitWidth.qml"));
|
|
view.show();
|
|
view.requestActivateWindow();
|
|
QVERIFY(QTest::qWaitForWindowActive(&view));
|
|
|
|
QQuickText *text = view.rootObject()->findChild<QQuickText*>("textItem");
|
|
QVERIFY(text != 0);
|
|
|
|
{
|
|
// Left Align
|
|
QImage image = view.grabWindow();
|
|
int left = numberOfNonWhitePixels(0, image.width() / 3, image);
|
|
int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
|
|
int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
|
|
QVERIFY(left > mid);
|
|
QVERIFY(mid > right);
|
|
}
|
|
{
|
|
// HCenter Align
|
|
text->setHAlign(QQuickText::AlignHCenter);
|
|
QImage image = view.grabWindow();
|
|
int left = numberOfNonWhitePixels(0, image.width() / 3, image);
|
|
int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
|
|
int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
|
|
QVERIFY(left < mid);
|
|
QVERIFY(mid > right);
|
|
}
|
|
{
|
|
// Right Align
|
|
text->setHAlign(QQuickText::AlignRight);
|
|
QImage image = view.grabWindow();
|
|
int left = numberOfNonWhitePixels(0, image.width() / 3, image);
|
|
int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
|
|
int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
|
|
QVERIFY(left < mid);
|
|
QVERIFY(mid < right);
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::verticalAlignment()
|
|
{
|
|
//test one align each, and then test if two align fails.
|
|
|
|
for (int i = 0; i < standard.size(); i++)
|
|
{
|
|
for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < richText.size(); i++)
|
|
{
|
|
for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void tst_qquicktext::font()
|
|
{
|
|
//test size, then bold, then italic, then family
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { font.pointSize: 40; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->font().pointSize(), 40);
|
|
QCOMPARE(textObject->font().bold(), false);
|
|
QCOMPARE(textObject->font().italic(), false);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { font.pixelSize: 40; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->font().pixelSize(), 40);
|
|
QCOMPARE(textObject->font().bold(), false);
|
|
QCOMPARE(textObject->font().italic(), false);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { font.bold: true; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->font().bold(), true);
|
|
QCOMPARE(textObject->font().italic(), false);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { font.italic: true; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->font().italic(), true);
|
|
QCOMPARE(textObject->font().bold(), false);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { font.family: \"Helvetica\"; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->font().family(), QString("Helvetica"));
|
|
QCOMPARE(textObject->font().bold(), false);
|
|
QCOMPARE(textObject->font().italic(), false);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { font.family: \"\"; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->font().family(), QString(""));
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::style()
|
|
{
|
|
//test style
|
|
for (int i = 0; i < styles.size(); i++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { style: \"" + styleStrings.at(i) + "\"; styleColor: \"white\"; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE((int)textObject->style(), (int)styles.at(i));
|
|
QCOMPARE(textObject->styleColor(), QColor("white"));
|
|
|
|
delete textObject;
|
|
}
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QRectF brPre = textObject->boundingRect();
|
|
textObject->setStyle(QQuickText::Outline);
|
|
QRectF brPost = textObject->boundingRect();
|
|
|
|
QVERIFY(brPre.width() < brPost.width());
|
|
QVERIFY(brPre.height() < brPost.height());
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
void tst_qquicktext::color()
|
|
{
|
|
//test style
|
|
for (int i = 0; i < colorStrings.size(); i++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
|
|
QCOMPARE(textObject->styleColor(), QColor("black"));
|
|
QCOMPARE(textObject->linkColor(), QColor("blue"));
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
for (int i = 0; i < colorStrings.size(); i++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { styleColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(i)));
|
|
// default color to black?
|
|
QCOMPARE(textObject->color(), QColor("black"));
|
|
QCOMPARE(textObject->linkColor(), QColor("blue"));
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
for (int i = 0; i < colorStrings.size(); i++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { linkColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->styleColor(), QColor("black"));
|
|
QCOMPARE(textObject->color(), QColor("black"));
|
|
QCOMPARE(textObject->linkColor(), QColor(colorStrings.at(i)));
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
for (int i = 0; i < colorStrings.size(); i++)
|
|
{
|
|
for (int j = 0; j < colorStrings.size(); j++)
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { "
|
|
"color: \"" + colorStrings.at(i) + "\"; "
|
|
"styleColor: \"" + colorStrings.at(j) + "\"; "
|
|
"linkColor: \"" + colorStrings.at(j) + "\"; "
|
|
"text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
|
|
QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(j)));
|
|
QCOMPARE(textObject->linkColor(), QColor(colorStrings.at(j)));
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
{
|
|
QString colorStr = "#AA001234";
|
|
QColor testColor("#001234");
|
|
testColor.setAlpha(170);
|
|
|
|
QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->color(), testColor);
|
|
|
|
delete textObject;
|
|
} {
|
|
QString colorStr = "#001234";
|
|
QColor testColor(colorStr);
|
|
|
|
QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QScopedPointer<QObject> object(textComponent.create());
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
|
|
|
|
QSignalSpy spy(textObject, SIGNAL(colorChanged()));
|
|
|
|
QCOMPARE(textObject->color(), testColor);
|
|
textObject->setColor(testColor);
|
|
QCOMPARE(textObject->color(), testColor);
|
|
QCOMPARE(spy.count(), 0);
|
|
|
|
testColor = QColor("black");
|
|
textObject->setColor(testColor);
|
|
QCOMPARE(textObject->color(), testColor);
|
|
QCOMPARE(spy.count(), 1);
|
|
} {
|
|
QString colorStr = "#001234";
|
|
QColor testColor(colorStr);
|
|
|
|
QString componentStr = "import QtQuick 2.0\nText { styleColor: \"" + colorStr + "\"; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QScopedPointer<QObject> object(textComponent.create());
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
|
|
|
|
QSignalSpy spy(textObject, SIGNAL(styleColorChanged()));
|
|
|
|
QCOMPARE(textObject->styleColor(), testColor);
|
|
textObject->setStyleColor(testColor);
|
|
QCOMPARE(textObject->styleColor(), testColor);
|
|
QCOMPARE(spy.count(), 0);
|
|
|
|
testColor = QColor("black");
|
|
textObject->setStyleColor(testColor);
|
|
QCOMPARE(textObject->styleColor(), testColor);
|
|
QCOMPARE(spy.count(), 1);
|
|
} {
|
|
QString colorStr = "#001234";
|
|
QColor testColor(colorStr);
|
|
|
|
QString componentStr = "import QtQuick 2.0\nText { linkColor: \"" + colorStr + "\"; text: \"Hello World\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QScopedPointer<QObject> object(textComponent.create());
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
|
|
|
|
QSignalSpy spy(textObject, SIGNAL(linkColorChanged()));
|
|
|
|
QCOMPARE(textObject->linkColor(), testColor);
|
|
textObject->setLinkColor(testColor);
|
|
QCOMPARE(textObject->linkColor(), testColor);
|
|
QCOMPARE(spy.count(), 0);
|
|
|
|
testColor = QColor("black");
|
|
textObject->setLinkColor(testColor);
|
|
QCOMPARE(textObject->linkColor(), testColor);
|
|
QCOMPARE(spy.count(), 1);
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::smooth()
|
|
{
|
|
for (int i = 0; i < standard.size(); i++)
|
|
{
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + standard.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
QCOMPARE(textObject->smooth(), false);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
QCOMPARE(textObject->smooth(), true);
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
for (int i = 0; i < richText.size(); i++)
|
|
{
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + richText.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
QCOMPARE(textObject->smooth(), false);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
QCOMPARE(textObject->smooth(), true);
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::weight()
|
|
{
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE((int)textObject->font().weight(), (int)QQuickFontValueType::Normal);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { font.weight: \"Bold\"; text: \"Hello world!\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE((int)textObject->font().weight(), (int)QQuickFontValueType::Bold);
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::underline()
|
|
{
|
|
QQuickView view(testFileUrl("underline.qml"));
|
|
view.show();
|
|
view.requestActivateWindow();
|
|
QVERIFY(QTest::qWaitForWindowActive(&view));
|
|
QQuickText *textObject = view.rootObject()->findChild<QQuickText*>("myText");
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->font().overline(), false);
|
|
QCOMPARE(textObject->font().underline(), true);
|
|
QCOMPARE(textObject->font().strikeOut(), false);
|
|
}
|
|
|
|
void tst_qquicktext::overline()
|
|
{
|
|
QQuickView view(testFileUrl("overline.qml"));
|
|
view.show();
|
|
view.requestActivateWindow();
|
|
QVERIFY(QTest::qWaitForWindowActive(&view));
|
|
QQuickText *textObject = view.rootObject()->findChild<QQuickText*>("myText");
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->font().overline(), true);
|
|
QCOMPARE(textObject->font().underline(), false);
|
|
QCOMPARE(textObject->font().strikeOut(), false);
|
|
}
|
|
|
|
void tst_qquicktext::strikeout()
|
|
{
|
|
QQuickView view(testFileUrl("strikeout.qml"));
|
|
view.show();
|
|
view.requestActivateWindow();
|
|
QVERIFY(QTest::qWaitForWindowActive(&view));
|
|
QQuickText *textObject = view.rootObject()->findChild<QQuickText*>("myText");
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->font().overline(), false);
|
|
QCOMPARE(textObject->font().underline(), false);
|
|
QCOMPARE(textObject->font().strikeOut(), true);
|
|
}
|
|
|
|
void tst_qquicktext::capitalization()
|
|
{
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::MixedCase);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllUppercase\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::AllUppercase);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllLowercase\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::AllLowercase);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"SmallCaps\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::SmallCaps);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"Capitalize\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::Capitalize);
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::letterSpacing()
|
|
{
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->font().letterSpacing(), 0.0);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: -2 }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->font().letterSpacing(), -2.);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: 3 }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->font().letterSpacing(), 3.);
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::wordSpacing()
|
|
{
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->font().wordSpacing(), 0.0);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: -50 }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->font().wordSpacing(), -50.);
|
|
|
|
delete textObject;
|
|
}
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: 200 }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QCOMPARE(textObject->font().wordSpacing(), 200.);
|
|
|
|
delete textObject;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
class EventSender : public QQuickItem
|
|
{
|
|
public:
|
|
void sendEvent(QMouseEvent *event) {
|
|
if (event->type() == QEvent::MouseButtonPress)
|
|
mousePressEvent(event);
|
|
else if (event->type() == QEvent::MouseButtonRelease)
|
|
mouseReleaseEvent(event);
|
|
else if (event->type() == QEvent::MouseMove)
|
|
mouseMoveEvent(event);
|
|
else
|
|
qWarning() << "Trying to send unsupported event type";
|
|
}
|
|
};
|
|
|
|
class LinkTest : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
LinkTest() {}
|
|
|
|
QString link;
|
|
|
|
public slots:
|
|
void linkClicked(QString l) { link = l; }
|
|
};
|
|
|
|
class TextMetrics
|
|
{
|
|
public:
|
|
TextMetrics(const QString &text, Qt::TextElideMode elideMode = Qt::ElideNone)
|
|
{
|
|
QString adjustedText = text;
|
|
adjustedText.replace(QLatin1Char('\n'), QChar(QChar::LineSeparator));
|
|
if (elideMode == Qt::ElideLeft)
|
|
adjustedText = QChar(0x2026) + adjustedText;
|
|
else if (elideMode == Qt::ElideRight)
|
|
adjustedText = adjustedText + QChar(0x2026);
|
|
|
|
layout.setText(adjustedText);
|
|
QTextOption option;
|
|
option.setUseDesignMetrics(true);
|
|
layout.setTextOption(option);
|
|
|
|
layout.beginLayout();
|
|
qreal height = 0;
|
|
QTextLine line = layout.createLine();
|
|
while (line.isValid()) {
|
|
line.setLineWidth(FLT_MAX);
|
|
line.setPosition(QPointF(0, height));
|
|
height += line.height();
|
|
line = layout.createLine();
|
|
}
|
|
layout.endLayout();
|
|
}
|
|
|
|
qreal width() const { return layout.maximumWidth(); }
|
|
|
|
QRectF characterRectangle(
|
|
int position,
|
|
int hAlign = Qt::AlignLeft,
|
|
int vAlign = Qt::AlignTop,
|
|
const QSizeF &bounds = QSizeF(240, 320)) const
|
|
{
|
|
qreal dy = 0;
|
|
switch (vAlign) {
|
|
case Qt::AlignBottom:
|
|
dy = bounds.height() - layout.boundingRect().height();
|
|
break;
|
|
case Qt::AlignVCenter:
|
|
dy = (bounds.height() - layout.boundingRect().height()) / 2;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
for (int i = 0; i < layout.lineCount(); ++i) {
|
|
QTextLine line = layout.lineAt(i);
|
|
if (position >= line.textStart() + line.textLength())
|
|
continue;
|
|
qreal dx = 0;
|
|
switch (hAlign) {
|
|
case Qt::AlignRight:
|
|
dx = bounds.width() - line.naturalTextWidth();
|
|
break;
|
|
case Qt::AlignHCenter:
|
|
dx = (bounds.width() - line.naturalTextWidth()) / 2;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
QRectF rect;
|
|
rect.setLeft(dx + line.cursorToX(position, QTextLine::Leading));
|
|
rect.setRight(dx + line.cursorToX(position, QTextLine::Trailing));
|
|
rect.setTop(dy + line.y());
|
|
rect.setBottom(dy + line.y() + line.height());
|
|
|
|
return rect;
|
|
}
|
|
return QRectF();
|
|
}
|
|
|
|
QTextLayout layout;
|
|
};
|
|
|
|
|
|
typedef QVector<QPointF> PointVector;
|
|
Q_DECLARE_METATYPE(PointVector);
|
|
|
|
void tst_qquicktext::clickLink_data()
|
|
{
|
|
QTest::addColumn<QString>("text");
|
|
QTest::addColumn<qreal>("width");
|
|
QTest::addColumn<QString>("bindings");
|
|
QTest::addColumn<PointVector>("mousePositions");
|
|
QTest::addColumn<QString>("link");
|
|
|
|
const QString singleLineText = "this text has a <a href=\\\"http://qt-project.org/single\\\">link</a> in it";
|
|
const QString singleLineLink = "http://qt-project.org/single";
|
|
const QString multipleLineText = "this text<br/>has <a href=\\\"http://qt-project.org/multiple\\\">multiple<br/>lines</a> in it";
|
|
const QString multipleLineLink = "http://qt-project.org/multiple";
|
|
const QString nestedText = "this text has a <a href=\\\"http://qt-project.org/outer\\\">nested <a href=\\\"http://qt-project.org/inner\\\">link</a> in it</a>";
|
|
const QString outerLink = "http://qt-project.org/outer";
|
|
const QString innerLink = "http://qt-project.org/inner";
|
|
|
|
{
|
|
const TextMetrics metrics("this text has a link in it");
|
|
|
|
QTest::newRow("click on link")
|
|
<< singleLineText << 240.
|
|
<< ""
|
|
<< (PointVector() << metrics.characterRectangle(18).center())
|
|
<< singleLineLink;
|
|
QTest::newRow("click on text")
|
|
<< singleLineText << 240.
|
|
<< ""
|
|
<< (PointVector() << metrics.characterRectangle(13).center())
|
|
<< QString();
|
|
QTest::newRow("drag within link")
|
|
<< singleLineText << 240.
|
|
<< ""
|
|
<< (PointVector()
|
|
<< metrics.characterRectangle(17).center()
|
|
<< metrics.characterRectangle(19).center())
|
|
<< singleLineLink;
|
|
QTest::newRow("drag away from link")
|
|
<< singleLineText << 240.
|
|
<< ""
|
|
<< (PointVector()
|
|
<< metrics.characterRectangle(18).center()
|
|
<< metrics.characterRectangle(13).center())
|
|
<< QString();
|
|
QTest::newRow("drag on to link")
|
|
<< singleLineText << 240.
|
|
<< ""
|
|
<< (PointVector()
|
|
<< metrics.characterRectangle(13).center()
|
|
<< metrics.characterRectangle(18).center())
|
|
<< QString();
|
|
QTest::newRow("click on bottom right aligned link")
|
|
<< singleLineText << 240.
|
|
<< "horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignBottom"
|
|
<< (PointVector() << metrics.characterRectangle(18, Qt::AlignRight, Qt::AlignBottom).center())
|
|
<< singleLineLink;
|
|
QTest::newRow("click on center aligned link")
|
|
<< singleLineText << 240.
|
|
<< "horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter"
|
|
<< (PointVector() << metrics.characterRectangle(18, Qt::AlignHCenter, Qt::AlignVCenter).center())
|
|
<< singleLineLink;
|
|
QTest::newRow("click on rich text link")
|
|
<< singleLineText << 240.
|
|
<< "textFormat: Text.RichText"
|
|
<< (PointVector() << metrics.characterRectangle(18).center())
|
|
<< singleLineLink;
|
|
QTest::newRow("click on rich text")
|
|
<< singleLineText << 240.
|
|
<< "textFormat: Text.RichText"
|
|
<< (PointVector() << metrics.characterRectangle(13).center())
|
|
<< QString();
|
|
QTest::newRow("click on bottom right aligned rich text link")
|
|
<< singleLineText << 240.
|
|
<< "textFormat: Text.RichText; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignBottom"
|
|
<< (PointVector() << metrics.characterRectangle(18, Qt::AlignRight, Qt::AlignBottom).center())
|
|
<< singleLineLink;
|
|
QTest::newRow("click on center aligned rich text link")
|
|
<< singleLineText << 240.
|
|
<< "textFormat: Text.RichText; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter"
|
|
<< (PointVector() << metrics.characterRectangle(18, Qt::AlignHCenter, Qt::AlignVCenter).center())
|
|
<< singleLineLink;
|
|
} {
|
|
const TextMetrics metrics("this text has a li", Qt::ElideRight);
|
|
QTest::newRow("click on right elided link")
|
|
<< singleLineText << metrics.width() + 2
|
|
<< "elide: Text.ElideRight"
|
|
<< (PointVector() << metrics.characterRectangle(17).center())
|
|
<< singleLineLink;
|
|
} {
|
|
const TextMetrics metrics("ink in it", Qt::ElideLeft);
|
|
QTest::newRow("click on left elided link")
|
|
<< singleLineText << metrics.width() + 2
|
|
<< "elide: Text.ElideLeft"
|
|
<< (PointVector() << metrics.characterRectangle(2).center())
|
|
<< singleLineLink;
|
|
} {
|
|
const TextMetrics metrics("this text\nhas multiple\nlines in it");
|
|
QTest::newRow("click on second line")
|
|
<< multipleLineText << 240.
|
|
<< ""
|
|
<< (PointVector() << metrics.characterRectangle(18).center())
|
|
<< multipleLineLink;
|
|
QTest::newRow("click on third line")
|
|
<< multipleLineText << 240.
|
|
<< ""
|
|
<< (PointVector() << metrics.characterRectangle(25).center())
|
|
<< multipleLineLink;
|
|
QTest::newRow("drag from second line to third")
|
|
<< multipleLineText << 240.
|
|
<< ""
|
|
<< (PointVector()
|
|
<< metrics.characterRectangle(18).center()
|
|
<< metrics.characterRectangle(25).center())
|
|
<< multipleLineLink;
|
|
QTest::newRow("click on rich text second line")
|
|
<< multipleLineText << 240.
|
|
<< "textFormat: Text.RichText"
|
|
<< (PointVector() << metrics.characterRectangle(18).center())
|
|
<< multipleLineLink;
|
|
QTest::newRow("click on rich text third line")
|
|
<< multipleLineText << 240.
|
|
<< "textFormat: Text.RichText"
|
|
<< (PointVector() << metrics.characterRectangle(25).center())
|
|
<< multipleLineLink;
|
|
QTest::newRow("drag rich text from second line to third")
|
|
<< multipleLineText << 240.
|
|
<< "textFormat: Text.RichText"
|
|
<< (PointVector()
|
|
<< metrics.characterRectangle(18).center()
|
|
<< metrics.characterRectangle(25).center())
|
|
<< multipleLineLink;
|
|
} {
|
|
const TextMetrics metrics("this text has a nested link in it");
|
|
QTest::newRow("click on left outer link")
|
|
<< nestedText << 240.
|
|
<< ""
|
|
<< (PointVector() << metrics.characterRectangle(22).center())
|
|
<< outerLink;
|
|
QTest::newRow("click on right outer link")
|
|
<< nestedText << 240.
|
|
<< ""
|
|
<< (PointVector() << metrics.characterRectangle(27).center())
|
|
<< outerLink;
|
|
QTest::newRow("click on inner link left")
|
|
<< nestedText << 240.
|
|
<< ""
|
|
<< (PointVector() << metrics.characterRectangle(23).center())
|
|
<< innerLink;
|
|
QTest::newRow("click on inner link right")
|
|
<< nestedText << 240.
|
|
<< ""
|
|
<< (PointVector() << metrics.characterRectangle(26).center())
|
|
<< innerLink;
|
|
QTest::newRow("drag from inner to outer link")
|
|
<< nestedText << 240.
|
|
<< ""
|
|
<< (PointVector()
|
|
<< metrics.characterRectangle(25).center()
|
|
<< metrics.characterRectangle(30).center())
|
|
<< QString();
|
|
QTest::newRow("drag from outer to inner link")
|
|
<< nestedText << 240.
|
|
<< ""
|
|
<< (PointVector()
|
|
<< metrics.characterRectangle(30).center()
|
|
<< metrics.characterRectangle(25).center())
|
|
<< QString();
|
|
QTest::newRow("click on left outer rich text link")
|
|
<< nestedText << 240.
|
|
<< "textFormat: Text.RichText"
|
|
<< (PointVector() << metrics.characterRectangle(22).center())
|
|
<< outerLink;
|
|
QTest::newRow("click on right outer rich text link")
|
|
<< nestedText << 240.
|
|
<< "textFormat: Text.RichText"
|
|
<< (PointVector() << metrics.characterRectangle(27).center())
|
|
<< outerLink;
|
|
QTest::newRow("click on inner rich text link left")
|
|
<< nestedText << 240.
|
|
<< "textFormat: Text.RichText"
|
|
<< (PointVector() << metrics.characterRectangle(23).center())
|
|
<< innerLink;
|
|
QTest::newRow("click on inner rich text link right")
|
|
<< nestedText << 240.
|
|
<< "textFormat: Text.RichText"
|
|
<< (PointVector() << metrics.characterRectangle(26).center())
|
|
<< innerLink;
|
|
QTest::newRow("drag from inner to outer rich text link")
|
|
<< nestedText << 240.
|
|
<< "textFormat: Text.RichText"
|
|
<< (PointVector()
|
|
<< metrics.characterRectangle(25).center()
|
|
<< metrics.characterRectangle(30).center())
|
|
<< QString();
|
|
QTest::newRow("drag from outer to inner rich text link")
|
|
<< nestedText << 240.
|
|
<< "textFormat: Text.RichText"
|
|
<< (PointVector()
|
|
<< metrics.characterRectangle(30).center()
|
|
<< metrics.characterRectangle(25).center())
|
|
<< QString();
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::clickLink()
|
|
{
|
|
QFETCH(QString, text);
|
|
QFETCH(qreal, width);
|
|
QFETCH(QString, bindings);
|
|
QFETCH(PointVector, mousePositions);
|
|
QFETCH(QString, link);
|
|
|
|
QString componentStr =
|
|
"import QtQuick 2.0\nText {\n"
|
|
"width: " + QString::number(width) + "\n"
|
|
"height: 320\n"
|
|
"text: \"" + text + "\"\n"
|
|
"" + bindings + "\n"
|
|
"}";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject != 0);
|
|
|
|
LinkTest test;
|
|
QObject::connect(textObject, SIGNAL(linkActivated(QString)), &test, SLOT(linkClicked(QString)));
|
|
|
|
QVERIFY(mousePositions.count() > 0);
|
|
|
|
QPointF mousePosition = mousePositions.first();
|
|
{
|
|
QMouseEvent me(QEvent::MouseButtonPress, mousePosition, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
|
|
static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me);
|
|
}
|
|
|
|
for (int i = 1; i < mousePositions.count(); ++i) {
|
|
mousePosition = mousePositions.at(i);
|
|
|
|
QMouseEvent me(QEvent::MouseMove, mousePosition, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
|
|
static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me);
|
|
}
|
|
|
|
{
|
|
QMouseEvent me(QEvent::MouseButtonRelease, mousePosition, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
|
|
static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me);
|
|
}
|
|
|
|
QCOMPARE(test.link, link);
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
void tst_qquicktext::baseUrl()
|
|
{
|
|
QUrl localUrl("file:///tests/text.qml");
|
|
QUrl remoteUrl("http://qt.nokia.com/test.qml");
|
|
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData("import QtQuick 2.0\n Text {}", localUrl);
|
|
QQuickText *textObject = qobject_cast<QQuickText *>(textComponent.create());
|
|
|
|
QCOMPARE(textObject->baseUrl(), localUrl);
|
|
|
|
QSignalSpy spy(textObject, SIGNAL(baseUrlChanged()));
|
|
|
|
textObject->setBaseUrl(localUrl);
|
|
QCOMPARE(textObject->baseUrl(), localUrl);
|
|
QCOMPARE(spy.count(), 0);
|
|
|
|
textObject->setBaseUrl(remoteUrl);
|
|
QCOMPARE(textObject->baseUrl(), remoteUrl);
|
|
QCOMPARE(spy.count(), 1);
|
|
|
|
textObject->resetBaseUrl();
|
|
QCOMPARE(textObject->baseUrl(), localUrl);
|
|
QCOMPARE(spy.count(), 2);
|
|
}
|
|
|
|
void tst_qquicktext::embeddedImages_data()
|
|
{
|
|
QTest::addColumn<QUrl>("qmlfile");
|
|
QTest::addColumn<QString>("error");
|
|
QTest::newRow("local") << testFileUrl("embeddedImagesLocal.qml") << "";
|
|
QTest::newRow("local-error") << testFileUrl("embeddedImagesLocalError.qml")
|
|
<< testFileUrl("embeddedImagesLocalError.qml").toString()+":3:1: QML Text: Cannot open: " + testFileUrl("http/notexists.png").toString();
|
|
QTest::newRow("local") << testFileUrl("embeddedImagesLocalRelative.qml") << "";
|
|
QTest::newRow("remote") << testFileUrl("embeddedImagesRemote.qml") << "";
|
|
QTest::newRow("remote-error") << testFileUrl("embeddedImagesRemoteError.qml")
|
|
<< testFileUrl("embeddedImagesRemoteError.qml").toString()+":3:1: QML Text: Error downloading " SERVER_ADDR "/notexists.png - server replied: Not found";
|
|
QTest::newRow("remote") << testFileUrl("embeddedImagesRemoteRelative.qml") << "";
|
|
}
|
|
|
|
void tst_qquicktext::embeddedImages()
|
|
{
|
|
// Tests QTBUG-9900
|
|
|
|
QFETCH(QUrl, qmlfile);
|
|
QFETCH(QString, error);
|
|
|
|
TestHTTPServer server(SERVER_PORT);
|
|
server.serveDirectory(testFile("http"));
|
|
|
|
if (!error.isEmpty())
|
|
QTest::ignoreMessage(QtWarningMsg, error.toLatin1());
|
|
|
|
QQuickView *view = new QQuickView(qmlfile);
|
|
view->show();
|
|
view->requestActivateWindow();
|
|
QVERIFY(QTest::qWaitForWindowActive(view));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(view->rootObject());
|
|
|
|
QVERIFY(textObject != 0);
|
|
QTRY_COMPARE(textObject->resourcesLoading(), 0);
|
|
|
|
QPixmap pm(testFile("http/exists.png"));
|
|
if (error.isEmpty()) {
|
|
QCOMPARE(textObject->width(), double(pm.width()));
|
|
QCOMPARE(textObject->height(), double(pm.height()));
|
|
} else {
|
|
QVERIFY(16 != pm.width()); // check test is effective
|
|
QCOMPARE(textObject->width(), 16.0); // default size of QTextDocument broken image icon
|
|
QCOMPARE(textObject->height(), 16.0);
|
|
}
|
|
|
|
delete view;
|
|
}
|
|
|
|
void tst_qquicktext::lineCount()
|
|
{
|
|
QQuickView *window = createView(testFile("lineCount.qml"));
|
|
|
|
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
|
|
QVERIFY(myText != 0);
|
|
|
|
QVERIFY(myText->lineCount() > 1);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->maximumLineCount(), INT_MAX);
|
|
|
|
myText->setMaximumLineCount(2);
|
|
QCOMPARE(myText->lineCount(), 2);
|
|
QCOMPARE(myText->truncated(), true);
|
|
QCOMPARE(myText->maximumLineCount(), 2);
|
|
|
|
myText->resetMaximumLineCount();
|
|
QCOMPARE(myText->maximumLineCount(), INT_MAX);
|
|
QCOMPARE(myText->truncated(), false);
|
|
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
myText->setMaximumLineCount(2);
|
|
QCOMPARE(myText->lineCount(), 2);
|
|
QCOMPARE(myText->truncated(), true);
|
|
QCOMPARE(myText->maximumLineCount(), 2);
|
|
|
|
delete window;
|
|
}
|
|
|
|
void tst_qquicktext::lineHeight()
|
|
{
|
|
QQuickView *window = createView(testFile("lineHeight.qml"));
|
|
|
|
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
|
|
QVERIFY(myText != 0);
|
|
|
|
QVERIFY(myText->lineHeight() == 1);
|
|
QVERIFY(myText->lineHeightMode() == QQuickText::ProportionalHeight);
|
|
|
|
qreal h = myText->height();
|
|
myText->setLineHeight(1.5);
|
|
QCOMPARE(myText->height(), qreal(qCeil(h)) * 1.5);
|
|
|
|
myText->setLineHeightMode(QQuickText::FixedHeight);
|
|
myText->setLineHeight(20);
|
|
QCOMPARE(myText->height(), myText->lineCount() * 20.0);
|
|
|
|
myText->setText("Lorem ipsum sit <b>amet</b>, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum.");
|
|
myText->setLineHeightMode(QQuickText::ProportionalHeight);
|
|
myText->setLineHeight(1.0);
|
|
|
|
qreal h2 = myText->height();
|
|
myText->setLineHeight(2.0);
|
|
QVERIFY(myText->height() == h2 * 2.0);
|
|
|
|
myText->setLineHeightMode(QQuickText::FixedHeight);
|
|
myText->setLineHeight(10);
|
|
QCOMPARE(myText->height(), myText->lineCount() * 10.0);
|
|
|
|
delete window;
|
|
}
|
|
|
|
void tst_qquicktext::implicitSize_data()
|
|
{
|
|
QTest::addColumn<QString>("text");
|
|
QTest::addColumn<QString>("width");
|
|
QTest::addColumn<QString>("wrap");
|
|
QTest::addColumn<QString>("elide");
|
|
QTest::addColumn<QString>("format");
|
|
QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideNone" << "Text.PlainText";
|
|
QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone" << "Text.RichText";
|
|
QTest::newRow("styledtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone" << "Text.StyledText";
|
|
QTest::newRow("plain, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideNone" << "Text.PlainText";
|
|
QTest::newRow("plain, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideRight" << "Text.PlainText";
|
|
QTest::newRow("plain, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideRight" << "Text.PlainText";
|
|
QTest::newRow("richtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone" << "Text.RichText";
|
|
QTest::newRow("styledtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone" << "Text.StyledText";
|
|
QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.PlainText";
|
|
QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.RichText";
|
|
QTest::newRow("styledtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.StyledText";
|
|
QTest::newRow("plain_wrap, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.PlainText";
|
|
QTest::newRow("plain_wrap, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideRight" << "Text.PlainText";
|
|
QTest::newRow("plain_wrap, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideRight" << "Text.PlainText";
|
|
QTest::newRow("richtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.RichText";
|
|
QTest::newRow("styledtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.StyledText";
|
|
}
|
|
|
|
void tst_qquicktext::implicitSize()
|
|
{
|
|
QFETCH(QString, text);
|
|
QFETCH(QString, width);
|
|
QFETCH(QString, format);
|
|
QFETCH(QString, wrap);
|
|
QFETCH(QString, elide);
|
|
QString componentStr = "import QtQuick 2.0\nText { "
|
|
"property real iWidth: implicitWidth; "
|
|
"text: \"" + text + "\"; "
|
|
"width: " + width + "; "
|
|
"textFormat: " + format + "; "
|
|
"wrapMode: " + wrap + "; "
|
|
"elide: " + elide + "; "
|
|
"maximumLineCount: 2 }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
|
|
|
|
QVERIFY(textObject->width() < textObject->implicitWidth());
|
|
QVERIFY(textObject->height() == textObject->implicitHeight());
|
|
QCOMPARE(textObject->property("iWidth").toReal(), textObject->implicitWidth());
|
|
|
|
textObject->resetWidth();
|
|
QVERIFY(textObject->width() == textObject->implicitWidth());
|
|
QVERIFY(textObject->height() == textObject->implicitHeight());
|
|
|
|
delete textObject;
|
|
}
|
|
|
|
void tst_qquicktext::contentSize()
|
|
{
|
|
QString componentStr = "import QtQuick 2.0\nText { width: 75; height: 16; font.pixelSize: 10 }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QScopedPointer<QObject> object(textComponent.create());
|
|
QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
|
|
|
|
QSignalSpy spy(textObject, SIGNAL(contentSizeChanged()));
|
|
|
|
textObject->setText("The quick red fox jumped over the lazy brown dog");
|
|
|
|
QVERIFY(textObject->contentWidth() > textObject->width());
|
|
QVERIFY(textObject->contentHeight() < textObject->height());
|
|
QCOMPARE(spy.count(), 1);
|
|
|
|
textObject->setWrapMode(QQuickText::WordWrap);
|
|
QVERIFY(textObject->contentWidth() <= textObject->width());
|
|
QVERIFY(textObject->contentHeight() > textObject->height());
|
|
QCOMPARE(spy.count(), 2);
|
|
|
|
textObject->setElideMode(QQuickText::ElideRight);
|
|
QVERIFY(textObject->contentWidth() <= textObject->width());
|
|
QVERIFY(textObject->contentHeight() < textObject->height());
|
|
QCOMPARE(spy.count(), 3);
|
|
int spyCount = 3;
|
|
qreal elidedWidth = textObject->contentWidth();
|
|
|
|
textObject->setText("The quickredfoxjumpedoverthe lazy brown dog");
|
|
QVERIFY(textObject->contentWidth() <= textObject->width());
|
|
QVERIFY(textObject->contentHeight() < textObject->height());
|
|
// this text probably won't have the same elided width, but it's not guaranteed.
|
|
if (textObject->contentWidth() != elidedWidth)
|
|
QCOMPARE(spy.count(), ++spyCount);
|
|
else
|
|
QCOMPARE(spy.count(), spyCount);
|
|
|
|
textObject->setElideMode(QQuickText::ElideNone);
|
|
QVERIFY(textObject->contentWidth() > textObject->width());
|
|
QVERIFY(textObject->contentHeight() > textObject->height());
|
|
QCOMPARE(spy.count(), ++spyCount);
|
|
}
|
|
|
|
void tst_qquicktext::geometryChanged()
|
|
{
|
|
// Test that text is re-laid out when the geometry of the item by verifying changes in content
|
|
// size. Implicit width is also tested as that in combination with item geometry provides a
|
|
// reference for expected content sizes.
|
|
|
|
QString componentStr = "import QtQuick 2.0\nText { font.family: \"__Qt__Box__Engine__\"; font.pixelSize: 10 }";
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QScopedPointer<QObject> object(textComponent.create());
|
|
QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
|
|
|
|
const qreal implicitHeight = textObject->implicitHeight();
|
|
|
|
const qreal widths[] = { 100, 2000, 3000, -100, 100 };
|
|
const qreal heights[] = { implicitHeight, 2000, 3000, -implicitHeight, implicitHeight };
|
|
|
|
QCOMPARE(textObject->implicitWidth(), 0.);
|
|
QVERIFY(implicitHeight > 0.);
|
|
QCOMPARE(textObject->width(), textObject->implicitWidth());
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QCOMPARE(textObject->contentWidth(), textObject->implicitWidth());
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setText("The quick red fox jumped over the lazy brown dog");
|
|
|
|
const qreal implicitWidth = textObject->implicitWidth();
|
|
|
|
QVERIFY(implicitWidth > 0.);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), textObject->implicitWidth());
|
|
QCOMPARE(textObject->height(), textObject->implicitHeight());
|
|
QCOMPARE(textObject->contentWidth(), textObject->implicitWidth());
|
|
QCOMPARE(textObject->contentHeight(), textObject->implicitHeight());
|
|
|
|
// Changing the geometry with no eliding, or wrapping doesn't change the content size.
|
|
for (int i = 0; i < 5; ++i) {
|
|
textObject->setWidth(widths[i]);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), widths[i]);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QCOMPARE(textObject->contentWidth(), implicitWidth);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
}
|
|
|
|
// With eliding enabled the content width is bounded to the item width, but is never
|
|
// larger than the implicit width.
|
|
textObject->setElideMode(QQuickText::ElideRight);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setWidth(2000.);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), 2000.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QCOMPARE(textObject->contentWidth(), implicitWidth);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setWidth(3000.);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), 3000.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QCOMPARE(textObject->contentWidth(), implicitWidth);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setWidth(-100);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), -100.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QCOMPARE(textObject->contentWidth(), 0.);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setWidth(100.);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
// With wrapping enabled the implicit height changes with the width.
|
|
textObject->setElideMode(QQuickText::ElideNone);
|
|
textObject->setWrapMode(QQuickText::Wrap);
|
|
const qreal wrappedImplicitHeight = textObject->implicitHeight();
|
|
|
|
QVERIFY(wrappedImplicitHeight > implicitHeight);
|
|
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), wrappedImplicitHeight);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), wrappedImplicitHeight);
|
|
|
|
textObject->setWidth(2000.);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), 2000.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QCOMPARE(textObject->contentWidth(), implicitWidth);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setWidth(3000.);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), 3000.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QCOMPARE(textObject->contentWidth(), implicitWidth);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setWidth(-100);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), -100.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QCOMPARE(textObject->contentWidth(), implicitWidth); // 0 or negative width item won't wrap.
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setWidth(100.);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), wrappedImplicitHeight);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), wrappedImplicitHeight);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), wrappedImplicitHeight);
|
|
|
|
// With no eliding or maximum line count the content height is the same as the implicit height.
|
|
for (int i = 0; i < 5; ++i) {
|
|
textObject->setHeight(heights[i]);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), wrappedImplicitHeight);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), heights[i]);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), wrappedImplicitHeight);
|
|
}
|
|
|
|
// The implicit height is unaffected by eliding but the content height will change.
|
|
textObject->setElideMode(QQuickText::ElideRight);
|
|
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), wrappedImplicitHeight);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setHeight(2000);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), wrappedImplicitHeight);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), 2000.);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), wrappedImplicitHeight);
|
|
|
|
textObject->setHeight(3000);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), wrappedImplicitHeight);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), 3000.);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), wrappedImplicitHeight);
|
|
|
|
textObject->setHeight(-implicitHeight);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), wrappedImplicitHeight);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), -implicitHeight);
|
|
QVERIFY(textObject->contentWidth() <= 0.);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight); // content height is never less than font height. seems a little odd in this instance.
|
|
|
|
textObject->setHeight(implicitHeight);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), wrappedImplicitHeight);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
// Varying the height with a maximum line count but no eliding won't affect the content height.
|
|
textObject->setElideMode(QQuickText::ElideNone);
|
|
textObject->setMaximumLineCount(2);
|
|
textObject->resetHeight();
|
|
|
|
const qreal maxLineCountImplicitHeight = textObject->implicitHeight();
|
|
QVERIFY(maxLineCountImplicitHeight > implicitHeight);
|
|
QVERIFY(maxLineCountImplicitHeight < wrappedImplicitHeight);
|
|
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), maxLineCountImplicitHeight);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), maxLineCountImplicitHeight);
|
|
|
|
for (int i = 0; i < 5; ++i) {
|
|
textObject->setHeight(heights[i]);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), maxLineCountImplicitHeight);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), heights[i]);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), maxLineCountImplicitHeight);
|
|
}
|
|
|
|
// Varying the width with a maximum line count won't increase the implicit height beyond the
|
|
// height of the maximum number of lines.
|
|
textObject->setWidth(2000.);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), 2000.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QCOMPARE(textObject->contentWidth(), implicitWidth);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setWidth(3000.);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), 3000.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QCOMPARE(textObject->contentWidth(), implicitWidth);
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setWidth(-100);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), implicitHeight);
|
|
QCOMPARE(textObject->width(), -100.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QCOMPARE(textObject->contentWidth(), implicitWidth); // 0 or negative width item won't wrap.
|
|
QCOMPARE(textObject->contentHeight(), implicitHeight);
|
|
|
|
textObject->setWidth(50.);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), maxLineCountImplicitHeight);
|
|
QCOMPARE(textObject->width(), 50.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QVERIFY(textObject->contentWidth() <= 50.);
|
|
QCOMPARE(textObject->contentHeight(), maxLineCountImplicitHeight);
|
|
|
|
textObject->setWidth(100.);
|
|
QCOMPARE(textObject->implicitWidth(), implicitWidth);
|
|
QCOMPARE(textObject->implicitHeight(), maxLineCountImplicitHeight);
|
|
QCOMPARE(textObject->width(), 100.);
|
|
QCOMPARE(textObject->height(), implicitHeight);
|
|
QVERIFY(textObject->contentWidth() <= 100.);
|
|
QCOMPARE(textObject->contentHeight(), maxLineCountImplicitHeight);
|
|
}
|
|
|
|
void tst_qquicktext::implicitSizeBinding_data()
|
|
{
|
|
implicitSize_data();
|
|
}
|
|
|
|
void tst_qquicktext::implicitSizeBinding()
|
|
{
|
|
QFETCH(QString, text);
|
|
QFETCH(QString, wrap);
|
|
QFETCH(QString, format);
|
|
QString componentStr = "import QtQuick 2.0\nText { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + "; textFormat: " + format + " }";
|
|
|
|
QQmlComponent textComponent(&engine);
|
|
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
|
|
QScopedPointer<QObject> object(textComponent.create());
|
|
QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
|
|
|
|
QCOMPARE(textObject->width(), textObject->implicitWidth());
|
|
QCOMPARE(textObject->height(), textObject->implicitHeight());
|
|
|
|
textObject->resetWidth();
|
|
QCOMPARE(textObject->width(), textObject->implicitWidth());
|
|
QCOMPARE(textObject->height(), textObject->implicitHeight());
|
|
|
|
textObject->resetHeight();
|
|
QCOMPARE(textObject->width(), textObject->implicitWidth());
|
|
QCOMPARE(textObject->height(), textObject->implicitHeight());
|
|
}
|
|
|
|
void tst_qquicktext::boundingRect_data()
|
|
{
|
|
QTest::addColumn<QString>("format");
|
|
QTest::newRow("PlainText") << "Text.PlainText";
|
|
QTest::newRow("StyledText") << "Text.StyledText";
|
|
QTest::newRow("RichText") << "Text.RichText";
|
|
}
|
|
|
|
void tst_qquicktext::boundingRect()
|
|
{
|
|
QFETCH(QString, format);
|
|
|
|
QQmlComponent component(&engine);
|
|
component.setData("import QtQuick 2.0\n Text { textFormat:" + format.toUtf8() + "}", QUrl());
|
|
QScopedPointer<QObject> object(component.create());
|
|
QQuickText *text = qobject_cast<QQuickText *>(object.data());
|
|
QVERIFY(text);
|
|
|
|
QCOMPARE(text->boundingRect().x(), qreal(0));
|
|
QCOMPARE(text->boundingRect().y(), qreal(0));
|
|
QCOMPARE(text->boundingRect().width(), qreal(0));
|
|
QCOMPARE(text->boundingRect().height(), qreal(qCeil(QFontMetricsF(text->font()).height())));
|
|
|
|
text->setText("Hello World");
|
|
|
|
QTextLayout layout(text->text());
|
|
layout.setFont(text->font());
|
|
|
|
if (!qmlDisableDistanceField()) {
|
|
QTextOption option;
|
|
option.setUseDesignMetrics(true);
|
|
layout.setTextOption(option);
|
|
}
|
|
layout.beginLayout();
|
|
QTextLine line = layout.createLine();
|
|
layout.endLayout();
|
|
|
|
QCOMPARE(text->boundingRect().x(), qreal(0));
|
|
QCOMPARE(text->boundingRect().y(), qreal(0));
|
|
QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
|
|
QCOMPARE(text->boundingRect().height(), line.height());
|
|
|
|
// the size of the bounding rect shouldn't be bounded by the size of item.
|
|
text->setWidth(text->width() / 2);
|
|
QCOMPARE(text->boundingRect().x(), qreal(0));
|
|
QCOMPARE(text->boundingRect().y(), qreal(0));
|
|
QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
|
|
QCOMPARE(text->boundingRect().height(), line.height());
|
|
|
|
text->setHeight(text->height() * 2);
|
|
QCOMPARE(text->boundingRect().x(), qreal(0));
|
|
QCOMPARE(text->boundingRect().y(), qreal(0));
|
|
QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
|
|
QCOMPARE(text->boundingRect().height(), line.height());
|
|
|
|
text->setHAlign(QQuickText::AlignRight);
|
|
QCOMPARE(text->boundingRect().x(), text->width() - line.naturalTextWidth());
|
|
QCOMPARE(text->boundingRect().y(), qreal(0));
|
|
QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
|
|
QCOMPARE(text->boundingRect().height(), line.height());
|
|
|
|
text->setWrapMode(QQuickText::Wrap);
|
|
QCOMPARE(text->boundingRect().right(), text->width());
|
|
QCOMPARE(text->boundingRect().y(), qreal(0));
|
|
QVERIFY(text->boundingRect().width() < line.naturalTextWidth());
|
|
QVERIFY(text->boundingRect().height() > line.height());
|
|
|
|
text->setVAlign(QQuickText::AlignBottom);
|
|
QCOMPARE(text->boundingRect().right(), text->width());
|
|
QCOMPARE(text->boundingRect().bottom(), text->height());
|
|
QVERIFY(text->boundingRect().width() < line.naturalTextWidth());
|
|
QVERIFY(text->boundingRect().height() > line.height());
|
|
}
|
|
|
|
void tst_qquicktext::clipRect()
|
|
{
|
|
QQmlComponent component(&engine);
|
|
component.setData("import QtQuick 2.0\n Text {}", QUrl());
|
|
QScopedPointer<QObject> object(component.create());
|
|
QQuickText *text = qobject_cast<QQuickText *>(object.data());
|
|
QVERIFY(text);
|
|
|
|
QTextLayout layout;
|
|
layout.setFont(text->font());
|
|
|
|
QCOMPARE(text->clipRect().x(), qreal(0));
|
|
QCOMPARE(text->clipRect().y(), qreal(0));
|
|
QCOMPARE(text->clipRect().width(), text->width());
|
|
QCOMPARE(text->clipRect().height(), text->height());
|
|
|
|
text->setText("Hello World");
|
|
|
|
QCOMPARE(text->clipRect().x(), qreal(0));
|
|
QCOMPARE(text->clipRect().y(), qreal(0));
|
|
QCOMPARE(text->clipRect().width(), text->width());
|
|
QCOMPARE(text->clipRect().height(), text->height());
|
|
|
|
// Clip rect follows the item not content dimensions.
|
|
text->setWidth(text->width() / 2);
|
|
QCOMPARE(text->clipRect().x(), qreal(0));
|
|
QCOMPARE(text->clipRect().y(), qreal(0));
|
|
QCOMPARE(text->clipRect().width(), text->width());
|
|
QCOMPARE(text->clipRect().height(), text->height());
|
|
|
|
text->setHeight(text->height() * 2);
|
|
QCOMPARE(text->clipRect().x(), qreal(0));
|
|
QCOMPARE(text->clipRect().y(), qreal(0));
|
|
QCOMPARE(text->clipRect().width(), text->width());
|
|
QCOMPARE(text->clipRect().height(), text->height());
|
|
|
|
// Setting a style adds a small amount of padding to the clip rect.
|
|
text->setStyle(QQuickText::Outline);
|
|
QCOMPARE(text->clipRect().x(), qreal(-1));
|
|
QCOMPARE(text->clipRect().y(), qreal(0));
|
|
QCOMPARE(text->clipRect().width(), text->width() + 2);
|
|
QCOMPARE(text->clipRect().height(), text->height() + 2);
|
|
}
|
|
|
|
void tst_qquicktext::lineLaidOut()
|
|
{
|
|
QQuickView *window = createView(testFile("lineLayout.qml"));
|
|
|
|
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
|
|
QVERIFY(myText != 0);
|
|
|
|
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
|
|
QVERIFY(textPrivate != 0);
|
|
|
|
QVERIFY(!textPrivate->extra.isAllocated());
|
|
|
|
for (int i = 0; i < textPrivate->layout.lineCount(); ++i) {
|
|
QRectF r = textPrivate->layout.lineAt(i).rect();
|
|
QVERIFY(r.width() == i * 15);
|
|
if (i >= 30)
|
|
QVERIFY(r.x() == r.width() + 30);
|
|
if (i >= 60) {
|
|
QVERIFY(r.x() == r.width() * 2 + 60);
|
|
QVERIFY(r.height() == 20);
|
|
}
|
|
}
|
|
|
|
delete window;
|
|
}
|
|
|
|
void tst_qquicktext::lineLaidOutRelayout()
|
|
{
|
|
QQuickView *window = createView(testFile("lineLayoutRelayout.qml"));
|
|
|
|
window->show();
|
|
window->requestActivateWindow();
|
|
QVERIFY(QTest::qWaitForWindowActive(window));
|
|
|
|
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
|
|
QVERIFY(myText != 0);
|
|
|
|
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
|
|
QVERIFY(textPrivate != 0);
|
|
|
|
QVERIFY(!textPrivate->extra.isAllocated());
|
|
|
|
qreal maxH = 0;
|
|
for (int i = 0; i < textPrivate->layout.lineCount(); ++i) {
|
|
QRectF r = textPrivate->layout.lineAt(i).rect();
|
|
|
|
if (r.x() == 0) {
|
|
QCOMPARE(r.y(), i * r.height());
|
|
maxH = qMax(maxH, r.y() + r.height());
|
|
} else {
|
|
QCOMPARE(r.x(), myText->width() / 2);
|
|
QCOMPARE(r.y(), (i * r.height()) - maxH);
|
|
}
|
|
}
|
|
|
|
delete window;
|
|
}
|
|
|
|
void tst_qquicktext::imgTagsBaseUrl_data()
|
|
{
|
|
QTest::addColumn<QUrl>("src");
|
|
QTest::addColumn<QUrl>("baseUrl");
|
|
QTest::addColumn<QUrl>("contextUrl");
|
|
QTest::addColumn<qreal>("imgHeight");
|
|
|
|
QTest::newRow("absolute local")
|
|
<< testFileUrl("images/heart200.png")
|
|
<< QUrl()
|
|
<< QUrl()
|
|
<< 181.;
|
|
QTest::newRow("relative local context 1")
|
|
<< QUrl("images/heart200.png")
|
|
<< QUrl()
|
|
<< testFileUrl("/app.qml")
|
|
<< 181.;
|
|
QTest::newRow("relative local context 2")
|
|
<< QUrl("heart200.png")
|
|
<< QUrl()
|
|
<< testFileUrl("images/app.qml")
|
|
<< 181.;
|
|
QTest::newRow("relative local base 1")
|
|
<< QUrl("images/heart200.png")
|
|
<< testFileUrl("")
|
|
<< testFileUrl("nonexistant/app.qml")
|
|
<< 181.;
|
|
QTest::newRow("relative local base 2")
|
|
<< QUrl("heart200.png")
|
|
<< testFileUrl("images/")
|
|
<< testFileUrl("nonexistant/app.qml")
|
|
<< 181.;
|
|
QTest::newRow("base relative to local context")
|
|
<< QUrl("heart200.png")
|
|
<< testFileUrl("images/")
|
|
<< testFileUrl("/app.qml")
|
|
<< 181.;
|
|
|
|
QTest::newRow("absolute remote")
|
|
<< QUrl(SERVER_ADDR "/images/heart200.png")
|
|
<< QUrl()
|
|
<< QUrl()
|
|
<< 181.;
|
|
QTest::newRow("relative remote base 1")
|
|
<< QUrl("images/heart200.png")
|
|
<< QUrl(SERVER_ADDR "/")
|
|
<< testFileUrl("nonexistant/app.qml")
|
|
<< 181.;
|
|
QTest::newRow("relative remote base 2")
|
|
<< QUrl("heart200.png")
|
|
<< QUrl(SERVER_ADDR "/images/")
|
|
<< testFileUrl("nonexistant/app.qml")
|
|
<< 181.;
|
|
}
|
|
|
|
void tst_qquicktext::imgTagsBaseUrl()
|
|
{
|
|
QFETCH(QUrl, src);
|
|
QFETCH(QUrl, baseUrl);
|
|
QFETCH(QUrl, contextUrl);
|
|
QFETCH(qreal, imgHeight);
|
|
|
|
TestHTTPServer server(SERVER_PORT);
|
|
server.serveDirectory(testFile(""));
|
|
|
|
QByteArray baseUrlFragment;
|
|
if (!baseUrl.isEmpty())
|
|
baseUrlFragment = "; baseUrl: \"" + baseUrl.toEncoded() + "\"";
|
|
QByteArray componentStr = "import QtQuick 2.0\nText { text: \"This is a test <img src=\\\"" + src.toEncoded() + "\\\">\"" + baseUrlFragment + " }";
|
|
|
|
QQmlComponent component(&engine);
|
|
component.setData(componentStr, contextUrl);
|
|
QScopedPointer<QObject> object(component.create());
|
|
QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
|
|
QVERIFY(textObject);
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
QTRY_COMPARE(textObject->height(), imgHeight);
|
|
}
|
|
|
|
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.\" }";
|
|
QQmlComponent 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\\\">.\" }";
|
|
|
|
QQmlComponent 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 *window = createView(testFile("imgTagsElide.qml"));
|
|
QQuickText *myText = window->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 window;
|
|
}
|
|
|
|
void tst_qquicktext::imgTagsUpdates()
|
|
{
|
|
QQuickView *window = createView(testFile("imgTagsUpdates.qml"));
|
|
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
|
|
QVERIFY(myText != 0);
|
|
|
|
QSignalSpy spy(myText, SIGNAL(contentSizeChanged()));
|
|
|
|
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 window;
|
|
}
|
|
|
|
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\\\">.\" }";
|
|
|
|
QQmlComponent 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;
|
|
}
|
|
|
|
void tst_qquicktext::fontSizeMode_data()
|
|
{
|
|
QTest::addColumn<QString>("text");
|
|
QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog";
|
|
QTest::newRow("styled") << "<b>The quick red fox jumped over the lazy brown dog</b>";
|
|
}
|
|
|
|
void tst_qquicktext::fontSizeMode()
|
|
{
|
|
QFETCH(QString, text);
|
|
|
|
QScopedPointer<QQuickView> window(createView(testFile("fontSizeMode.qml")));
|
|
window->show();
|
|
|
|
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
|
|
QVERIFY(myText != 0);
|
|
|
|
myText->setText(text);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
qreal originalWidth = myText->contentWidth();
|
|
qreal originalHeight = myText->contentHeight();
|
|
|
|
// The original text unwrapped should exceed the width of the item.
|
|
QVERIFY(originalWidth > myText->width());
|
|
QVERIFY(originalHeight < myText->height());
|
|
|
|
QFont font = myText->font();
|
|
font.setPixelSize(64);
|
|
|
|
myText->setFont(font);
|
|
myText->setFontSizeMode(QQuickText::HorizontalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// Font size reduced to fit within the width of the item.
|
|
qreal horizontalFitWidth = myText->contentWidth();
|
|
qreal horizontalFitHeight = myText->contentHeight();
|
|
QVERIFY(horizontalFitWidth <= myText->width() + 2); // rounding
|
|
QVERIFY(horizontalFitHeight <= myText->height() + 2);
|
|
|
|
// Elide won't affect the size with HorizontalFit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideLeft);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideMiddle);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::VerticalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// Font size increased to fill the height of the item.
|
|
qreal verticalFitHeight = myText->contentHeight();
|
|
QVERIFY(myText->contentWidth() > myText->width());
|
|
QVERIFY(verticalFitHeight <= myText->height() + 2);
|
|
QVERIFY(verticalFitHeight > originalHeight);
|
|
|
|
// Elide won't affect the height of a single line with VerticalFit but will crop the width.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(myText->truncated());
|
|
QVERIFY(myText->contentWidth() <= myText->width() + 2);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideLeft);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(myText->truncated());
|
|
QVERIFY(myText->contentWidth() <= myText->width() + 2);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideMiddle);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(myText->truncated());
|
|
QVERIFY(myText->contentWidth() <= myText->width() + 2);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::Fit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// Should be the same as HorizontalFit with no wrapping.
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
// Elide won't affect the size with Fit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideLeft);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideMiddle);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::FixedSize);
|
|
myText->setWrapMode(QQuickText::Wrap);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
originalWidth = myText->contentWidth();
|
|
originalHeight = myText->contentHeight();
|
|
|
|
// The original text wrapped should exceed the height of the item.
|
|
QVERIFY(originalWidth <= myText->width() + 2);
|
|
QVERIFY(originalHeight > myText->height());
|
|
|
|
myText->setFontSizeMode(QQuickText::HorizontalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
|
|
// same size as without text wrapping.
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
// Elide won't affect the size with HorizontalFit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::VerticalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// VerticalFit should reduce the size to the wrapped text within the vertical height.
|
|
verticalFitHeight = myText->contentHeight();
|
|
qreal verticalFitWidth = myText->contentWidth();
|
|
QVERIFY(myText->contentWidth() <= myText->width() + 2);
|
|
QVERIFY(verticalFitHeight <= myText->height() + 2);
|
|
QVERIFY(verticalFitHeight < originalHeight);
|
|
|
|
// Elide won't affect the height or width of a wrapped text with VerticalFit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::Fit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// Should be the same as VerticalFit with wrapping.
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
// Elide won't affect the size with Fit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::FixedSize);
|
|
myText->setMaximumLineCount(2);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
// The original text wrapped should exceed the height of the item.
|
|
QVERIFY(originalWidth <= myText->width() + 2);
|
|
QVERIFY(originalHeight > myText->height());
|
|
|
|
myText->setFontSizeMode(QQuickText::HorizontalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
|
|
// same size as without text wrapping.
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
// Elide won't affect the size with HorizontalFit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::VerticalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// VerticalFit should reduce the size to the wrapped text within the vertical height.
|
|
verticalFitHeight = myText->contentHeight();
|
|
verticalFitWidth = myText->contentWidth();
|
|
QVERIFY(myText->contentWidth() <= myText->width() + 2);
|
|
QVERIFY(verticalFitHeight <= myText->height() + 2);
|
|
QVERIFY(verticalFitHeight < originalHeight);
|
|
|
|
// Elide won't affect the height or width of a wrapped text with VerticalFit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::Fit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// Should be the same as VerticalFit with wrapping.
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
// Elide won't affect the size with Fit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
}
|
|
|
|
void tst_qquicktext::fontSizeModeMultiline_data()
|
|
{
|
|
QTest::addColumn<QString>("text");
|
|
QTest::newRow("plain") << "The quick red fox jumped\n over the lazy brown dog";
|
|
QTest::newRow("styledtext") << "<b>The quick red fox jumped<br/> over the lazy brown dog</b>";
|
|
}
|
|
|
|
void tst_qquicktext::fontSizeModeMultiline()
|
|
{
|
|
QFETCH(QString, text);
|
|
|
|
QScopedPointer<QQuickView> window(createView(testFile("fontSizeMode.qml")));
|
|
window->show();
|
|
|
|
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
|
|
QVERIFY(myText != 0);
|
|
|
|
myText->setText(text);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
qreal originalWidth = myText->contentWidth();
|
|
qreal originalHeight = myText->contentHeight();
|
|
QCOMPARE(myText->lineCount(), 2);
|
|
|
|
// The original text unwrapped should exceed the width and height of the item.
|
|
QVERIFY(originalWidth > myText->width());
|
|
QVERIFY(originalHeight > myText->height());
|
|
|
|
QFont font = myText->font();
|
|
font.setPixelSize(64);
|
|
|
|
myText->setFont(font);
|
|
myText->setFontSizeMode(QQuickText::HorizontalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// Font size reduced to fit within the width of the item.
|
|
QCOMPARE(myText->lineCount(), 2);
|
|
qreal horizontalFitWidth = myText->contentWidth();
|
|
qreal horizontalFitHeight = myText->contentHeight();
|
|
QVERIFY(horizontalFitWidth <= myText->width() + 2); // rounding
|
|
QVERIFY(horizontalFitHeight > myText->height());
|
|
|
|
// Right eliding will remove the last line
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(myText->truncated());
|
|
QCOMPARE(myText->lineCount(), 1);
|
|
QVERIFY(myText->contentWidth() <= myText->width() + 2);
|
|
QVERIFY(myText->contentHeight() <= myText->height() + 2);
|
|
|
|
// Left or middle eliding wont have any effect.
|
|
myText->setElideMode(QQuickText::ElideLeft);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideMiddle);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::VerticalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// Font size reduced to fit within the height of the item.
|
|
qreal verticalFitWidth = myText->contentWidth();
|
|
qreal verticalFitHeight = myText->contentHeight();
|
|
QVERIFY(verticalFitWidth <= myText->width() + 2);
|
|
QVERIFY(verticalFitHeight <= myText->height() + 2);
|
|
|
|
// Elide will have no effect.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QVERIFY(myText->contentWidth() <= myText->width() + 2);
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideLeft);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideMiddle);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::Fit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// Should be the same as VerticalFit with no wrapping.
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
// Elide won't affect the size with Fit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideLeft);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideMiddle);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::FixedSize);
|
|
myText->setWrapMode(QQuickText::Wrap);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
originalWidth = myText->contentWidth();
|
|
originalHeight = myText->contentHeight();
|
|
|
|
// The original text wrapped should exceed the height of the item.
|
|
QVERIFY(originalWidth <= myText->width() + 2);
|
|
QVERIFY(originalHeight > myText->height());
|
|
|
|
myText->setFontSizeMode(QQuickText::HorizontalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
|
|
// same size as without text wrapping.
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
// Text will be elided vertically with HorizontalFit
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(myText->truncated());
|
|
QVERIFY(myText->contentWidth() <= myText->width() + 2);
|
|
QVERIFY(myText->contentHeight() <= myText->height() + 2);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::VerticalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// VerticalFit should reduce the size to the wrapped text within the vertical height.
|
|
verticalFitHeight = myText->contentHeight();
|
|
verticalFitWidth = myText->contentWidth();
|
|
QVERIFY(myText->contentWidth() <= myText->width() + 2);
|
|
QVERIFY(verticalFitHeight <= myText->height() + 2);
|
|
QVERIFY(verticalFitHeight < originalHeight);
|
|
|
|
// Elide won't affect the height or width of a wrapped text with VerticalFit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::Fit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// Should be the same as VerticalFit with wrapping.
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
// Elide won't affect the size with Fit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::FixedSize);
|
|
myText->setMaximumLineCount(2);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
// The original text wrapped should exceed the height of the item.
|
|
QVERIFY(originalWidth <= myText->width() + 2);
|
|
QVERIFY(originalHeight > myText->height());
|
|
|
|
myText->setFontSizeMode(QQuickText::HorizontalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
|
|
// same size as without text wrapping.
|
|
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
|
|
|
|
// Elide won't affect the size with HorizontalFit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(myText->truncated());
|
|
QVERIFY(myText->contentWidth() <= myText->width() + 2);
|
|
QVERIFY(myText->contentHeight() <= myText->height() + 2);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::VerticalFit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// VerticalFit should reduce the size to the wrapped text within the vertical height.
|
|
verticalFitHeight = myText->contentHeight();
|
|
verticalFitWidth = myText->contentWidth();
|
|
QVERIFY(myText->contentWidth() <= myText->width() + 2);
|
|
QVERIFY(verticalFitHeight <= myText->height() + 2);
|
|
QVERIFY(verticalFitHeight < originalHeight);
|
|
|
|
// Elide won't affect the height or width of a wrapped text with VerticalFit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
myText->setFontSizeMode(QQuickText::Fit);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
// Should be the same as VerticalFit with wrapping.
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
// Elide won't affect the size with Fit.
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
QVERIFY(!myText->truncated());
|
|
QCOMPARE(myText->contentWidth(), verticalFitWidth);
|
|
QCOMPARE(myText->contentHeight(), verticalFitHeight);
|
|
|
|
myText->setElideMode(QQuickText::ElideNone);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
}
|
|
|
|
void tst_qquicktext::multilengthStrings_data()
|
|
{
|
|
QTest::addColumn<QString>("source");
|
|
QTest::newRow("No Wrap") << testFile("multilengthStrings.qml");
|
|
QTest::newRow("Wrap") << testFile("multilengthStringsWrapped.qml");
|
|
}
|
|
|
|
void tst_qquicktext::multilengthStrings()
|
|
{
|
|
QFETCH(QString, source);
|
|
|
|
QScopedPointer<QQuickView> window(createView(source));
|
|
window->show();
|
|
|
|
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
|
|
QVERIFY(myText != 0);
|
|
|
|
const QString longText = "the quick brown fox jumped over the lazy dog";
|
|
const QString mediumText = "the brown fox jumped over the dog";
|
|
const QString shortText = "fox jumped dog";
|
|
|
|
myText->setText(longText);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
const qreal longWidth = myText->contentWidth();
|
|
const qreal longHeight = myText->contentHeight();
|
|
|
|
myText->setText(mediumText);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
const qreal mediumWidth = myText->contentWidth();
|
|
const qreal mediumHeight = myText->contentHeight();
|
|
|
|
myText->setText(shortText);
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
const qreal shortWidth = myText->contentWidth();
|
|
const qreal shortHeight = myText->contentHeight();
|
|
|
|
myText->setElideMode(QQuickText::ElideRight);
|
|
myText->setText(longText + QLatin1Char('\x9c') + mediumText + QLatin1Char('\x9c') + shortText);
|
|
|
|
myText->setSize(QSizeF(longWidth, longHeight));
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
QCOMPARE(myText->contentWidth(), longWidth);
|
|
QCOMPARE(myText->contentHeight(), longHeight);
|
|
QCOMPARE(myText->truncated(), false);
|
|
|
|
myText->setSize(QSizeF(mediumWidth, mediumHeight));
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
QCOMPARE(myText->contentWidth(), mediumWidth);
|
|
QCOMPARE(myText->contentHeight(), mediumHeight);
|
|
QCOMPARE(myText->truncated(), true);
|
|
|
|
myText->setSize(QSizeF(shortWidth, shortHeight));
|
|
QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
|
|
|
|
QCOMPARE(myText->contentWidth(), shortWidth);
|
|
QCOMPARE(myText->contentHeight(), shortHeight);
|
|
QCOMPARE(myText->truncated(), true);
|
|
}
|
|
|
|
void tst_qquicktext::fontFormatSizes_data()
|
|
{
|
|
QTest::addColumn<QString>("text");
|
|
QTest::addColumn<QString>("textWithTag");
|
|
QTest::addColumn<bool>("fontIsBigger");
|
|
|
|
QTest::newRow("fs1") << "Hello world!" << "Hello <font size=\"1\">world</font>!" << false;
|
|
QTest::newRow("fs2") << "Hello world!" << "Hello <font size=\"2\">world</font>!" << false;
|
|
QTest::newRow("fs3") << "Hello world!" << "Hello <font size=\"3\">world</font>!" << false;
|
|
QTest::newRow("fs4") << "Hello world!" << "Hello <font size=\"4\">world</font>!" << true;
|
|
QTest::newRow("fs5") << "Hello world!" << "Hello <font size=\"5\">world</font>!" << true;
|
|
QTest::newRow("fs6") << "Hello world!" << "Hello <font size=\"6\">world</font>!" << true;
|
|
QTest::newRow("fs7") << "Hello world!" << "Hello <font size=\"7\">world</font>!" << true;
|
|
QTest::newRow("h1") << "This is<br/>a font<br/> size test." << "This is <h1>a font</h1> size test." << true;
|
|
QTest::newRow("h2") << "This is<br/>a font<br/> size test." << "This is <h2>a font</h2> size test." << true;
|
|
QTest::newRow("h3") << "This is<br/>a font<br/> size test." << "This is <h3>a font</h3> size test." << true;
|
|
QTest::newRow("h4") << "This is<br/>a font<br/> size test." << "This is <h4>a font</h4> size test." << true;
|
|
QTest::newRow("h5") << "This is<br/>a font<br/> size test." << "This is <h5>a font</h5> size test." << false;
|
|
QTest::newRow("h6") << "This is<br/>a font<br/> size test." << "This is <h6>a font</h6> size test." << false;
|
|
}
|
|
|
|
void tst_qquicktext::fontFormatSizes()
|
|
{
|
|
QFETCH(QString, text);
|
|
QFETCH(QString, textWithTag);
|
|
QFETCH(bool, fontIsBigger);
|
|
|
|
QQuickView *view = new QQuickView;
|
|
{
|
|
view->setSource(testFileUrl("pointFontSizes.qml"));
|
|
view->show();
|
|
|
|
QQuickText *qtext = view->rootObject()->findChild<QQuickText*>("text");
|
|
QQuickText *qtextWithTag = view->rootObject()->findChild<QQuickText*>("textWithTag");
|
|
QVERIFY(qtext != 0);
|
|
QVERIFY(qtextWithTag != 0);
|
|
|
|
qtext->setText(text);
|
|
qtextWithTag->setText(textWithTag);
|
|
|
|
for (int size = 6; size < 100; size += 4) {
|
|
view->rootObject()->setProperty("pointSize", size);
|
|
if (fontIsBigger)
|
|
QVERIFY(qtext->height() <= qtextWithTag->height());
|
|
else
|
|
QVERIFY(qtext->height() >= qtextWithTag->height());
|
|
}
|
|
}
|
|
|
|
{
|
|
view->setSource(testFileUrl("pixelFontSizes.qml"));
|
|
QQuickText *qtext = view->rootObject()->findChild<QQuickText*>("text");
|
|
QQuickText *qtextWithTag = view->rootObject()->findChild<QQuickText*>("textWithTag");
|
|
QVERIFY(qtext != 0);
|
|
QVERIFY(qtextWithTag != 0);
|
|
|
|
qtext->setText(text);
|
|
qtextWithTag->setText(textWithTag);
|
|
|
|
for (int size = 6; size < 100; size += 4) {
|
|
view->rootObject()->setProperty("pixelSize", size);
|
|
if (fontIsBigger)
|
|
QVERIFY(qtext->height() <= qtextWithTag->height());
|
|
else
|
|
QVERIFY(qtext->height() >= qtextWithTag->height());
|
|
}
|
|
}
|
|
delete view;
|
|
}
|
|
|
|
typedef qreal (*ExpectedBaseline)(QQuickText *item);
|
|
Q_DECLARE_METATYPE(ExpectedBaseline)
|
|
|
|
static qreal expectedBaselineTop(QQuickText *item)
|
|
{
|
|
QFontMetricsF fm(item->font());
|
|
return fm.ascent();
|
|
}
|
|
|
|
static qreal expectedBaselineBottom(QQuickText *item)
|
|
{
|
|
QFontMetricsF fm(item->font());
|
|
return item->height() - item->contentHeight() + fm.ascent();
|
|
}
|
|
|
|
static qreal expectedBaselineCenter(QQuickText *item)
|
|
{
|
|
QFontMetricsF fm(item->font());
|
|
return ((item->height() - item->contentHeight()) / 2) + fm.ascent();
|
|
}
|
|
|
|
static qreal expectedBaselineBold(QQuickText *item)
|
|
{
|
|
QFont font = item->font();
|
|
font.setBold(true);
|
|
QFontMetricsF fm(font);
|
|
return fm.ascent();
|
|
}
|
|
|
|
static qreal expectedBaselineImage(QQuickText *item)
|
|
{
|
|
QFontMetricsF fm(item->font());
|
|
// The line is positioned so the bottom of the line is aligned with the bottom of the image,
|
|
// or image height - line height and the baseline is line position + ascent. Because
|
|
// QTextLine's height is rounded up this can give slightly different results to image height
|
|
// - descent.
|
|
return 181 - qCeil(fm.height()) + fm.ascent();
|
|
}
|
|
|
|
static qreal expectedBaselineCustom(QQuickText *item)
|
|
{
|
|
QFontMetricsF fm(item->font());
|
|
return 16 + fm.ascent();
|
|
}
|
|
|
|
static qreal expectedBaselineScaled(QQuickText *item)
|
|
{
|
|
QFont font = item->font();
|
|
QTextLayout layout(item->text().replace(QLatin1Char('\n'), QChar::LineSeparator));
|
|
do {
|
|
layout.setFont(font);
|
|
qreal width = 0;
|
|
layout.beginLayout();
|
|
for (QTextLine line = layout.createLine(); line.isValid(); line = layout.createLine()) {
|
|
line.setLineWidth(FLT_MAX);
|
|
width = qMax(line.naturalTextWidth(), width);
|
|
}
|
|
layout.endLayout();
|
|
|
|
if (width < item->width()) {
|
|
QFontMetricsF fm(layout.font());
|
|
return fm.ascent();
|
|
}
|
|
font.setPointSize(font.pointSize() - 1);
|
|
} while (font.pointSize() > 0);
|
|
return 0;
|
|
}
|
|
|
|
static qreal expectedBaselineFixedBottom(QQuickText *item)
|
|
{
|
|
QFontMetricsF fm(item->font());
|
|
qreal dy = item->text().contains(QLatin1Char('\n'))
|
|
? 160
|
|
: 180;
|
|
return dy + fm.ascent();
|
|
}
|
|
|
|
static qreal expectedBaselineProportionalBottom(QQuickText *item)
|
|
{
|
|
QFontMetricsF fm(item->font());
|
|
qreal dy = item->text().contains(QLatin1Char('\n'))
|
|
? 200 - (qCeil(fm.height()) * 3)
|
|
: 200 - (qCeil(fm.height()) * 1.5);
|
|
return dy + fm.ascent();
|
|
}
|
|
|
|
void tst_qquicktext::baselineOffset_data()
|
|
{
|
|
qRegisterMetaType<ExpectedBaseline>();
|
|
QTest::addColumn<QString>("text");
|
|
QTest::addColumn<QString>("wrappedText");
|
|
QTest::addColumn<QByteArray>("bindings");
|
|
QTest::addColumn<ExpectedBaseline>("expectedBaseline");
|
|
QTest::addColumn<ExpectedBaseline>("expectedBaselineEmpty");
|
|
|
|
QTest::newRow("top align")
|
|
<< "hello world"
|
|
<< "hello\nworld"
|
|
<< QByteArray("height: 200; verticalAlignment: Text.AlignTop")
|
|
<< &expectedBaselineTop
|
|
<< &expectedBaselineTop;
|
|
QTest::newRow("bottom align")
|
|
<< "hello world"
|
|
<< "hello\nworld"
|
|
<< QByteArray("height: 200; verticalAlignment: Text.AlignBottom")
|
|
<< &expectedBaselineBottom
|
|
<< &expectedBaselineBottom;
|
|
QTest::newRow("center align")
|
|
<< "hello world"
|
|
<< "hello\nworld"
|
|
<< QByteArray("height: 200; verticalAlignment: Text.AlignVCenter")
|
|
<< &expectedBaselineCenter
|
|
<< &expectedBaselineCenter;
|
|
|
|
QTest::newRow("bold")
|
|
<< "<b>hello world</b>"
|
|
<< "<b>hello<br/>world</b>"
|
|
<< QByteArray("height: 200")
|
|
<< &expectedBaselineTop
|
|
<< &expectedBaselineBold;
|
|
|
|
QTest::newRow("richText")
|
|
<< "<b>hello world</b>"
|
|
<< "<b>hello<br/>world</b>"
|
|
<< QByteArray("height: 200; textFormat: Text.RichText")
|
|
<< &expectedBaselineTop
|
|
<< &expectedBaselineTop;
|
|
|
|
QTest::newRow("elided")
|
|
<< "hello world"
|
|
<< "hello\nworld"
|
|
<< QByteArray("width: 20; height: 8; elide: Text.ElideRight")
|
|
<< &expectedBaselineTop
|
|
<< &expectedBaselineTop;
|
|
|
|
QTest::newRow("elided bottom align")
|
|
<< "hello world"
|
|
<< "hello\nworld!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
|
<< QByteArray("width: 200; height: 200; elide: Text.ElideRight; verticalAlignment: Text.AlignBottom")
|
|
<< &expectedBaselineBottom
|
|
<< &expectedBaselineBottom;
|
|
|
|
QTest::newRow("image")
|
|
<< "hello <img src=\"images/heart200.png\" /> world"
|
|
<< "hello <img src=\"images/heart200.png\" /><br/>world"
|
|
<< QByteArray("height: 200\n; baseUrl: \"") + testFileUrl("reference").toEncoded() + QByteArray("\"")
|
|
<< &expectedBaselineImage
|
|
<< &expectedBaselineTop;
|
|
|
|
QTest::newRow("customLine")
|
|
<< "hello world"
|
|
<< "hello\nworld"
|
|
<< QByteArray("height: 200; onLineLaidOut: line.y += 16")
|
|
<< &expectedBaselineCustom
|
|
<< &expectedBaselineCustom;
|
|
|
|
QTest::newRow("scaled font")
|
|
<< "hello world"
|
|
<< "hello\nworld"
|
|
<< QByteArray("width: 200; minimumPointSize: 1; font.pointSize: 64; fontSizeMode: Text.HorizontalFit")
|
|
<< &expectedBaselineScaled
|
|
<< &expectedBaselineTop;
|
|
|
|
QTest::newRow("fixed line height top align")
|
|
<< "hello world"
|
|
<< "hello\nworld"
|
|
<< QByteArray("height: 200; lineHeightMode: Text.FixedHeight; lineHeight: 20; verticalAlignment: Text.AlignTop")
|
|
<< &expectedBaselineTop
|
|
<< &expectedBaselineTop;
|
|
|
|
QTest::newRow("fixed line height bottom align")
|
|
<< "hello world"
|
|
<< "hello\nworld"
|
|
<< QByteArray("height: 200; lineHeightMode: Text.FixedHeight; lineHeight: 20; verticalAlignment: Text.AlignBottom")
|
|
<< &expectedBaselineFixedBottom
|
|
<< &expectedBaselineFixedBottom;
|
|
|
|
QTest::newRow("proportional line height top align")
|
|
<< "hello world"
|
|
<< "hello\nworld"
|
|
<< QByteArray("height: 200; lineHeightMode: Text.ProportionalHeight; lineHeight: 1.5; verticalAlignment: Text.AlignTop")
|
|
<< &expectedBaselineTop
|
|
<< &expectedBaselineTop;
|
|
|
|
QTest::newRow("proportional line height bottom align")
|
|
<< "hello world"
|
|
<< "hello\nworld"
|
|
<< QByteArray("height: 200; lineHeightMode: Text.ProportionalHeight; lineHeight: 1.5; verticalAlignment: Text.AlignBottom")
|
|
<< &expectedBaselineProportionalBottom
|
|
<< &expectedBaselineProportionalBottom;
|
|
}
|
|
|
|
void tst_qquicktext::baselineOffset()
|
|
{
|
|
QFETCH(QString, text);
|
|
QFETCH(QString, wrappedText);
|
|
QFETCH(QByteArray, bindings);
|
|
QFETCH(ExpectedBaseline, expectedBaseline);
|
|
QFETCH(ExpectedBaseline, expectedBaselineEmpty);
|
|
|
|
QQmlComponent component(&engine);
|
|
component.setData(
|
|
"import QtQuick 2.0\n"
|
|
"Text {\n"
|
|
+ bindings + "\n"
|
|
"}", QUrl());
|
|
|
|
QScopedPointer<QObject> object(component.create());
|
|
|
|
QQuickText *item = qobject_cast<QQuickText *>(object.data());
|
|
QVERIFY(item);
|
|
|
|
{
|
|
qreal baseline = expectedBaselineEmpty(item);
|
|
|
|
QCOMPARE(item->baselineOffset(), baseline);
|
|
|
|
item->setText(text);
|
|
if (expectedBaseline != expectedBaselineEmpty)
|
|
baseline = expectedBaseline(item);
|
|
|
|
QCOMPARE(item->baselineOffset(), baseline);
|
|
|
|
item->setText(wrappedText);
|
|
QCOMPARE(item->baselineOffset(), expectedBaseline(item));
|
|
}
|
|
|
|
QFont font = item->font();
|
|
font.setPointSize(font.pointSize() + 8);
|
|
|
|
{
|
|
QCOMPARE(item->baselineOffset(), expectedBaseline(item));
|
|
|
|
item->setText(text);
|
|
qreal baseline = expectedBaseline(item);
|
|
QCOMPARE(item->baselineOffset(), baseline);
|
|
|
|
item->setText(QString());
|
|
if (expectedBaselineEmpty != expectedBaseline)
|
|
baseline = expectedBaselineEmpty(item);
|
|
|
|
QCOMPARE(item->baselineOffset(), baseline);
|
|
}
|
|
}
|
|
|
|
void tst_qquicktext::htmlLists()
|
|
{
|
|
QFETCH(QString, text);
|
|
QFETCH(int, nbLines);
|
|
|
|
QQuickView *view = createView(testFile("htmlLists.qml"));
|
|
QQuickText *textObject = view->rootObject()->findChild<QQuickText*>("myText");
|
|
|
|
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
|
|
QVERIFY(textPrivate != 0);
|
|
QVERIFY(textPrivate->extra.isAllocated());
|
|
|
|
QVERIFY(textObject != 0);
|
|
textObject->setText(text);
|
|
|
|
view->show();
|
|
view->requestActivateWindow();
|
|
QVERIFY(QTest::qWaitForWindowActive(view));
|
|
|
|
QCOMPARE(textPrivate->extra->doc->lineCount(), nbLines);
|
|
|
|
delete view;
|
|
}
|
|
|
|
void tst_qquicktext::htmlLists_data()
|
|
{
|
|
QTest::addColumn<QString>("text");
|
|
QTest::addColumn<int>("nbLines");
|
|
|
|
QTest::newRow("ordered list") << "<ol><li>one<li>two<li>three" << 3;
|
|
QTest::newRow("ordered list closed") << "<ol><li>one</li></ol>" << 1;
|
|
QTest::newRow("ordered list alpha") << "<ol type=\"a\"><li>one</li><li>two</li></ol>" << 2;
|
|
QTest::newRow("ordered list upper alpha") << "<ol type=\"A\"><li>one</li><li>two</li></ol>" << 2;
|
|
QTest::newRow("ordered list roman") << "<ol type=\"i\"><li>one</li><li>two</li></ol>" << 2;
|
|
QTest::newRow("ordered list upper roman") << "<ol type=\"I\"><li>one</li><li>two</li></ol>" << 2;
|
|
QTest::newRow("ordered list bad") << "<ol type=\"z\"><li>one</li><li>two</li></ol>" << 2;
|
|
QTest::newRow("unordered list") << "<ul><li>one<li>two" << 2;
|
|
QTest::newRow("unordered list closed") << "<ul><li>one</li><li>two</li></ul>" << 2;
|
|
QTest::newRow("unordered list disc") << "<ul type=\"disc\"><li>one</li><li>two</li></ul>" << 2;
|
|
QTest::newRow("unordered list square") << "<ul type=\"square\"><li>one</li><li>two</li></ul>" << 2;
|
|
QTest::newRow("unordered list bad") << "<ul type=\"bad\"><li>one</li><li>two</li></ul>" << 2;
|
|
}
|
|
|
|
QTEST_MAIN(tst_qquicktext)
|
|
|
|
#include "tst_qquicktext.moc"
|