diff options
author | Shane Kearns <shane.kearns@accenture.com> | 2011-03-25 14:08:28 (GMT) |
---|---|---|
committer | Shane Kearns <shane.kearns@accenture.com> | 2011-03-25 14:08:28 (GMT) |
commit | 12fd077f71a8bc6f865e4e8a4ffe61d5d1b8a504 (patch) | |
tree | ba98e1ff32f288b47b0a05eb0fc293e3c3420889 /tests | |
parent | be5e7924ec7bd6cccd626f931f55e2687910ad13 (diff) | |
parent | 116fed06f9ed561befb505d94b6b44dc71bf9e45 (diff) | |
download | Qt-12fd077f71a8bc6f865e4e8a4ffe61d5d1b8a504.zip Qt-12fd077f71a8bc6f865e4e8a4ffe61d5d1b8a504.tar.gz Qt-12fd077f71a8bc6f865e4e8a4ffe61d5d1b8a504.tar.bz2 |
Merge remote branch 'earth/master' into symbian-socket-engine
Conflicts:
src/network/access/qhttpnetworkconnectionchannel.cpp
src/network/socket/qlocalsocket.cpp
src/s60installs/bwins/QtCoreu.def
src/s60installs/bwins/QtGuiu.def
src/s60installs/bwins/QtTestu.def
src/s60installs/eabi/QtCoreu.def
src/s60installs/eabi/QtGuiu.def
Diffstat (limited to 'tests')
182 files changed, 9501 insertions, 1958 deletions
diff --git a/tests/arthur/baselineserver/src/baselineserver.cpp b/tests/arthur/baselineserver/src/baselineserver.cpp index 8aaa8ff..0c0871a 100644 --- a/tests/arthur/baselineserver/src/baselineserver.cpp +++ b/tests/arthur/baselineserver/src/baselineserver.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -178,7 +178,7 @@ bool BaselineHandler::establishConnection() if (branch.isEmpty()) { // Not run by Pulse, i.e. ad hoc run: Ok. } - else if (branch != QLS("master-integration") || !plat.value(PI_GitCommit).contains(QLS("Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into master-integration"))) { + else if (branch != QLS("master-integration") || !plat.value(PI_GitCommit).contains(QLS("Merge branch 'master' of scm.dev.nokia.troll.no:qt/qt-fire-staging into master-integration"))) { qDebug() << runId << logtime() << "Did not pass branch/staging repo filter, disconnecting."; proto.sendBlock(BaselineProtocol::Abort, QByteArray("This branch/staging repo is not assigned to be tested.")); proto.socket.disconnectFromHost(); @@ -426,27 +426,25 @@ QString BaselineHandler::clearAllBaselines(const QString &context) return QString(QLS("%1 of %2 baselines cleared from context ")).arg((tot-failed)/2).arg(tot/2) + context; } -QString BaselineHandler::updateSingleBaseline(const QString &oldBaseline, const QString &newBaseline) +QString BaselineHandler::updateBaselines(const QString &context, const QString &mismatchContext, const QString &itemFile) { - QString res; - QString basePath(BaselineServer::storagePath() + QLC('/')); - QString srcBase(basePath + newBaseline.left(newBaseline.length() - 3)); - QString dstDir(basePath + oldBaseline.left(oldBaseline.lastIndexOf(QLC('/')))); - - QProcess proc; - proc.setProcessChannelMode(QProcess::MergedChannels); - proc.start(QLS("cp"), QStringList() << QLS("-f") << srcBase + QLS(FileFormat) << srcBase + QLS(MetadataFileExt) << dstDir); - proc.waitForFinished(); - if (proc.exitCode() == 0) - res = QString("Successfully updated '%1'").arg(oldBaseline); - else - res = QString("Error updating baseline: %1<br>" - "Command output: <pre>%2</pre>").arg(proc.errorString(), proc.readAll().constData()); - - return res; + int tot = 0; + int failed = 0; + QString storagePrefix = BaselineServer::storagePath() + QLC('/'); + // If itemId is set, update just that one, otherwise, update all: + QString filter = itemFile.isEmpty() ? QLS("*_????.") : itemFile; + QDirIterator it(storagePrefix + mismatchContext, QStringList() << filter + QLS(FileFormat) << filter + QLS(MetadataFileExt)); + while (it.hasNext()) { + tot++; + it.next(); + QString oldFile = storagePrefix + context + QLC('/') + it.fileName(); + QFile::remove(oldFile); // Remove existing baseline file + if (!QFile::copy(it.filePath(), oldFile)) // and replace it with the mismatch + failed++; + } + return QString(QLS("%1 of %2 baselines updated in context %3 from context %4")).arg((tot-failed)/2).arg(tot/2).arg(context, mismatchContext); } - QString BaselineHandler::blacklistTest(const QString &context, const QString &itemId, bool removeFromBlacklist) { QFile file(BaselineServer::storagePath() + QLC('/') + context + QLS("/BLACKLIST")); diff --git a/tests/arthur/baselineserver/src/baselineserver.h b/tests/arthur/baselineserver/src/baselineserver.h index a5683b2..cae490f 100644 --- a/tests/arthur/baselineserver/src/baselineserver.h +++ b/tests/arthur/baselineserver/src/baselineserver.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -109,7 +109,7 @@ public: // CGI callbacks: static QString view(const QString &baseline, const QString &rendered, const QString &compared); static QString clearAllBaselines(const QString &context); - static QString updateSingleBaseline(const QString &oldBaseline, const QString &newBaseline); + static QString updateBaselines(const QString &context, const QString &mismatchContext, const QString &itemFile); static QString blacklistTest(const QString &context, const QString &itemId, bool removeFromBlacklist = false); private slots: diff --git a/tests/arthur/baselineserver/src/main.cpp b/tests/arthur/baselineserver/src/main.cpp index 02fc2fa..3a03b2f 100644 --- a/tests/arthur/baselineserver/src/main.cpp +++ b/tests/arthur/baselineserver/src/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/arthur/baselineserver/src/report.cpp b/tests/arthur/baselineserver/src/report.cpp index c85f144..5854706 100644 --- a/tests/arthur/baselineserver/src/report.cpp +++ b/tests/arthur/baselineserver/src/report.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -154,10 +154,14 @@ void Report::writeFunctionResults(const ImageItemList &list) QString testFunction = list.at(0).testFunction; QString pageUrl = BaselineServer::baseUrl() + path; QString ctx = handler->pathForItem(list.at(0), true, false).section(QLC('/'), 0, -2); + QString misCtx = handler->pathForItem(list.at(0), false, false).section(QLC('/'), 0, -2); + out << "\n<p> </p><h3>Test function: " << testFunction << "</h3>\n"; out << "<p><a href=\"/cgi-bin/server.cgi?cmd=clearAllBaselines&context=" << ctx << "&url=" << pageUrl - << "\"><b><big>Clear all baselines</big></b></a></h3> (They will be recreated by the next run)</p>\n\n"; + << "\"><b>Clear all baselines</b></a> for this testfunction (They will be recreated by the next run)</p>\n"; + out << "<p><a href=\"/cgi-bin/server.cgi?cmd=updateAllBaselines&context=" << ctx << "&mismatchContext=" << misCtx << "&url=" << pageUrl + << "\"><b>Let these mismatching images be the new baselines</b></a> for this testfunction</p>\n\n"; out << "<table border=\"2\">\n" "<tr>\n" @@ -176,7 +180,8 @@ void Report::writeFunctionResults(const ImageItemList &list) QString metadata = prefix + QLS(MetadataFileExt); if (item.status == ImageItem::Mismatch) { QString rendered = handler->pathForItem(item, false, false) + QLS(FileFormat); - writeItem(baseline, rendered, item, ctx, metadata); + QString itemFile = prefix.section(QLC('/'), -1); + writeItem(baseline, rendered, item, itemFile, ctx, misCtx, metadata); } else { out << "<td align=center><a href=\"/" << baseline << "\">image</a> <a href=\"/" << metadata << "\">info</a></td>\n" @@ -207,7 +212,8 @@ void Report::writeFunctionResults(const ImageItemList &list) out << "</table>\n"; } -void Report::writeItem(const QString &baseline, const QString &rendered, const ImageItem &item, const QString &ctx, const QString &metadata) +void Report::writeItem(const QString &baseline, const QString &rendered, const ImageItem &item, + const QString &itemFile, const QString &ctx, const QString &misCtx, const QString &metadata) { QString compared = generateCompared(baseline, rendered); QString pageUrl = BaselineServer::baseUrl() + path; @@ -219,8 +225,8 @@ void Report::writeItem(const QString &baseline, const QString &rendered, const I out << "<td align=center>\n" << "<p><span style=\"color:red\">Mismatch reported</span></p>\n" << "<p><a href=\"/" << metadata << "\">Baseline Info</a>\n" - << "<p><a href=\"/cgi-bin/server.cgi?cmd=updateSingleBaseline&oldBaseline=" << baseline - << "&newBaseline=" << rendered << "&url=" << pageUrl << "\">Replace baseline with rendered</a></p>\n" + << "<p><a href=\"/cgi-bin/server.cgi?cmd=updateSingleBaseline&context=" << ctx << "&mismatchContext=" << misCtx + << "&itemFile=" << itemFile << "&url=" << pageUrl << "\">Let this be the new baseline</a></p>\n" << "<p><a href=\"/cgi-bin/server.cgi?cmd=blacklist&context=" << ctx << "&itemId=" << item.itemName << "&url=" << pageUrl << "\">Blacklist this item</a></p>\n" << "<p><a href=\"/cgi-bin/server.cgi?cmd=view&baseline=" << baseline << "&rendered=" << rendered @@ -280,8 +286,13 @@ void Report::handleCGIQuery(const QString &query) cgiUrl.queryItemValue(QLS("compared"))); } else if (command == QLS("updateSingleBaseline")) { - s << BaselineHandler::updateSingleBaseline(cgiUrl.queryItemValue(QLS("oldBaseline")), - cgiUrl.queryItemValue(QLS("newBaseline"))); + s << BaselineHandler::updateBaselines(cgiUrl.queryItemValue(QLS("context")), + cgiUrl.queryItemValue(QLS("mismatchContext")), + cgiUrl.queryItemValue(QLS("itemFile"))); + } else if (command == QLS("updateAllBaselines")) { + s << BaselineHandler::updateBaselines(cgiUrl.queryItemValue(QLS("context")), + cgiUrl.queryItemValue(QLS("mismatchContext")), + QString()); } else if (command == QLS("clearAllBaselines")) { s << BaselineHandler::clearAllBaselines(cgiUrl.queryItemValue(QLS("context"))); } else if (command == QLS("blacklist")) { diff --git a/tests/arthur/baselineserver/src/report.h b/tests/arthur/baselineserver/src/report.h index a56aafb..d549a72 100644 --- a/tests/arthur/baselineserver/src/report.h +++ b/tests/arthur/baselineserver/src/report.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -67,7 +67,8 @@ public: private: void write(); void writeFunctionResults(const ImageItemList &list); - void writeItem(const QString &baseline, const QString &rendered, const ImageItem &item, const QString &ctx, const QString &metadata); + void writeItem(const QString &baseline, const QString &rendered, const ImageItem &item, + const QString &itemFile, const QString &ctx, const QString &misCtx, const QString &metadata); void writeHeader(); void writeFooter(); QString generateCompared(const QString &baseline, const QString &rendered, bool fuzzy = false); diff --git a/tests/arthur/common/baselineprotocol.cpp b/tests/arthur/common/baselineprotocol.cpp index e4445bd..0e7e507 100644 --- a/tests/arthur/common/baselineprotocol.cpp +++ b/tests/arthur/common/baselineprotocol.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -310,7 +310,7 @@ bool BaselineProtocol::connect(const QString &testCase, bool *dryrun) } if (cmd == Abort) { - errMsg += QLS("Server aborted connection. Reason: ") + QString::fromLatin1(block); + errMsg += QLS("Server rejected connection. Reason: ") + QString::fromLatin1(block); return false; } diff --git a/tests/arthur/common/baselineprotocol.h b/tests/arthur/common/baselineprotocol.h index 2315bc3..259555d 100644 --- a/tests/arthur/common/baselineprotocol.h +++ b/tests/arthur/common/baselineprotocol.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/arthur/common/lookup3.cpp b/tests/arthur/common/lookup3.cpp index 8cdc64b..1aa501f 100644 --- a/tests/arthur/common/lookup3.cpp +++ b/tests/arthur/common/lookup3.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/arthur/common/qbaselinetest.cpp b/tests/arthur/common/qbaselinetest.cpp index 79241d5..1d028f8 100644 --- a/tests/arthur/common/qbaselinetest.cpp +++ b/tests/arthur/common/qbaselinetest.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/arthur/common/qbaselinetest.h b/tests/arthur/common/qbaselinetest.h index e27cda2..dc32109 100644 --- a/tests/arthur/common/qbaselinetest.h +++ b/tests/arthur/common/qbaselinetest.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/baselineexample/baselineexample.pro b/tests/auto/baselineexample/baselineexample.pro index 30feecc..13f03b8 100644 --- a/tests/auto/baselineexample/baselineexample.pro +++ b/tests/auto/baselineexample/baselineexample.pro @@ -15,4 +15,4 @@ TEMPLATE = app SOURCES += tst_baselineexample.cpp DEFINES += SRCDIR=\\\"$$PWD/\\\" -include($$QT_SOURCE_TREE/tests/arthur/common/qbaselinetest.pri) +include($$PWD/../../arthur/common/qbaselinetest.pri) diff --git a/tests/auto/baselineexample/tst_baselineexample.cpp b/tests/auto/baselineexample/tst_baselineexample.cpp index b97cc63..02af816 100644 --- a/tests/auto/baselineexample/tst_baselineexample.cpp +++ b/tests/auto/baselineexample/tst_baselineexample.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro index 08f0b9e..98e15e8 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -76,11 +76,6 @@ contains(QT_CONFIG, private_tests) { qdeclarativeworkerscript \ qdeclarativexmllistmodel \ qpacketprotocol - -contains(QT_CONFIG, webkit) { - SUBDIRS += \ - qdeclarativewebview -} } # Tests which should run in Pulse diff --git a/tests/auto/declarative/qdeclarativeanchors/data/fill.qml b/tests/auto/declarative/qdeclarativeanchors/data/fill.qml index 50fbbe0..ff19675 100644 --- a/tests/auto/declarative/qdeclarativeanchors/data/fill.qml +++ b/tests/auto/declarative/qdeclarativeanchors/data/fill.qml @@ -6,9 +6,9 @@ Rectangle { objectName: "filler" width: 50; height: 50; color: "blue" anchors.fill: parent; - anchors.leftMargin: 10; - anchors.rightMargin: 20; - anchors.topMargin: 30; - anchors.bottomMargin: 40; + anchors.leftMargin: 10; + anchors.rightMargin: 20; + anchors.topMargin: 30; + anchors.bottomMargin: 40; } } diff --git a/tests/auto/declarative/qdeclarativeanchors/data/margins.qml b/tests/auto/declarative/qdeclarativeanchors/data/margins.qml index dace9c0..685346a 100644 --- a/tests/auto/declarative/qdeclarativeanchors/data/margins.qml +++ b/tests/auto/declarative/qdeclarativeanchors/data/margins.qml @@ -6,8 +6,8 @@ Rectangle { objectName: "filler" width: 50; height: 50; color: "blue" anchors.fill: parent; - anchors.margins: 10 - anchors.leftMargin: 5 - anchors.topMargin: 6 + anchors.margins: 10 + anchors.leftMargin: 5 + anchors.topMargin: 6 } } diff --git a/tests/auto/declarative/qdeclarativeanchors/tst_qdeclarativeanchors.cpp b/tests/auto/declarative/qdeclarativeanchors/tst_qdeclarativeanchors.cpp index e880857..0442350 100644 --- a/tests/auto/declarative/qdeclarativeanchors/tst_qdeclarativeanchors.cpp +++ b/tests/auto/declarative/qdeclarativeanchors/tst_qdeclarativeanchors.cpp @@ -65,13 +65,10 @@ class tst_qdeclarativeanchors : public QObject public: tst_qdeclarativeanchors() {} - template<typename T> - T *findItem(QGraphicsObject *parent, const QString &id); - QGraphicsObject *findObject(QGraphicsObject *parent, const QString &objectName); - private slots: void basicAnchors(); void basicAnchorsQGraphicsWidget(); + void basicAnchorsRTL(); void loops(); void illegalSets(); void illegalSets_data(); @@ -82,16 +79,20 @@ private slots: void nullItem_data(); void crash1(); void centerIn(); + void centerInRTL(); void hvCenter(); + void hvCenterRTL(); void fill(); + void fillRTL(); void margins(); + void marginsRTL(); }; /* Find an item with the specified id. */ template<typename T> -T *tst_qdeclarativeanchors::findItem(QGraphicsObject *parent, const QString &objectName) +T *findItem(QGraphicsObject *parent, const QString &objectName) { const QMetaObject &mo = T::staticMetaObject; QList<QGraphicsItem *> children = parent->childItems(); @@ -110,7 +111,7 @@ T *tst_qdeclarativeanchors::findItem(QGraphicsObject *parent, const QString &obj return 0; } -QGraphicsObject *tst_qdeclarativeanchors::findObject(QGraphicsObject *parent, const QString &objectName) +QGraphicsObject *findObject(QGraphicsObject *parent, const QString &objectName) { QList<QGraphicsItem *> children = parent->childItems(); for (int i = 0; i < children.count(); ++i) { @@ -263,6 +264,105 @@ void tst_qdeclarativeanchors::basicAnchorsQGraphicsWidget() delete view; } +QDeclarativeItem* childItem(QDeclarativeItem *parentItem, const char * itemString) { + return findItem<QDeclarativeItem>(parentItem, QLatin1String(itemString)); +} + +qreal offsetMasterRTL(QDeclarativeItem *rootItem, const char * itemString) { + QDeclarativeItem* masterItem = findItem<QDeclarativeItem>(rootItem, QLatin1String("masterRect")); + return masterItem->width()+2*masterItem->x()-findItem<QDeclarativeItem>(rootItem, QLatin1String(itemString))->width(); +} + +qreal offsetParentRTL(QDeclarativeItem *rootItem, const char * itemString) { + return rootItem->width()+2*rootItem->x()-findItem<QDeclarativeItem>(rootItem, QLatin1String(itemString))->width(); +} + +void mirrorAnchors(QDeclarativeItem *item) { + QDeclarativeItemPrivate *itemPrivate = QDeclarativeItemPrivate::get(item); + itemPrivate->setLayoutMirror(true); +} + +void tst_qdeclarativeanchors::basicAnchorsRTL() +{ + QDeclarativeView *view = new QDeclarativeView; + view->setSource(QUrl::fromLocalFile(SRCDIR "/data/anchors.qml")); + + qApp->processEvents(); + + QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(view->rootObject()); + foreach(QObject *child, rootItem->children()) { + bool mirrored = QDeclarativeItemPrivate::get(qobject_cast<QDeclarativeItem*>(child))->anchors()->property("mirrored").toBool(); + QCOMPARE(mirrored, false); + } + + foreach(QObject *child, rootItem->children()) + mirrorAnchors(qobject_cast<QDeclarativeItem*>(child)); + + foreach(QObject *child, rootItem->children()) { + bool mirrored = QDeclarativeItemPrivate::get(qobject_cast<QDeclarativeItem*>(child))->anchors()->property("mirrored").toBool(); + QCOMPARE(mirrored, true); + } + + //sibling horizontal + QCOMPARE(childItem(rootItem, "rect1")->x(), offsetMasterRTL(rootItem, "rect1")-26.0); + QCOMPARE(childItem(rootItem, "rect2")->x(), offsetMasterRTL(rootItem, "rect2")-122.0); + QCOMPARE(childItem(rootItem, "rect3")->x(), offsetMasterRTL(rootItem, "rect3")-74.0); + QCOMPARE(childItem(rootItem, "rect4")->x(), offsetMasterRTL(rootItem, "rect4")-16.0); + QCOMPARE(childItem(rootItem, "rect5")->x(), offsetMasterRTL(rootItem, "rect5")-112.0); + QCOMPARE(childItem(rootItem, "rect6")->x(), offsetMasterRTL(rootItem, "rect6")-64.0); + + //parent horizontal + QCOMPARE(childItem(rootItem, "rect7")->x(), offsetParentRTL(rootItem, "rect7")-0.0); + QCOMPARE(childItem(rootItem, "rect8")->x(), offsetParentRTL(rootItem, "rect8")-240.0); + QCOMPARE(childItem(rootItem, "rect9")->x(), offsetParentRTL(rootItem, "rect9")-120.0); + QCOMPARE(childItem(rootItem, "rect10")->x(), offsetParentRTL(rootItem, "rect10")+10.0); + QCOMPARE(childItem(rootItem, "rect11")->x(), offsetParentRTL(rootItem, "rect11")-230.0); + QCOMPARE(childItem(rootItem, "rect12")->x(), offsetParentRTL(rootItem, "rect12")-110.0); + + //vertical + QCOMPARE(childItem(rootItem, "rect13")->y(), 20.0); + QCOMPARE(childItem(rootItem, "rect14")->y(), 155.0); + + //stretch + QCOMPARE(childItem(rootItem, "rect15")->x(), offsetMasterRTL(rootItem, "rect15")-26.0); + QCOMPARE(childItem(rootItem, "rect15")->width(), 96.0); + QCOMPARE(childItem(rootItem, "rect16")->x(), offsetMasterRTL(rootItem, "rect16")-26.0); + QCOMPARE(childItem(rootItem, "rect16")->width(), 192.0); + QCOMPARE(childItem(rootItem, "rect17")->x(), offsetMasterRTL(rootItem, "rect17")+70.0); + QCOMPARE(childItem(rootItem, "rect17")->width(), 192.0); + + //vertical stretch + QCOMPARE(childItem(rootItem, "rect18")->y(), 20.0); + QCOMPARE(childItem(rootItem, "rect18")->height(), 40.0); + + //more parent horizontal + QCOMPARE(childItem(rootItem, "rect19")->x(), offsetParentRTL(rootItem, "rect19")-115.0); + QCOMPARE(childItem(rootItem, "rect20")->x(), offsetParentRTL(rootItem, "rect20")-235.0); + QCOMPARE(childItem(rootItem, "rect21")->x(), offsetParentRTL(rootItem, "rect21")+5.0); + + //centerIn + QCOMPARE(childItem(rootItem, "rect22")->x(), offsetMasterRTL(rootItem, "rect22")-69.0); + QCOMPARE(childItem(rootItem, "rect22")->y(), 5.0); + + //margins + QCOMPARE(childItem(rootItem, "rect23")->x(), offsetMasterRTL(rootItem, "rect23")-31.0); + QCOMPARE(childItem(rootItem, "rect23")->y(), 5.0); + QCOMPARE(childItem(rootItem, "rect23")->width(), 86.0); + QCOMPARE(childItem(rootItem, "rect23")->height(), 10.0); + + // offsets + QCOMPARE(childItem(rootItem, "rect24")->x(), offsetMasterRTL(rootItem, "rect24")-26.0); + QCOMPARE(childItem(rootItem, "rect25")->y(), 60.0); + QCOMPARE(childItem(rootItem, "rect26")->y(), 5.0); + + //baseline + QDeclarativeText *text1 = findItem<QDeclarativeText>(rootItem, QLatin1String("text1")); + QDeclarativeText *text2 = findItem<QDeclarativeText>(rootItem, QLatin1String("text2")); + QCOMPARE(text1->y(), text2->y()); + + delete view; +} + // mostly testing that we don't crash void tst_qdeclarativeanchors::loops() { @@ -514,6 +614,31 @@ void tst_qdeclarativeanchors::fill() delete view; } +void tst_qdeclarativeanchors::fillRTL() +{ + QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/fill.qml")); + + qApp->processEvents(); + QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("filler")); + QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect); + mirrorAnchors(rect); + + QCOMPARE(rect->x(), 0.0 + 20.0); + QCOMPARE(rect->y(), 0.0 + 30.0); + QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0); + QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0); + //Alter Offsets (tests QTBUG-6631) + rectPrivate->anchors()->setLeftMargin(20.0); + rectPrivate->anchors()->setRightMargin(0.0); + rectPrivate->anchors()->setBottomMargin(0.0); + rectPrivate->anchors()->setTopMargin(10.0); + QCOMPARE(rect->x(), 0.0 + 0.0); + QCOMPARE(rect->y(), 0.0 + 10.0); + QCOMPARE(rect->width(), 200.0 - 20.0); + QCOMPARE(rect->height(), 200.0 - 10.0); + + delete view; +} void tst_qdeclarativeanchors::centerIn() { QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/centerin.qml")); @@ -521,6 +646,7 @@ void tst_qdeclarativeanchors::centerIn() qApp->processEvents(); QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("centered")); QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect); + QCOMPARE(rect->x(), 75.0 + 10); QCOMPARE(rect->y(), 75.0 + 30); //Alter Offsets (tests QTBUG-6631) @@ -532,6 +658,27 @@ void tst_qdeclarativeanchors::centerIn() delete view; } + +void tst_qdeclarativeanchors::centerInRTL() +{ + QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/centerin.qml")); + + qApp->processEvents(); + QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("centered")); + QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect); + mirrorAnchors(rect); + + QCOMPARE(rect->x(), 75.0 - 10); + QCOMPARE(rect->y(), 75.0 + 30); + //Alter Offsets (tests QTBUG-6631) + rectPrivate->anchors()->setHorizontalCenterOffset(-20.0); + rectPrivate->anchors()->setVerticalCenterOffset(-10.0); + QCOMPARE(rect->x(), 75.0 + 20.0); + QCOMPARE(rect->y(), 75.0 - 10.0); + + delete view; +} + void tst_qdeclarativeanchors::hvCenter() { QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/hvCenter.qml")); @@ -539,12 +686,39 @@ void tst_qdeclarativeanchors::hvCenter() qApp->processEvents(); QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("centered")); QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect); + // test QTBUG-10999 QCOMPARE(rect->x(), 10.0); QCOMPARE(rect->y(), 19.0); + + rectPrivate->anchors()->setHorizontalCenterOffset(-5.0); + rectPrivate->anchors()->setVerticalCenterOffset(5.0); + QCOMPARE(rect->x(), 10.0 - 5.0); + QCOMPARE(rect->y(), 19.0 + 5.0); + delete view; } +void tst_qdeclarativeanchors::hvCenterRTL() +{ + QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/hvCenter.qml")); + + qApp->processEvents(); + QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("centered")); + QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect); + mirrorAnchors(rect); + + // test QTBUG-10999 + QCOMPARE(rect->x(), 10.0); + QCOMPARE(rect->y(), 19.0); + + rectPrivate->anchors()->setHorizontalCenterOffset(-5.0); + rectPrivate->anchors()->setVerticalCenterOffset(5.0); + QCOMPARE(rect->x(), 10.0 + 5.0); + QCOMPARE(rect->y(), 19.0 + 5.0); + + delete view; +} void tst_qdeclarativeanchors::margins() { QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/margins.qml")); @@ -568,6 +742,31 @@ void tst_qdeclarativeanchors::margins() delete view; } +void tst_qdeclarativeanchors::marginsRTL() +{ + QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/margins.qml")); + + QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("filler")); + QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect); + mirrorAnchors(rect); + + QCOMPARE(rect->x(), 10.0); + QCOMPARE(rect->y(), 6.0); + QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0); + QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0); + + rectPrivate->anchors()->setTopMargin(0.0); + rectPrivate->anchors()->setMargins(20.0); + + QCOMPARE(rect->x(), 20.0); + QCOMPARE(rect->y(), 20.0); + QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0); + QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0); + + delete view; +} + + QTEST_MAIN(tst_qdeclarativeanchors) #include "tst_qdeclarativeanchors.moc" diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp b/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp index 104ee15..7d1b807 100644 --- a/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp +++ b/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp @@ -46,6 +46,7 @@ #include <private/qdeclarativeimage_p.h> #include <private/qdeclarativeanimatedimage_p.h> #include <QSignalSpy> +#include <QtDeclarative/qdeclarativecontext.h> #include "../shared/testhttpserver.h" #include "../../../shared/util.h" @@ -76,6 +77,7 @@ private slots: void sourceSizeReadOnly(); void invalidSource(); void qtbug_16520(); + void progressAndStatusChanges(); private: QPixmap grabScene(QGraphicsScene *scene, int width, int height); @@ -333,6 +335,53 @@ void tst_qdeclarativeanimatedimage::qtbug_16520() delete anim; } +void tst_qdeclarativeanimatedimage::progressAndStatusChanges() +{ + TestHTTPServer server(14449); + QVERIFY(server.isValid()); + server.serveDirectory(SRCDIR "/data"); + + QDeclarativeEngine engine; + QString componentStr = "import QtQuick 1.0\nAnimatedImage { source: srcImage }"; + QDeclarativeContext *ctxt = engine.rootContext(); + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/stickman.gif")); + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeImage *obj = qobject_cast<QDeclarativeImage*>(component.create()); + QVERIFY(obj != 0); + QVERIFY(obj->status() == QDeclarativeImage::Ready); + QTRY_VERIFY(obj->progress() == 1.0); + + QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &))); + QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal))); + QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QDeclarativeImageBase::Status))); + + // Loading local file + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/colors.gif")); + QTRY_VERIFY(obj->status() == QDeclarativeImage::Ready); + QTRY_VERIFY(obj->progress() == 1.0); + QTRY_COMPARE(sourceSpy.count(), 1); + QTRY_COMPARE(progressSpy.count(), 0); + QTRY_COMPARE(statusSpy.count(), 0); + + // Loading remote file + ctxt->setContextProperty("srcImage", "http://127.0.0.1:14449/stickman.gif"); + QTRY_VERIFY(obj->status() == QDeclarativeImage::Loading); + QTRY_VERIFY(obj->progress() == 0.0); + QTRY_VERIFY(obj->status() == QDeclarativeImage::Ready); + QTRY_VERIFY(obj->progress() == 1.0); + QTRY_COMPARE(sourceSpy.count(), 2); + QTRY_VERIFY(progressSpy.count() > 1); + QTRY_COMPARE(statusSpy.count(), 2); + + ctxt->setContextProperty("srcImage", ""); + QTRY_VERIFY(obj->status() == QDeclarativeImage::Null); + QTRY_VERIFY(obj->progress() == 0.0); + QTRY_COMPARE(sourceSpy.count(), 3); + QTRY_VERIFY(progressSpy.count() > 2); + QTRY_COMPARE(statusSpy.count(), 3); +} + QTEST_MAIN(tst_qdeclarativeanimatedimage) #include "tst_qdeclarativeanimatedimage.moc" diff --git a/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp b/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp index 64f327b..1168471 100644 --- a/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp +++ b/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/declarative/qdeclarativeflickable/data/disabledcontent.qml b/tests/auto/declarative/qdeclarativeflickable/data/disabledcontent.qml new file mode 100644 index 0000000..dcbb20b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeflickable/data/disabledcontent.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 + +Flickable { + width: 100; height: 100 + contentWidth: 200; contentHeight: 300 + + QGraphicsWidget { width: 200; height: 300; enabled: false } +} diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index 736f8f4..d499edf 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -69,6 +69,7 @@ private slots: void maximumFlickVelocity(); void flickDeceleration(); void pressDelay(); + void disabledContent(); void nestedPressDelay(); void flickableDirection(); void qgraphicswidget(); @@ -247,6 +248,44 @@ void tst_qdeclarativeflickable::pressDelay() QCOMPARE(spy.count(),1); } +// QT-4677 +void tst_qdeclarativeflickable::disabledContent() +{ + QDeclarativeView *canvas = new QDeclarativeView; + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/disabledcontent.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeFlickable *flickable = qobject_cast<QDeclarativeFlickable*>(canvas->rootObject()); + QVERIFY(flickable != 0); + + QVERIFY(flickable->contentX() == 0); + QVERIFY(flickable->contentY() == 0); + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 50))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(70,70)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(90,90)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(100,100)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + + QVERIFY(flickable->contentX() < 0); + QVERIFY(flickable->contentY() < 0); + + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(90, 90))); + + delete canvas; +} + + // QTBUG-17361 void tst_qdeclarativeflickable::nestedPressDelay() { @@ -267,8 +306,8 @@ void tst_qdeclarativeflickable::nestedPressDelay() QVERIFY(outer->property("pressed").toBool() == false); // The outer pressDelay will prevail (50ms, vs. 10sec) - QTest::qWait(300); - QVERIFY(outer->property("pressed").toBool() == true); + // QTRY_VERIFY() has 5sec timeout, so will timeout well within 10sec. + QTRY_VERIFY(outer->property("pressed").toBool() == true); QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(150, 150))); diff --git a/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp b/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp index a62ea31..ffd5d38 100644 --- a/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp +++ b/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp @@ -62,14 +62,24 @@ class tst_qdeclarativefolderlistmodel : public QObject { Q_OBJECT public: - tst_qdeclarativefolderlistmodel() {} + tst_qdeclarativefolderlistmodel() : removeStart(0), removeEnd(0) {} + +public slots: + void removed(const QModelIndex &, int start, int end) { + removeStart = start; + removeEnd = end; + } private slots: void basicProperties(); + void refresh(); private: void checkNoErrors(const QDeclarativeComponent& component); QDeclarativeEngine engine; + + int removeStart; + int removeEnd; }; void tst_qdeclarativefolderlistmodel::checkNoErrors(const QDeclarativeComponent& component) @@ -115,6 +125,28 @@ void tst_qdeclarativefolderlistmodel::basicProperties() QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile("")); } +void tst_qdeclarativefolderlistmodel::refresh() +{ + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml")); + checkNoErrors(component); + + QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create()); + QVERIFY(flm != 0); + + flm->setProperty("folder",QUrl::fromLocalFile(SRCDIR "/data")); + QTRY_COMPARE(flm->property("count").toInt(),2); // wait for refresh + + int count = flm->rowCount(); + + connect(flm, SIGNAL(rowsRemoved(const QModelIndex&,int,int)), + this, SLOT(removed(const QModelIndex&,int,int))); + + flm->setProperty("sortReversed", true); + + QCOMPARE(removeStart, 0); + QCOMPARE(removeEnd, count-1); +} + QTEST_MAIN(tst_qdeclarativefolderlistmodel) #include "tst_qdeclarativefolderlistmodel.moc" diff --git a/tests/auto/declarative/qdeclarativegridview/data/gridview-enforcerange.qml b/tests/auto/declarative/qdeclarativegridview/data/gridview-enforcerange.qml index 5719f43..69eaa47 100644 --- a/tests/auto/declarative/qdeclarativegridview/data/gridview-enforcerange.qml +++ b/tests/auto/declarative/qdeclarativegridview/data/gridview-enforcerange.qml @@ -1,4 +1,4 @@ -import QtQuick 1.0 +import QtQuick 1.1 Rectangle { width: 240 @@ -48,6 +48,8 @@ Rectangle { model: testModel delegate: myDelegate highlight: myHighlight + flow: (testTopToBottom == true) ? GridView.TopToBottom : GridView.LeftToRight + layoutDirection: (testRightToLeft == true) ? Qt.RightToLeft : Qt.LeftToRight preferredHighlightBegin: 100 preferredHighlightEnd: 100 highlightRangeMode: "StrictlyEnforceRange" diff --git a/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml b/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml index e4e699c..caa28d6 100644 --- a/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml +++ b/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml @@ -1,4 +1,4 @@ -import QtQuick 1.0 +import QtQuick 1.1 Rectangle { id: root @@ -55,7 +55,8 @@ Rectangle { height: 320 cellWidth: 80 cellHeight: 60 - flow: (testTopToBottom == false) ? "LeftToRight" : "TopToBottom" + flow: (testTopToBottom == false) ? GridView.LeftToRight : GridView.TopToBottom + layoutDirection: (testRightToLeft == true) ? Qt.RightToLeft : Qt.LeftToRight model: testModel delegate: myDelegate header: root.showHeader ? headerFooter : null diff --git a/tests/auto/declarative/qdeclarativegridview/data/mirroring.qml b/tests/auto/declarative/qdeclarativegridview/data/mirroring.qml new file mode 100644 index 0000000..54de16b --- /dev/null +++ b/tests/auto/declarative/qdeclarativegridview/data/mirroring.qml @@ -0,0 +1,43 @@ +// This example demonstrates how item positioning +// changes in right-to-left layout direction + +import QtQuick 1.1 + +Rectangle { + color: "lightgray" + width: 340 + height: 370 + + VisualItemModel { + id: itemModel + objectName: "itemModel" + Rectangle { + objectName: "item1" + height: 110; width: 120; color: "#FFFEF0" + Text { objectName: "text1"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent } + } + Rectangle { + objectName: "item2" + height: 130; width: 150; color: "#F0FFF7" + Text { objectName: "text2"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent } + } + Rectangle { + objectName: "item3" + height: 170; width: 190; color: "#F4F0FF" + Text { objectName: "text3"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent } + } + } + + GridView { + id: view + objectName: "view" + cellWidth: 190 + cellHeight: 170 + anchors.fill: parent + anchors.bottomMargin: 30 + model: itemModel + highlightRangeMode: "StrictlyEnforceRange" + flow: GridView.TopToBottom + flickDeceleration: 2000 + } +} diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp index 79189a7..c183934 100644 --- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp +++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp @@ -46,6 +46,7 @@ #include <QtDeclarative/qdeclarativecomponent.h> #include <QtDeclarative/qdeclarativecontext.h> #include <QtDeclarative/qdeclarativeexpression.h> +#include <QtDeclarative/private/qdeclarativeitem_p.h> #include <QtDeclarative/private/qlistmodelinterface_p.h> #include <QtDeclarative/private/qdeclarativegridview_p.h> #include <QtDeclarative/private/qdeclarativetext_p.h> @@ -68,6 +69,7 @@ private slots: void changed(); void inserted(); void removed(); + void clear(); void moved(); void changeFlow(); void currentIndex(); @@ -78,9 +80,12 @@ private slots: void componentChanges(); void modelChanges(); void positionViewAtIndex(); + void positionViewAtIndex_rightToLeft(); + void mirroring(); void snapping(); void resetModel(); void enforceRange(); + void enforceRange_rightToLeft(); void QTBUG_8456(); void manualHighlight(); void footer(); @@ -203,6 +208,7 @@ void tst_QDeclarativeGridView::items() QDeclarativeContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); ctxt->setContextProperty("testTopToBottom", QVariant(false)); canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); @@ -251,6 +257,7 @@ void tst_QDeclarativeGridView::changed() QDeclarativeContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); ctxt->setContextProperty("testTopToBottom", QVariant(false)); canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); @@ -284,6 +291,7 @@ void tst_QDeclarativeGridView::inserted() QDeclarativeContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); ctxt->setContextProperty("testTopToBottom", QVariant(false)); canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); @@ -360,6 +368,7 @@ void tst_QDeclarativeGridView::removed() QDeclarativeContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); ctxt->setContextProperty("testTopToBottom", QVariant(false)); canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); @@ -493,6 +502,44 @@ void tst_QDeclarativeGridView::removed() delete canvas; } +void tst_QDeclarativeGridView::clear() +{ + QDeclarativeView *canvas = createView(); + + TestModel model; + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); + ctxt->setContextProperty("testTopToBottom", QVariant(false)); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); + qApp->processEvents(); + + QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid"); + QVERIFY(gridview != 0); + + QDeclarativeItem *contentItem = gridview->contentItem(); + QVERIFY(contentItem != 0); + + model.clear(); + + QVERIFY(gridview->count() == 0); + QVERIFY(gridview->currentItem() == 0); + QVERIFY(gridview->contentY() == 0); + QVERIFY(gridview->currentIndex() == -1); + + // confirm sanity when adding an item to cleared list + model.addItem("New", "1"); + QVERIFY(gridview->count() == 1); + QVERIFY(gridview->currentItem() != 0); + QVERIFY(gridview->currentIndex() == 0); + + delete canvas; +} + void tst_QDeclarativeGridView::moved() { QDeclarativeView *canvas = createView(); @@ -503,6 +550,7 @@ void tst_QDeclarativeGridView::moved() QDeclarativeContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); ctxt->setContextProperty("testTopToBottom", QVariant(false)); canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); @@ -726,6 +774,58 @@ void tst_QDeclarativeGridView::currentIndex() QVERIFY(!gridview->highlightItem()); QVERIFY(!gridview->currentItem()); + gridview->setHighlightFollowsCurrentItem(true); + + gridview->setFlow(QDeclarativeGridView::LeftToRight); + gridview->setLayoutDirection(Qt::RightToLeft); + + qApp->setActiveWindow(canvas); +#ifdef Q_WS_X11 + // to be safe and avoid failing setFocus with window managers + qt_x11_wait_for_window_manager(canvas); +#endif + QTRY_VERIFY(canvas->hasFocus()); + QTRY_VERIFY(canvas->scene()->hasFocus()); + qApp->processEvents(); + + gridview->setCurrentIndex(35); + + QTest::keyClick(canvas, Qt::Key_Right); + QCOMPARE(gridview->currentIndex(), 34); + + QTest::keyClick(canvas, Qt::Key_Down); + QCOMPARE(gridview->currentIndex(), 37); + + QTest::keyClick(canvas, Qt::Key_Up); + QCOMPARE(gridview->currentIndex(), 34); + + QTest::keyClick(canvas, Qt::Key_Left); + QCOMPARE(gridview->currentIndex(), 35); + + + // turn off auto highlight + gridview->setHighlightFollowsCurrentItem(false); + QVERIFY(gridview->highlightFollowsCurrentItem() == false); + QVERIFY(gridview->highlightItem()); + hlPosX = gridview->highlightItem()->x(); + hlPosY = gridview->highlightItem()->y(); + + gridview->setCurrentIndex(5); + QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX); + QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY); + + // insert item before currentIndex + gridview->setCurrentIndex(28); + model.insertItem(0, "Foo", "1111"); + QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29); + + // check removing highlight by setting currentIndex to -1; + gridview->setCurrentIndex(-1); + + QCOMPARE(gridview->currentIndex(), -1); + QVERIFY(!gridview->highlightItem()); + QVERIFY(!gridview->currentItem()); + delete canvas; } @@ -774,6 +874,7 @@ void tst_QDeclarativeGridView::changeFlow() QDeclarativeContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); ctxt->setContextProperty("testTopToBottom", QVariant(false)); canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); @@ -819,6 +920,44 @@ void tst_QDeclarativeGridView::changeFlow() QTRY_COMPARE(number->text(), model.number(i)); } + ctxt->setContextProperty("testRightToLeft", QVariant(true)); + + // Confirm items positioned correctly and indexes correct + itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_COMPARE(item->x(), qreal(-(i/5)*80 - item->width())); + QTRY_COMPARE(item->y(), qreal((i%5)*60)); + QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", i); + QTRY_VERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", i); + QTRY_VERIFY(number != 0); + QTRY_COMPARE(number->text(), model.number(i)); + } + gridview->setContentX(100); + QTRY_COMPARE(gridview->contentX(), 100.); + ctxt->setContextProperty("testTopToBottom", QVariant(false)); + QTRY_COMPARE(gridview->contentX(), 0.); + + // Confirm items positioned correctly and indexes correct + itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_COMPARE(item->x(), qreal(240 - (i%3+1)*80)); + QTRY_COMPARE(item->y(), qreal((i/3)*60)); + QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", i); + QTRY_VERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", i); + QTRY_VERIFY(number != 0); + QTRY_COMPARE(number->text(), model.number(i)); + } + delete canvas; } @@ -879,6 +1018,7 @@ void tst_QDeclarativeGridView::propertyChanges() QSignalSpy keyNavigationWrapsSpy(gridView, SIGNAL(keyNavigationWrapsChanged())); QSignalSpy cacheBufferSpy(gridView, SIGNAL(cacheBufferChanged())); + QSignalSpy layoutSpy(gridView, SIGNAL(layoutDirectionChanged())); QSignalSpy flowSpy(gridView, SIGNAL(flowChanged())); QTRY_COMPARE(gridView->isWrapEnabled(), true); @@ -905,6 +1045,38 @@ void tst_QDeclarativeGridView::propertyChanges() QTRY_COMPARE(cacheBufferSpy.count(),1); QTRY_COMPARE(flowSpy.count(),1); + gridView->setFlow(QDeclarativeGridView::LeftToRight); + QTRY_COMPARE(gridView->flow(), QDeclarativeGridView::LeftToRight); + + gridView->setWrapEnabled(true); + gridView->setCacheBuffer(5); + gridView->setLayoutDirection(Qt::RightToLeft); + + QTRY_COMPARE(gridView->isWrapEnabled(), true); + QTRY_COMPARE(gridView->cacheBuffer(), 5); + QTRY_COMPARE(gridView->layoutDirection(), Qt::RightToLeft); + + QTRY_COMPARE(keyNavigationWrapsSpy.count(),2); + QTRY_COMPARE(cacheBufferSpy.count(),2); + QTRY_COMPARE(layoutSpy.count(),1); + QTRY_COMPARE(flowSpy.count(),2); + + gridView->setWrapEnabled(true); + gridView->setCacheBuffer(5); + gridView->setLayoutDirection(Qt::RightToLeft); + + QTRY_COMPARE(keyNavigationWrapsSpy.count(),2); + QTRY_COMPARE(cacheBufferSpy.count(),2); + QTRY_COMPARE(layoutSpy.count(),1); + QTRY_COMPARE(flowSpy.count(),2); + + gridView->setFlow(QDeclarativeGridView::TopToBottom); + QTRY_COMPARE(gridView->flow(), QDeclarativeGridView::TopToBottom); + QTRY_COMPARE(flowSpy.count(),3); + + gridView->setFlow(QDeclarativeGridView::TopToBottom); + QTRY_COMPARE(flowSpy.count(),3); + delete canvas; } @@ -992,6 +1164,7 @@ void tst_QDeclarativeGridView::positionViewAtIndex() QDeclarativeContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); ctxt->setContextProperty("testTopToBottom", QVariant(false)); canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); @@ -1185,6 +1358,7 @@ void tst_QDeclarativeGridView::snapping() QDeclarativeContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("testTopToBottom", QVariant(false)); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); qApp->processEvents(); @@ -1211,6 +1385,200 @@ void tst_QDeclarativeGridView::snapping() QCOMPARE(gridview->contentY(), 120.); delete canvas; + +} + +void tst_QDeclarativeGridView::mirroring() +{ + QDeclarativeView *canvasA = createView(); + canvasA->setSource(QUrl::fromLocalFile(SRCDIR "/data/mirroring.qml")); + QDeclarativeGridView *gridviewA = findItem<QDeclarativeGridView>(canvasA->rootObject(), "view"); + QTRY_VERIFY(gridviewA != 0); + + QDeclarativeView *canvasB = createView(); + canvasB->setSource(QUrl::fromLocalFile(SRCDIR "/data/mirroring.qml")); + QDeclarativeGridView *gridviewB = findItem<QDeclarativeGridView>(canvasB->rootObject(), "view"); + QTRY_VERIFY(gridviewA != 0); + qApp->processEvents(); + + QList<QString> objectNames; + objectNames << "item1" << "item2"; // << "item3" + + gridviewA->setProperty("layoutDirection", Qt::LeftToRight); + gridviewB->setProperty("layoutDirection", Qt::RightToLeft); + QCOMPARE(gridviewA->layoutDirection(), gridviewA->effectiveLayoutDirection()); + + // LTR != RTL + foreach(const QString objectName, objectNames) + QVERIFY(findItem<QDeclarativeItem>(gridviewA, objectName)->x() != findItem<QDeclarativeItem>(gridviewB, objectName)->x()); + + gridviewA->setProperty("layoutDirection", Qt::LeftToRight); + gridviewB->setProperty("layoutDirection", Qt::LeftToRight); + + // LTR == LTR + foreach(const QString objectName, objectNames) + QCOMPARE(findItem<QDeclarativeItem>(gridviewA, objectName)->x(), findItem<QDeclarativeItem>(gridviewB, objectName)->x()); + + QVERIFY(gridviewB->layoutDirection() == gridviewB->effectiveLayoutDirection()); + QDeclarativeItemPrivate::get(gridviewB)->setLayoutMirror(true); + QVERIFY(gridviewB->layoutDirection() != gridviewB->effectiveLayoutDirection()); + + // LTR != LTR+mirror + foreach(const QString objectName, objectNames) + QVERIFY(findItem<QDeclarativeItem>(gridviewA, objectName)->x() != findItem<QDeclarativeItem>(gridviewB, objectName)->x()); + + gridviewA->setProperty("layoutDirection", Qt::RightToLeft); + + // RTL == LTR+mirror + foreach(const QString objectName, objectNames) + QCOMPARE(findItem<QDeclarativeItem>(gridviewA, objectName)->x(), findItem<QDeclarativeItem>(gridviewB, objectName)->x()); + + gridviewB->setProperty("layoutDirection", Qt::RightToLeft); + + // RTL != RTL+mirror + foreach(const QString objectName, objectNames) + QVERIFY(findItem<QDeclarativeItem>(gridviewA, objectName)->x() != findItem<QDeclarativeItem>(gridviewB, objectName)->x()); + + gridviewA->setProperty("layoutDirection", Qt::LeftToRight); + + // LTR == RTL+mirror + foreach(const QString objectName, objectNames) + QCOMPARE(findItem<QDeclarativeItem>(gridviewA, objectName)->x(), findItem<QDeclarativeItem>(gridviewB, objectName)->x()); + + delete canvasA; + delete canvasB; +} + +void tst_QDeclarativeGridView::positionViewAtIndex_rightToLeft() +{ + QDeclarativeView *canvas = createView(); + + TestModel model; + for (int i = 0; i < 40; i++) + model.addItem("Item" + QString::number(i), ""); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testTopToBottom", QVariant(true)); + ctxt->setContextProperty("testRightToLeft", QVariant(true)); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); + qApp->processEvents(); + + QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid"); + QTRY_VERIFY(gridview != 0); + + QDeclarativeItem *contentItem = gridview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + // Confirm items positioned correctly + int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount-1; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width())); + QTRY_COMPARE(item->y(), qreal((i%5)*60)); + } + + // Position on a currently visible item + gridview->positionViewAtIndex(6, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->contentX(), -320.); + + // Confirm items positioned correctly + itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width())); + QTRY_COMPARE(item->y(), qreal((i%5)*60)); + } + + // Position on an item beyond the visible items + gridview->positionViewAtIndex(21, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->contentX(), -560.); + + // Confirm items positioned correctly + itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width())); + QTRY_COMPARE(item->y(), qreal((i%5)*60)); + } + + // Position on an item that would leave empty space if positioned at the top + gridview->positionViewAtIndex(31, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->contentX(), -639.); + + // Confirm items positioned correctly + itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width())); + QTRY_COMPARE(item->y(), qreal((i%5)*60)); + } + + // Position at the beginning again + gridview->positionViewAtIndex(0, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->contentX(), -240.); + + // Confirm items positioned correctly + itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount-1; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width())); + QTRY_COMPARE(item->y(), qreal((i%5)*60)); + } + + // Position at End + gridview->positionViewAtIndex(30, QDeclarativeGridView::End); + QTRY_COMPARE(gridview->contentX(), -560.); + + // Position in Center + gridview->positionViewAtIndex(15, QDeclarativeGridView::Center); + QTRY_COMPARE(gridview->contentX(), -400.); + + // Ensure at least partially visible + gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible); + QTRY_COMPARE(gridview->contentX(), -400.); + + gridview->setContentX(-555.); + gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible); + QTRY_COMPARE(gridview->contentX(), -555.); + + gridview->setContentX(-239); + gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible); + QTRY_COMPARE(gridview->contentX(), -320.); + + gridview->setContentX(-239); + gridview->positionViewAtIndex(20, QDeclarativeGridView::Visible); + QTRY_COMPARE(gridview->contentX(), -400.); + + gridview->setContentX(-640); + gridview->positionViewAtIndex(20, QDeclarativeGridView::Visible); + QTRY_COMPARE(gridview->contentX(), -560.); + + // Ensure completely visible + gridview->setContentX(-400); + gridview->positionViewAtIndex(20, QDeclarativeGridView::Contain); + QTRY_COMPARE(gridview->contentX(), -400.); + + gridview->setContentX(-315); + gridview->positionViewAtIndex(15, QDeclarativeGridView::Contain); + QTRY_COMPARE(gridview->contentX(), -320.); + + gridview->setContentX(-640); + gridview->positionViewAtIndex(20, QDeclarativeGridView::Contain); + QTRY_COMPARE(gridview->contentX(), -560.); + + delete canvas; } void tst_QDeclarativeGridView::resetModel() @@ -1264,9 +1632,12 @@ void tst_QDeclarativeGridView::enforceRange() QDeclarativeContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); + ctxt->setContextProperty("testTopToBottom", QVariant(false)); canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview-enforcerange.qml")); qApp->processEvents(); + QVERIFY(canvas->rootObject() != 0); QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid"); QTRY_VERIFY(gridview != 0); @@ -1307,6 +1678,64 @@ void tst_QDeclarativeGridView::enforceRange() delete canvas; } +void tst_QDeclarativeGridView::enforceRange_rightToLeft() +{ + QDeclarativeView *canvas = createView(); + + TestModel model; + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(true)); + ctxt->setContextProperty("testTopToBottom", QVariant(true)); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview-enforcerange.qml")); + qApp->processEvents(); + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid"); + QTRY_VERIFY(gridview != 0); + + QTRY_COMPARE(gridview->preferredHighlightBegin(), 100.0); + QTRY_COMPARE(gridview->preferredHighlightEnd(), 100.0); + QTRY_COMPARE(gridview->highlightRangeMode(), QDeclarativeGridView::StrictlyEnforceRange); + + QDeclarativeItem *contentItem = gridview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + // view should be positioned at the top of the range. + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", 0); + QTRY_VERIFY(item); + QTRY_COMPARE(gridview->contentX(), -100.); + QTRY_COMPARE(gridview->contentY(), 0.0); + + QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 0); + QTRY_VERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(0)); + QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 0); + QTRY_VERIFY(number != 0); + QTRY_COMPARE(number->text(), model.number(0)); + + // Check currentIndex is updated when contentItem moves + gridview->setContentX(-200); + QTRY_COMPARE(gridview->currentIndex(), 3); + + gridview->setCurrentIndex(7); + QTRY_COMPARE(gridview->contentX(), -300.); + QTRY_COMPARE(gridview->contentY(), 0.0); + + TestModel model2; + for (int i = 0; i < 5; i++) + model2.addItem("Item" + QString::number(i), ""); + + ctxt->setContextProperty("testModel", &model2); + QCOMPARE(gridview->count(), 5); + + delete canvas; +} + void tst_QDeclarativeGridView::QTBUG_8456() { QDeclarativeView *canvas = createView(); @@ -1475,6 +1904,7 @@ void tst_QDeclarativeGridView::indexAt() QDeclarativeContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); ctxt->setContextProperty("testTopToBottom", QVariant(false)); canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); diff --git a/tests/auto/declarative/qdeclarativeimage/data/qtbug_16389.qml b/tests/auto/declarative/qdeclarativeimage/data/qtbug_16389.qml new file mode 100644 index 0000000..29fba40 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeimage/data/qtbug_16389.qml @@ -0,0 +1,30 @@ +import QtQuick 1.0 +Rectangle { + width: 400 + height: 400 + + Item { + anchors.top: parent.top + anchors.left: parent.left + anchors.bottom: blueHandle.top + anchors.right: blueHandle.left + + Image { + id: iconImage + objectName: "iconImage" + anchors.top: parent.top + anchors.bottom: parent.bottom + source: "heart200.png" + fillMode: Image.PreserveAspectFit + smooth: true + } + } + + Rectangle { + id: blueHandle + objectName: "blueHandle" + color: "blue" + width: 25 + height: 25 + } +} diff --git a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp index f1fe2bd..9e090d2 100644 --- a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp +++ b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp @@ -89,6 +89,7 @@ private slots: void noLoading(); void paintedWidthHeight(); void sourceSize_QTBUG_14303(); + void sourceSize_QTBUG_16389(); void nullPixmapPaint(); void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); @@ -640,6 +641,29 @@ void tst_qdeclarativeimage::sourceSize_QTBUG_14303() QTRY_COMPARE(sourceSizeSpy.count(), 2); } +void tst_qdeclarativeimage::sourceSize_QTBUG_16389() +{ + QDeclarativeView *canvas = new QDeclarativeView(0); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/qtbug_16389.qml")); + canvas->show(); + qApp->processEvents(); + + QDeclarativeImage *image = findItem<QDeclarativeImage>(canvas->rootObject(), "iconImage"); + QDeclarativeItem *handle = findItem<QDeclarativeItem>(canvas->rootObject(), "blueHandle"); + + QCOMPARE(image->sourceSize().width(), 200); + QCOMPARE(image->sourceSize().height(), 200); + QCOMPARE(image->paintedWidth(), 0.0); + QCOMPARE(image->paintedHeight(), 0.0); + + handle->setY(20); + + QCOMPARE(image->sourceSize().width(), 200); + QCOMPARE(image->sourceSize().height(), 200); + QCOMPARE(image->paintedWidth(), 20.0); + QCOMPARE(image->paintedHeight(), 20.0); +} + static int numberOfWarnings = 0; static void checkWarnings(QtMsgType, const char *) { diff --git a/tests/auto/declarative/qdeclarativeitem/data/layoutmirroring.qml b/tests/auto/declarative/qdeclarativeitem/data/layoutmirroring.qml new file mode 100644 index 0000000..866b615 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeitem/data/layoutmirroring.qml @@ -0,0 +1,54 @@ +import QtQuick 1.1 + +Item { + property bool childrenInherit: true + Item { + objectName: "mirrored1" + LayoutMirroring.enabled: true + LayoutMirroring.childrenInherit: parent.childrenInherit + Item { + Item { + objectName: "notMirrored1" + LayoutMirroring.enabled: false + Item { + objectName: "inheritedMirror1" + } + } + Item { + objectName: "inheritedMirror2" + } + } + } + Item { + objectName: "mirrored2" + LayoutMirroring.enabled: true + LayoutMirroring.childrenInherit: false + Item { + objectName: "notMirrored2" + } + } + Item { + LayoutMirroring.enabled: true + LayoutMirroring.childrenInherit: true + Loader { + id: loader + } + } + states: State { + name: "newContent" + PropertyChanges { + target: loader + sourceComponent: component + } + } + Component { + id: component + Item { + objectName: "notMirrored3" + LayoutMirroring.enabled: false + Item { + objectName: "inheritedMirror3" + } + } + } +} diff --git a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp index 137522d..52c9a72 100644 --- a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp +++ b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp @@ -65,7 +65,10 @@ private slots: void keys(); void keysProcessingOrder(); void keyNavigation(); + void keyNavigation_RightToLeft(); void keyNavigation_skipNotVisible(); + void layoutMirroring(); + void layoutMirroringIllegalParent(); void smooth(); void clip(); void mapCoordinates(); @@ -87,13 +90,33 @@ private slots: void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); void qtbug_16871(); - private: - template<typename T> - T *findItem(QGraphicsObject *parent, const QString &objectName); QDeclarativeEngine engine; }; +template<typename T> +T *findItem(QGraphicsObject *parent, const QString &objectName) +{ + if (!parent) + return 0; + + const QMetaObject &mo = T::staticMetaObject; + //qDebug() << parent->QGraphicsObject::children().count() << "children"; + for (int i = 0; i < parent->childItems().count(); ++i) { + QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i)); + if(!item) + continue; + //qDebug() << "try" << item; + if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) + return static_cast<T*>(item); + item = findItem<T>(item, objectName); + if (item) + return static_cast<T*>(item); + } + + return 0; +} + class KeysTestObject : public QObject { Q_OBJECT @@ -380,6 +403,165 @@ void tst_QDeclarativeItem::keysProcessingOrder() delete testObject; } +QDeclarativeItemPrivate *childPrivate(QGraphicsObject *rootItem, const char * itemString) +{ + QDeclarativeItem *item = findItem<QDeclarativeItem>(rootItem, QString(QLatin1String(itemString))); + QDeclarativeItemPrivate* itemPrivate = QDeclarativeItemPrivate::get(item); + return itemPrivate; +} + +QVariant childProperty(QGraphicsObject *rootItem, const char * itemString, const char * property) +{ + QDeclarativeItem *item = findItem<QDeclarativeItem>(rootItem, QString(QLatin1String(itemString))); + return item->property(property); +} + +bool anchorsMirrored(QGraphicsObject *rootItem, const char * itemString) +{ + QDeclarativeItem *item = findItem<QDeclarativeItem>(rootItem, QString(QLatin1String(itemString))); + QDeclarativeItemPrivate* itemPrivate = QDeclarativeItemPrivate::get(item); + return itemPrivate->anchors()->mirrored(); +} + +void tst_QDeclarativeItem::layoutMirroring() +{ + QDeclarativeView *canvas = new QDeclarativeView(0); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/layoutmirroring.qml")); + canvas->show(); + + QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(canvas->rootObject()); + QVERIFY(rootItem); + QDeclarativeItemPrivate *rootPrivate = QDeclarativeItemPrivate::get(rootItem); + QVERIFY(rootPrivate); + + QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "mirrored2")->effectiveLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false); + QCOMPARE(childPrivate(rootItem, "notMirrored2")->effectiveLayoutMirror, false); + QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true); + + QCOMPARE(anchorsMirrored(rootItem, "mirrored1"), true); + QCOMPARE(anchorsMirrored(rootItem, "mirrored2"), true); + QCOMPARE(anchorsMirrored(rootItem, "notMirrored1"), false); + QCOMPARE(anchorsMirrored(rootItem, "notMirrored2"), false); + QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror1"), true); + QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror2"), true); + + QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritedLayoutMirror, false); + QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritedLayoutMirror, false); + QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true); + + QCOMPARE(childPrivate(rootItem, "mirrored1")->isMirrorImplicit, false); + QCOMPARE(childPrivate(rootItem, "mirrored2")->isMirrorImplicit, false); + QCOMPARE(childPrivate(rootItem, "notMirrored1")->isMirrorImplicit, false); + QCOMPARE(childPrivate(rootItem, "notMirrored2")->isMirrorImplicit, true); + QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->isMirrorImplicit, true); + QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->isMirrorImplicit, true); + + QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromParent, true); + QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromParent, false); + QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromParent, true); + QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromParent, false); + QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromParent, true); + QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromParent, true); + + QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromItem, true); + QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromItem, false); + QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromItem, false); + QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromItem, false); + QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromItem, false); + QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromItem, false); + + // load dynamic content using Loader that needs to inherit mirroring + rootItem->setProperty("state", "newContent"); + QCOMPARE(childPrivate(rootItem, "notMirrored3")->effectiveLayoutMirror, false); + QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->effectiveLayoutMirror, true); + + QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritedLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritedLayoutMirror, true); + + QCOMPARE(childPrivate(rootItem, "notMirrored3")->isMirrorImplicit, false); + QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->isMirrorImplicit, true); + + QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromParent, true); + QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritMirrorFromParent, true); + + QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false); + QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false); + + // disable inheritance + rootItem->setProperty("childrenInherit", false); + + QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, false); + QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, false); + QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false); + + QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, false); + QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, false); + QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, false); + QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, false); + + // re-enable inheritance + rootItem->setProperty("childrenInherit", true); + + QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false); + + QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true); + QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true); + + // + // dynamic parenting + // + QDeclarativeItem *parentItem1 = new QDeclarativeItem(); + QDeclarativeItemPrivate::get(parentItem1)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true + QDeclarativeItemPrivate::get(parentItem1)->isMirrorImplicit = false; + QDeclarativeItemPrivate::get(parentItem1)->inheritMirrorFromItem = true; // LayoutMirroring.childrenInherit: true + QDeclarativeItemPrivate::get(parentItem1)->resolveLayoutMirror(); + + // inherit in constructor + QDeclarativeItem *childItem1 = new QDeclarativeItem(parentItem1); + QCOMPARE(QDeclarativeItemPrivate::get(childItem1)->effectiveLayoutMirror, true); + QCOMPARE(QDeclarativeItemPrivate::get(childItem1)->inheritMirrorFromParent, true); + + // inherit through a parent change + QDeclarativeItem *childItem2 = new QDeclarativeItem(); + QCOMPARE(QDeclarativeItemPrivate::get(childItem2)->effectiveLayoutMirror, false); + QCOMPARE(QDeclarativeItemPrivate::get(childItem2)->inheritMirrorFromParent, false); + childItem2->setParentItem(parentItem1); + QCOMPARE(QDeclarativeItemPrivate::get(childItem2)->effectiveLayoutMirror, true); + QCOMPARE(QDeclarativeItemPrivate::get(childItem2)->inheritMirrorFromParent, true); + + // stop inherting through a parent change + QDeclarativeItem *parentItem2 = new QDeclarativeItem(); + QDeclarativeItemPrivate::get(parentItem2)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true + QDeclarativeItemPrivate::get(parentItem2)->resolveLayoutMirror(); + childItem2->setParentItem(parentItem2); + QCOMPARE(QDeclarativeItemPrivate::get(childItem2)->effectiveLayoutMirror, false); + QCOMPARE(QDeclarativeItemPrivate::get(childItem2)->inheritMirrorFromParent, false); + + delete parentItem1; + delete parentItem2; +} + +void tst_QDeclarativeItem::layoutMirroringIllegalParent() +{ + QDeclarativeComponent component(&engine); + component.setData("import QtQuick 1.1; QtObject { LayoutMirroring.enabled: true; LayoutMirroring.childrenInherit: true }", QUrl::fromLocalFile("")); + QTest::ignoreMessage(QtWarningMsg, "file::1:21: QML QtObject: LayoutDirection attached property only works with Items"); + QObject *object = component.create(); + QVERIFY(object != 0); +} + void tst_QDeclarativeItem::keyNavigation() { QDeclarativeView *canvas = new QDeclarativeView(0); @@ -460,6 +642,59 @@ void tst_QDeclarativeItem::keyNavigation() delete canvas; } +void tst_QDeclarativeItem::keyNavigation_RightToLeft() +{ + QDeclarativeView *canvas = new QDeclarativeView(0); + canvas->setFixedSize(240,320); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/keynavigationtest.qml")); + canvas->show(); + qApp->processEvents(); + + QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(canvas->rootObject()); + QVERIFY(rootItem); + QDeclarativeItemPrivate* rootItemPrivate = QDeclarativeItemPrivate::get(rootItem); + + rootItemPrivate->effectiveLayoutMirror = true; // LayoutMirroring.mirror: true + rootItemPrivate->isMirrorImplicit = false; + rootItemPrivate->inheritMirrorFromItem = true; // LayoutMirroring.inherit: true + rootItemPrivate->resolveLayoutMirror(); + + QEvent wa(QEvent::WindowActivate); + QApplication::sendEvent(canvas, &wa); + QFocusEvent fe(QEvent::FocusIn); + QApplication::sendEvent(canvas, &fe); + + QDeclarativeItem *item = findItem<QDeclarativeItem>(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + QVariant result; + QVERIFY(QMetaObject::invokeMethod(canvas->rootObject(), "verify", + Q_RETURN_ARG(QVariant, result))); + QVERIFY(result.toBool()); + + // right + QKeyEvent key(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem<QDeclarativeItem>(canvas->rootObject(), "item2"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // left + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem<QDeclarativeItem>(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + delete canvas; +} + void tst_QDeclarativeItem::keyNavigation_skipNotVisible() { QDeclarativeView *canvas = new QDeclarativeView(0); @@ -1003,32 +1238,6 @@ void tst_QDeclarativeItem::qtbug_16871() delete o; } - -template<typename T> -T *tst_QDeclarativeItem::findItem(QGraphicsObject *parent, const QString &objectName) -{ - if (!parent) - return 0; - - const QMetaObject &mo = T::staticMetaObject; - //qDebug() << parent->QGraphicsObject::children().count() << "children"; - for (int i = 0; i < parent->childItems().count(); ++i) { - QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i)); - if(!item) - continue; - //qDebug() << "try" << item; - if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) - return static_cast<T*>(item); - item = findItem<T>(item, objectName); - if (item) - return static_cast<T*>(item); - } - - return 0; -} - - - QTEST_MAIN(tst_QDeclarativeItem) #include "tst_qdeclarativeitem.moc" diff --git a/tests/auto/declarative/qdeclarativelanguage/data/InlineAssignmentsOverrideBindingsType.qml b/tests/auto/declarative/qdeclarativelanguage/data/InlineAssignmentsOverrideBindingsType.qml new file mode 100644 index 0000000..4526cf0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/InlineAssignmentsOverrideBindingsType.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +QtObject { + property InlineAssignmentsOverrideBindingsType2 nested: InlineAssignmentsOverrideBindingsType2 { + value: 19 * 33 + } +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/InlineAssignmentsOverrideBindingsType2.qml b/tests/auto/declarative/qdeclarativelanguage/data/InlineAssignmentsOverrideBindingsType2.qml new file mode 100644 index 0000000..4127ca4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/InlineAssignmentsOverrideBindingsType2.qml @@ -0,0 +1,5 @@ +import QtQuick 1.0 + +QtObject { + property int value +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/inlineAssignmentsOverrideBindings.qml b/tests/auto/declarative/qdeclarativelanguage/data/inlineAssignmentsOverrideBindings.qml new file mode 100644 index 0000000..8f3c5ce --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/inlineAssignmentsOverrideBindings.qml @@ -0,0 +1,6 @@ +import QtQuick 1.0 + +InlineAssignmentsOverrideBindingsType { + property int test: nested.value + nested.value: 11 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index f3f41a9..5a2591f 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -134,6 +134,7 @@ private slots: void dontDoubleCallClassBegin(); void reservedWords_data(); void reservedWords(); + void inlineAssignmentsOverrideBindings(); void basicRemote_data(); void basicRemote(); @@ -1413,9 +1414,18 @@ void tst_qdeclarativelanguage::testType(const QString& qml, const QString& type, } } +// QTBUG-17276 +void tst_qdeclarativelanguage::inlineAssignmentsOverrideBindings() +{ + QDeclarativeComponent component(&engine, TEST_FILE("inlineAssignmentsOverrideBindings.qml")); -// Import tests (QT-558) + QObject *o = component.create(); + QVERIFY(o != 0); + QCOMPARE(o->property("test").toInt(), 11); + delete o; +} +// Import tests (QT-558) void tst_qdeclarativelanguage::importsBuiltin_data() { // QT-610 diff --git a/tests/auto/declarative/qdeclarativelistview/data/headerfooter.qml b/tests/auto/declarative/qdeclarativelistview/data/headerfooter.qml new file mode 100644 index 0000000..5633831 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelistview/data/headerfooter.qml @@ -0,0 +1,26 @@ +import QtQuick 1.1 + +ListView { + id: view + property bool horizontal: false + property bool rtl: false + width: 240 + height: 320 + + orientation: horizontal ? ListView.Horizontal : ListView.Vertical + header: Rectangle { + objectName: "header" + width: horizontal ? 20 : view.width + height: horizontal ? view.height : 20 + color: "red" + } + footer: Rectangle { + objectName: "footer" + width: horizontal ? 30 : view.width + height: horizontal ? view.height : 30 + color: "blue" + } +// model: testModel + delegate: Text { width: 30; height: 30; text: index + "(" + x + ")" } + layoutDirection: rtl ? Qt.RightToLeft : Qt.LeftToRight +} diff --git a/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml b/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml index 9d9cda8..b2d9213 100644 --- a/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml +++ b/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml @@ -1,6 +1,7 @@ import QtQuick 1.0 Rectangle { + property string sectionProperty: "number" width: 240 height: 320 color: "#ffffff" @@ -56,7 +57,7 @@ Rectangle { height: 320 model: testModel delegate: myDelegate - section.property: "number" + section.property: sectionProperty section.delegate: Rectangle { objectName: "sect_" + section color: "#99bb99" diff --git a/tests/auto/declarative/qdeclarativelistview/data/rightToLeft.qml b/tests/auto/declarative/qdeclarativelistview/data/rightToLeft.qml new file mode 100644 index 0000000..1e92bb3 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelistview/data/rightToLeft.qml @@ -0,0 +1,42 @@ +// This example demonstrates how item positioning +// changes in right-to-left layout direction + +import QtQuick 1.1 + +Rectangle { + color: "lightgray" + width: 640 + height: 320 + + VisualItemModel { + id: itemModel + objectName: "itemModel" + Rectangle { + objectName: "item1" + height: view.height; width: 100; color: "#FFFEF0" + Text { objectName: "text1"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent } + } + Rectangle { + objectName: "item2" + height: view.height; width: 200; color: "#F0FFF7" + Text { objectName: "text2"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent } + } + Rectangle { + objectName: "item3" + height: view.height; width: 240; color: "#F4F0FF" + Text { objectName: "text3"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent } + } + } + + ListView { + id: view + objectName: "view" + anchors.fill: parent + anchors.bottomMargin: 30 + model: itemModel + highlightRangeMode: "StrictlyEnforceRange" + orientation: ListView.Horizontal + flickDeceleration: 2000 + layoutDirection: Qt.RightToLeft + } +} diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp index c7f90da..2267a89 100644 --- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp +++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp @@ -45,6 +45,7 @@ #include <QtDeclarative/qdeclarativeengine.h> #include <QtDeclarative/qdeclarativecontext.h> #include <QtDeclarative/qdeclarativeexpression.h> +#include <QtDeclarative/private/qdeclarativeitem_p.h> #include <QtDeclarative/private/qdeclarativelistview_p.h> #include <QtDeclarative/private/qdeclarativetext_p.h> #include <QtDeclarative/private/qdeclarativevisualitemmodel_p.h> @@ -102,6 +103,7 @@ private slots: void QTBUG_11105(); void header(); void footer(); + void headerFooter(); void resizeView(); void sizeLessThan1(); void QTBUG_14821(); @@ -115,6 +117,8 @@ private slots: void onRemove_data(); void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); + void rightToLeft(); + void test_mirroring(); private: template <class T> void items(); @@ -737,6 +741,13 @@ void tst_QDeclarativeListView::clear() QTRY_VERIFY(listview->count() == 0); QTRY_VERIFY(listview->currentItem() == 0); QTRY_VERIFY(listview->contentY() == 0); + QVERIFY(listview->currentIndex() == -1); + + // confirm sanity when adding an item to cleared list + model.addItem("New", "1"); + QTRY_VERIFY(listview->count() == 1); + QVERIFY(listview->currentItem() != 0); + QVERIFY(listview->currentIndex() == 0); delete canvas; } @@ -1091,6 +1102,52 @@ void tst_QDeclarativeListView::sectionsDelegate() QList<QDeclarativeItem*> items = findItems<QDeclarativeItem>(contentItem, "sect_1"); QCOMPARE(items.count(), 1); + // QTBUG-17759 + model.modifyItem(0, "One", "aaa"); + model.modifyItem(1, "One", "aaa"); + model.modifyItem(2, "One", "aaa"); + model.modifyItem(3, "Four", "aaa"); + model.modifyItem(4, "Four", "aaa"); + model.modifyItem(5, "Four", "aaa"); + model.modifyItem(6, "Five", "aaa"); + model.modifyItem(7, "Five", "aaa"); + model.modifyItem(8, "Five", "aaa"); + model.modifyItem(9, "Two", "aaa"); + model.modifyItem(10, "Two", "aaa"); + model.modifyItem(11, "Two", "aaa"); + QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "sect_aaa").count(), 1); + canvas->rootObject()->setProperty("sectionProperty", "name"); + // ensure view has settled. + QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "sect_Four").count(), 1); + for (int i = 0; i < 4; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, + "sect_" + model.name(i*3)); + QVERIFY(item); + QTRY_COMPARE(item->y(), qreal(i*20*4)); + } + + // QTBUG-17769 + model.removeItems(10, 20); + // ensure view has settled. + QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "wrapper").count(), 10); + // Drag view up beyond bounds + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20,20))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,0)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,-50)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,-200)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20,-200))); + // view should settle back at 0 + QTRY_COMPARE(listview->contentY(), 0.0); + delete canvas; } @@ -1709,8 +1766,6 @@ void tst_QDeclarativeListView::manualHighlight() QDeclarativeView *canvas = new QDeclarativeView(0); canvas->setFixedSize(240,320); - QDeclarativeContext *ctxt = canvas->rootContext(); - QString filename(SRCDIR "/data/manual-highlight.qml"); canvas->setSource(QUrl::fromLocalFile(filename)); @@ -1841,8 +1896,6 @@ void tst_QDeclarativeListView::header() TestModel model; - QDeclarativeContext *ctxt = canvas->rootContext(); - canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header1.qml")); qApp->processEvents(); @@ -1913,6 +1966,112 @@ void tst_QDeclarativeListView::footer() delete canvas; } +class LVAccessor : public QDeclarativeListView +{ +public: + qreal minY() const { return minYExtent(); } + qreal maxY() const { return maxYExtent(); } + qreal minX() const { return minXExtent(); } + qreal maxX() const { return maxXExtent(); } +}; + +void tst_QDeclarativeListView::headerFooter() +{ + { + // Vertical + QDeclarativeView *canvas = createView(); + + TestModel model; + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml")); + qApp->processEvents(); + + QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject()); + QTRY_VERIFY(listview != 0); + + QDeclarativeItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header"); + QVERIFY(header); + QCOMPARE(header->y(), 0.0); + + QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer"); + QVERIFY(footer); + QCOMPARE(footer->y(), 20.0); + + QVERIFY(static_cast<LVAccessor*>(listview)->minY() == 0); + QVERIFY(static_cast<LVAccessor*>(listview)->maxY() == 0); + + delete canvas; + } + { + // Horizontal + QDeclarativeView *canvas = createView(); + + TestModel model; + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml")); + canvas->rootObject()->setProperty("horizontal", true); + qApp->processEvents(); + + QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject()); + QTRY_VERIFY(listview != 0); + + QDeclarativeItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header"); + QVERIFY(header); + QCOMPARE(header->x(), 0.0); + + QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer"); + QVERIFY(footer); + QCOMPARE(footer->x(), 20.0); + + QVERIFY(static_cast<LVAccessor*>(listview)->minX() == 0); + QVERIFY(static_cast<LVAccessor*>(listview)->maxX() == 0); + + delete canvas; + } + { + // Horizontal RTL + QDeclarativeView *canvas = createView(); + + TestModel model; + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml")); + canvas->rootObject()->setProperty("horizontal", true); + canvas->rootObject()->setProperty("rtl", true); + qApp->processEvents(); + + QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject()); + QTRY_VERIFY(listview != 0); + + QDeclarativeItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header"); + QVERIFY(header); + QCOMPARE(header->x(), -20.0); + + QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer"); + QVERIFY(footer); + QCOMPARE(footer->x(), -50.0); + + QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), 240.); + QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), 240.); + + delete canvas; + } +} + void tst_QDeclarativeListView::resizeView() { QDeclarativeView *canvas = createView(); @@ -2312,6 +2471,118 @@ void tst_QDeclarativeListView::testQtQuick11Attributes_data() << ""; } +void tst_QDeclarativeListView::rightToLeft() +{ + QDeclarativeView *canvas = createView(); + canvas->setFixedSize(640,320); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml")); + qApp->processEvents(); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "view"); + QTRY_VERIFY(listview != 0); + + QDeclarativeItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QDeclarativeVisualItemModel *model = canvas->rootObject()->findChild<QDeclarativeVisualItemModel*>("itemModel"); + QTRY_VERIFY(model != 0); + + QTRY_VERIFY(model->count() == 3); + QTRY_COMPARE(listview->currentIndex(), 0); + + // initial position at first item, right edge aligned + QCOMPARE(listview->contentX(), -640.); + + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "item1"); + QTRY_VERIFY(item); + QTRY_COMPARE(item->x(), -100.0); + QCOMPARE(item->height(), listview->height()); + + QDeclarativeText *text = findItem<QDeclarativeText>(contentItem, "text1"); + QTRY_VERIFY(text); + QTRY_COMPARE(text->text(), QLatin1String("index: 0")); + + listview->setCurrentIndex(2); + + item = findItem<QDeclarativeItem>(contentItem, "item3"); + QTRY_VERIFY(item); + QTRY_COMPARE(item->x(), -540.0); + + text = findItem<QDeclarativeText>(contentItem, "text3"); + QTRY_VERIFY(text); + QTRY_COMPARE(text->text(), QLatin1String("index: 2")); + + QCOMPARE(listview->contentX(), -640.); + + // Ensure resizing maintains position relative to right edge + qobject_cast<QDeclarativeItem*>(canvas->rootObject())->setWidth(600); + QTRY_COMPARE(listview->contentX(), -600.); + + delete canvas; +} + +void tst_QDeclarativeListView::test_mirroring() +{ + QDeclarativeView *canvasA = createView(); + canvasA->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml")); + QDeclarativeListView *listviewA = findItem<QDeclarativeListView>(canvasA->rootObject(), "view"); + QTRY_VERIFY(listviewA != 0); + + QDeclarativeView *canvasB = createView(); + canvasB->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml")); + QDeclarativeListView *listviewB = findItem<QDeclarativeListView>(canvasB->rootObject(), "view"); + QTRY_VERIFY(listviewA != 0); + qApp->processEvents(); + + QList<QString> objectNames; + objectNames << "item1" << "item2"; // << "item3" + + listviewA->setProperty("layoutDirection", Qt::LeftToRight); + listviewB->setProperty("layoutDirection", Qt::RightToLeft); + QCOMPARE(listviewA->layoutDirection(), listviewA->effectiveLayoutDirection()); + + // LTR != RTL + foreach(const QString objectName, objectNames) + QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x()); + + listviewA->setProperty("layoutDirection", Qt::LeftToRight); + listviewB->setProperty("layoutDirection", Qt::LeftToRight); + + // LTR == LTR + foreach(const QString objectName, objectNames) + QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x()); + + QVERIFY(listviewB->layoutDirection() == listviewB->effectiveLayoutDirection()); + QDeclarativeItemPrivate::get(listviewB)->setLayoutMirror(true); + QVERIFY(listviewB->layoutDirection() != listviewB->effectiveLayoutDirection()); + + // LTR != LTR+mirror + foreach(const QString objectName, objectNames) + QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x()); + + listviewA->setProperty("layoutDirection", Qt::RightToLeft); + + // RTL == LTR+mirror + foreach(const QString objectName, objectNames) + QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x()); + + listviewB->setProperty("layoutDirection", Qt::RightToLeft); + + // RTL != RTL+mirror + foreach(const QString objectName, objectNames) + QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x()); + + listviewA->setProperty("layoutDirection", Qt::LeftToRight); + + // LTR == RTL+mirror + foreach(const QString objectName, objectNames) + QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x()); + + delete canvasA; + delete canvasB; +} + void tst_QDeclarativeListView::qListModelInterface_items() { items<TestModel>(); @@ -2421,7 +2692,7 @@ QList<T*> tst_QDeclarativeListView::findItems(QGraphicsObject *parent, const QSt //qDebug() << parent->childItems().count() << "children"; for (int i = 0; i < parent->childItems().count(); ++i) { QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i)); - if(!item) + if(!item || !item->isVisible()) continue; //qDebug() << "try" << item; if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) diff --git a/tests/auto/declarative/qdeclarativepathview/data/dragpath.qml b/tests/auto/declarative/qdeclarativepathview/data/dragpath.qml index a361bdc..0f94840 100644 --- a/tests/auto/declarative/qdeclarativepathview/data/dragpath.qml +++ b/tests/auto/declarative/qdeclarativepathview/data/dragpath.qml @@ -9,7 +9,7 @@ PathView { startX: 0; startY: 100 PathLine { x: 400; y: 100 } } - delegate: Rectangle { height: 100; width: 1; color: PathView.isCurrentItem?"red" : "black" } + delegate: Rectangle { objectName: "wrapper"; height: 100; width: 2; color: PathView.isCurrentItem?"red" : "black" } dragMargin: 100 preferredHighlightBegin: 0.5 preferredHighlightEnd: 0.5 diff --git a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp index ebb5f98..8000137 100644 --- a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp +++ b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp @@ -111,6 +111,7 @@ private slots: void undefinedPath(); void mouseDrag(); void treeModel(); + void changePreferredHighlight(); private: QDeclarativeView *createView(); @@ -948,6 +949,45 @@ void tst_QDeclarativePathView::treeModel() delete canvas; } +void tst_QDeclarativePathView::changePreferredHighlight() +{ + QDeclarativeView *canvas = createView(); + canvas->setFixedSize(400,200); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/dragpath.qml")); + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject()); + QVERIFY(pathview != 0); + + int current = pathview->currentIndex(); + QCOMPARE(current, 0); + + QDeclarativeRectangle *firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 0); + QVERIFY(firstItem); + QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path()); + QVERIFY(path); + QPointF start = path->pointAt(0.5); + start.setX(qRound(start.x())); + start.setY(qRound(start.y())); + QPointF offset;//Center of item is at point, but pos is from corner + offset.setX(firstItem->width()/2); + offset.setY(firstItem->height()/2); + QTRY_COMPARE(firstItem->pos() + offset, start); + + pathview->setPreferredHighlightBegin(0.8); + pathview->setPreferredHighlightEnd(0.8); + start = path->pointAt(0.8); + start.setX(qRound(start.x())); + start.setY(qRound(start.y())); + QTRY_COMPARE(firstItem->pos() + offset, start); + QCOMPARE(pathview->currentIndex(), 0); + + delete canvas; +} + QDeclarativeView *tst_QDeclarativePathView::createView() { QDeclarativeView *canvas = new QDeclarativeView(0); diff --git a/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml b/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml deleted file mode 100644 index 0ec1f37..0000000 --- a/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml +++ /dev/null @@ -1,41 +0,0 @@ -import QtQuick 1.1 - -Item { - width: 640 - height: 480 - Grid { - objectName: "grid" - columns: 3 - layoutDirection: Qt.RightToLeft - Rectangle { - objectName: "one" - color: "red" - width: 50 - height: 50 - } - Rectangle { - objectName: "two" - color: "green" - width: 20 - height: 50 - } - Rectangle { - objectName: "three" - color: "blue" - width: 50 - height: 20 - } - Rectangle { - objectName: "four" - color: "cyan" - width: 50 - height: 50 - } - Rectangle { - objectName: "five" - color: "magenta" - width: 10 - height: 10 - } - } -} diff --git a/tests/auto/declarative/qdeclarativepositioners/data/gridtest.qml b/tests/auto/declarative/qdeclarativepositioners/data/gridtest.qml index f3b17dd..929b726 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/gridtest.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/gridtest.qml @@ -1,9 +1,11 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 640 height: 480 + property bool testRightToLeft: false Grid { + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight objectName: "grid" columns: 3 Rectangle { @@ -21,7 +23,7 @@ Item { Rectangle { objectName: "three" color: "blue" - width: 50 + width: 30 height: 20 } Rectangle { diff --git a/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml b/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml index e1a9652..d35c02d 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml @@ -4,7 +4,6 @@ Item { width: 640 height: 480 property bool testRightToLeft: false - Row { objectName: "row" layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight diff --git a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp index 40e533d..92ab722 100644 --- a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp +++ b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp @@ -45,6 +45,7 @@ #include <private/qdeclarativerectangle_p.h> #include <private/qdeclarativepositioners_p.h> #include <private/qdeclarativetransition_p.h> +#include <private/qdeclarativeitem_p.h> #include <qdeclarativeexpression.h> #include <QtGui/qgraphicswidget.h> #include "../../../shared/util.h" @@ -87,6 +88,7 @@ private slots: void test_flow_implicit_resize(); void test_conflictinganchors(); void test_vertical_qgraphicswidget(); + void test_mirroring(); void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); private: @@ -452,7 +454,7 @@ void tst_QDeclarativePositioners::test_grid() QDeclarativeGrid *grid = canvas->rootObject()->findChild<QDeclarativeGrid*>("grid"); QCOMPARE(grid->flow(), QDeclarativeGrid::LeftToRight); - QCOMPARE(grid->width(), 120.0); + QCOMPARE(grid->width(), 100.0); QCOMPARE(grid->height(), 100.0); delete canvas; @@ -494,7 +496,9 @@ void tst_QDeclarativePositioners::test_grid_topToBottom() void tst_QDeclarativePositioners::test_grid_rightToLeft() { - QDeclarativeView *canvas = createView(SRCDIR "/data/grid-righttoleft.qml"); + QDeclarativeView *canvas = createView(SRCDIR "/data/gridtest.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", true); QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); QVERIFY(one != 0); @@ -507,20 +511,20 @@ void tst_QDeclarativePositioners::test_grid_rightToLeft() QDeclarativeRectangle *five = canvas->rootObject()->findChild<QDeclarativeRectangle*>("five"); QVERIFY(five != 0); - QCOMPARE(one->x(), 70.0); + QCOMPARE(one->x(), 50.0); QCOMPARE(one->y(), 0.0); - QCOMPARE(two->x(), 50.0); + QCOMPARE(two->x(), 30.0); QCOMPARE(two->y(), 0.0); QCOMPARE(three->x(), 0.0); QCOMPARE(three->y(), 0.0); - QCOMPARE(four->x(), 70.0); + QCOMPARE(four->x(), 50.0); QCOMPARE(four->y(), 50.0); - QCOMPARE(five->x(), 60.0); + QCOMPARE(five->x(), 40.0); QCOMPARE(five->y(), 50.0); QDeclarativeGrid *grid = canvas->rootObject()->findChild<QDeclarativeGrid*>("grid"); QCOMPARE(grid->layoutDirection(), Qt::RightToLeft); - QCOMPARE(grid->width(), 120.0); + QCOMPARE(grid->width(), 100.0); QCOMPARE(grid->height(), 100.0); delete canvas; @@ -1198,6 +1202,66 @@ void tst_QDeclarativePositioners::test_vertical_qgraphicswidget() delete canvas; } +void tst_QDeclarativePositioners::test_mirroring() +{ + QList<QString> qmlFiles; + qmlFiles << "horizontal.qml" << "gridtest.qml" << "flowtest.qml"; + QList<QString> objectNames; + objectNames << "one" << "two" << "three" << "four" << "five"; + + foreach(const QString qmlFile, qmlFiles) { + QDeclarativeView *canvasA = createView(QString(SRCDIR) + "/data/" + qmlFile); + QDeclarativeItem *rootA = qobject_cast<QDeclarativeItem*>(canvasA->rootObject()); + + QDeclarativeView *canvasB = createView(QString(SRCDIR) + "/data/" + qmlFile); + QDeclarativeItem *rootB = qobject_cast<QDeclarativeItem*>(canvasB->rootObject()); + + rootA->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft + + // LTR != RTL + foreach(const QString objectName, objectNames) { + // horizontal.qml only has three items + if (qmlFile == QString("horizontal.qml") && objectName == QString("four")) + break; + QDeclarativeItem *itemA = rootA->findChild<QDeclarativeItem*>(objectName); + QDeclarativeItem *itemB = rootB->findChild<QDeclarativeItem*>(objectName); + QVERIFY(itemA->x() != itemB->x()); + } + + QDeclarativeItemPrivate* rootPrivateB = QDeclarativeItemPrivate::get(rootB); + + rootPrivateB->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true + rootPrivateB->isMirrorImplicit = false; + rootPrivateB->inheritMirrorFromItem = true; // LayoutMirroring.childrenInherit: true + rootPrivateB->resolveLayoutMirror(); + + // RTL == mirror + foreach(const QString objectName, objectNames) { + // horizontal.qml only has three items + if (qmlFile == QString("horizontal.qml") && objectName == QString("four")) + break; + QDeclarativeItem *itemA = rootA->findChild<QDeclarativeItem*>(objectName); + QDeclarativeItem *itemB = rootB->findChild<QDeclarativeItem*>(objectName); + QCOMPARE(itemA->x(), itemB->x()); + } + + rootA->setProperty("testRightToLeft", false); // layoutDirection: Qt.LeftToRight + rootB->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft + + // LTR == RTL + mirror + foreach(const QString objectName, objectNames) { + // horizontal.qml only has three items + if (qmlFile == QString("horizontal.qml") && objectName == QString("four")) + break; + QDeclarativeItem *itemA = rootA->findChild<QDeclarativeItem*>(objectName); + QDeclarativeItem *itemB = rootB->findChild<QDeclarativeItem*>(objectName); + QCOMPARE(itemA->x(), itemB->x()); + } + delete canvasA; + delete canvasB; + } +} + void tst_QDeclarativePositioners::testQtQuick11Attributes() { QFETCH(QString, code); diff --git a/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp b/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp index 7d746a7..e3a4723 100644 --- a/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp +++ b/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp @@ -76,6 +76,40 @@ void tst_QDeclarativePropertyMap::insert() map.insert(QLatin1String("key1"),"Hello World"); QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World")); + + //inserting property names same with existing method(signal, slot, method) names is not allowed + //QDeclarativePropertyMap has an invokable keys() method + QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"keys\" is not permitted, conflicts with internal symbols. "); + map.insert(QLatin1String("keys"), 1); + QVERIFY(map.keys().count() == 2); + QVERIFY(!map.contains(QLatin1String("keys"))); + QVERIFY(map.value(QLatin1String("keys")).isNull()); + + //QDeclarativePropertyMap has a deleteLater() slot + QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"deleteLater\" is not permitted, conflicts with internal symbols. "); + map.insert(QLatin1String("deleteLater"), 1); + QVERIFY(map.keys().count() == 2); + QVERIFY(!map.contains(QLatin1String("deleteLater"))); + QVERIFY(map.value(QLatin1String("deleteLater")).isNull()); + + //QDeclarativePropertyMap has an valueChanged() signal + QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"valueChanged\" is not permitted, conflicts with internal symbols. "); + map.insert(QLatin1String("valueChanged"), 1); + QVERIFY(map.keys().count() == 2); + QVERIFY(!map.contains(QLatin1String("valueChanged"))); + QVERIFY(map.value(QLatin1String("valueChanged")).isNull()); + + //but 'valueChange' should be ok + map.insert(QLatin1String("valueChange"), 1); + QVERIFY(map.keys().count() == 3); + QVERIFY(map.contains(QLatin1String("valueChange"))); + QCOMPARE(map.value(QLatin1String("valueChange")), QVariant(1)); + + //'valueCHANGED' should be ok, too + map.insert(QLatin1String("valueCHANGED"), 1); + QVERIFY(map.keys().count() == 4); + QVERIFY(map.contains(QLatin1String("valueCHANGED"))); + QCOMPARE(map.value(QLatin1String("valueCHANGED")), QVariant(1)); } void tst_QDeclarativePropertyMap::operatorInsert() diff --git a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp index 56bed30..20e2640 100644 --- a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp +++ b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp @@ -120,6 +120,9 @@ private slots: void anchorChanges3(); void anchorChanges4(); void anchorChanges5(); + void anchorChangesRTL(); + void anchorChangesRTL2(); + void anchorChangesRTL3(); void anchorChangesCrash(); void anchorRewindBug(); void anchorRewindBug2(); @@ -813,6 +816,125 @@ void tst_qdeclarativestates::anchorChanges5() delete rect; } +void mirrorAnchors(QDeclarativeItem *item) { + QDeclarativeItemPrivate *itemPrivate = QDeclarativeItemPrivate::get(item); + itemPrivate->setLayoutMirror(true); +} + +qreal offsetRTL(QDeclarativeItem *anchorItem, QDeclarativeItem *item) { + return anchorItem->width()+2*anchorItem->x()-item->width(); +} + +void tst_qdeclarativestates::anchorChangesRTL() +{ + QDeclarativeEngine engine; + + QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges1.qml"); + QDeclarativeRectangle *rect = qobject_cast<QDeclarativeRectangle*>(rectComponent.create()); + QVERIFY(rect != 0); + QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect); + + QDeclarativeRectangle *innerRect = qobject_cast<QDeclarativeRectangle*>(rect->findChild<QDeclarativeRectangle*>("MyRect")); + QVERIFY(innerRect != 0); + mirrorAnchors(innerRect); + + QDeclarativeListReference list(rect, "states"); + QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0)); + QVERIFY(state != 0); + + qmlExecuteDeferred(state); + QDeclarativeAnchorChanges *aChanges = qobject_cast<QDeclarativeAnchorChanges*>(state->operationAt(0)); + QVERIFY(aChanges != 0); + + rectPrivate->setState("right"); + QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150)); + QCOMPARE(aChanges->object(), qobject_cast<QDeclarativeItem*>(innerRect)); + QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QDeclarativeAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all) + QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item); + QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine); + + rectPrivate->setState(""); + QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) -qreal(5)); + + delete rect; +} + +void tst_qdeclarativestates::anchorChangesRTL2() +{ + QDeclarativeEngine engine; + + QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges2.qml"); + QDeclarativeRectangle *rect = qobject_cast<QDeclarativeRectangle*>(rectComponent.create()); + QVERIFY(rect != 0); + QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect); + + QDeclarativeRectangle *innerRect = qobject_cast<QDeclarativeRectangle*>(rect->findChild<QDeclarativeRectangle*>("MyRect")); + QVERIFY(innerRect != 0); + mirrorAnchors(innerRect); + + rectPrivate->setState("right"); + QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150)); + + rectPrivate->setState(""); + QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(5)); + + delete rect; +} + +void tst_qdeclarativestates::anchorChangesRTL3() +{ + QDeclarativeEngine engine; + + QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorChanges3.qml"); + QDeclarativeRectangle *rect = qobject_cast<QDeclarativeRectangle*>(rectComponent.create()); + QVERIFY(rect != 0); + QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect); + + QDeclarativeRectangle *innerRect = qobject_cast<QDeclarativeRectangle*>(rect->findChild<QDeclarativeRectangle*>("MyRect")); + QVERIFY(innerRect != 0); + mirrorAnchors(innerRect); + + QDeclarativeItem *leftGuideline = qobject_cast<QDeclarativeItem*>(rect->findChild<QDeclarativeItem*>("LeftGuideline")); + QVERIFY(leftGuideline != 0); + + QDeclarativeItem *bottomGuideline = qobject_cast<QDeclarativeItem*>(rect->findChild<QDeclarativeItem*>("BottomGuideline")); + QVERIFY(bottomGuideline != 0); + + QDeclarativeListReference list(rect, "states"); + QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0)); + QVERIFY(state != 0); + + qmlExecuteDeferred(state); + QDeclarativeAnchorChanges *aChanges = qobject_cast<QDeclarativeAnchorChanges*>(state->operationAt(0)); + QVERIFY(aChanges != 0); + + rectPrivate->setState("reanchored"); + QCOMPARE(aChanges->object(), qobject_cast<QDeclarativeItem*>(innerRect)); + QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->left().item, QDeclarativeItemPrivate::get(leftGuideline)->left().item); + QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QDeclarativeItemPrivate::get(leftGuideline)->left().anchorLine); + QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item); + QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine); + QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item); + QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine); + QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->bottom().item, QDeclarativeItemPrivate::get(bottomGuideline)->bottom().item); + QCOMPARE(QDeclarativeItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QDeclarativeItemPrivate::get(bottomGuideline)->bottom().anchorLine); + + QCOMPARE(innerRect->x(), offsetRTL(leftGuideline, innerRect) - qreal(10)); + QCOMPARE(innerRect->y(), qreal(0)); + // between left side of parent and leftGuideline.x: 10, which has width 0 + QCOMPARE(innerRect->width(), qreal(10)); + QCOMPARE(innerRect->height(), qreal(150)); + + rectPrivate->setState(""); + QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(0)); + QCOMPARE(innerRect->y(), qreal(10)); + // between right side of parent and left side of rightGuideline.x: 150, which has width 0 + QCOMPARE(innerRect->width(), qreal(50)); + QCOMPARE(innerRect->height(), qreal(190)); + + delete rect; +} + //QTBUG-9609 void tst_qdeclarativestates::anchorChangesCrash() { diff --git a/tests/auto/declarative/qdeclarativetext/data/qtbug_14734.qml b/tests/auto/declarative/qdeclarativetext/data/qtbug_14734.qml new file mode 100644 index 0000000..bd07d66 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetext/data/qtbug_14734.qml @@ -0,0 +1,10 @@ +import QtQuick 1.0 + +Rectangle { + width: 640 + height: 480 + + Text { + text: "Ã " + } +} diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index a3bba3b..8841aa3 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -109,6 +109,7 @@ private slots: void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); + void qtbug_14734(); private: QStringList standard; QStringList richText; @@ -517,20 +518,112 @@ void tst_qdeclarativetext::horizontalAlignment_RightToLeft() QDeclarativeTextPrivate *textPrivate = QDeclarativeTextPrivate::get(text); QVERIFY(textPrivate != 0); - QVERIFY(textPrivate->layout.lineAt(0).x() > canvas->width()/2); + // implicit alignment should follow the reading direction of RTL text + QCOMPARE(text->hAlign(), QDeclarativeText::AlignRight); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2); + + // explicitly left aligned text + text->setHAlign(QDeclarativeText::AlignLeft); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignLeft); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2); + + // explicitly right aligned text + text->setHAlign(QDeclarativeText::AlignRight); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignRight); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2); - // "Right" aligned + // change to rich text + QString textString = text->text(); + text->setText(QString("<i>") + textString + QString("</i>")); + text->setTextFormat(QDeclarativeText::RichText); + text->resetHAlign(); + + // implicitly aligned rich text should follow the reading direction of text + QCOMPARE(text->hAlign(), QDeclarativeText::AlignRight); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft); + + // explicitly left aligned rich text + text->setHAlign(QDeclarativeText::AlignLeft); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignLeft); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignRight); + + // explicitly right aligned rich text text->setHAlign(QDeclarativeText::AlignRight); QCOMPARE(text->hAlign(), QDeclarativeText::AlignRight); - QVERIFY(textPrivate->layout.lineAt(0).x() < canvas->width()/2); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft); + + text->setText(textString); + text->setTextFormat(QDeclarativeText::PlainText); - // Center aligned + // explicitly center aligned text->setHAlign(QDeclarativeText::AlignHCenter); QCOMPARE(text->hAlign(), QDeclarativeText::AlignHCenter); - QVERIFY(textPrivate->layout.lineAt(0).x() < canvas->width()/2); - QVERIFY(textPrivate->layout.lineAt(0).x() + textPrivate->layout.lineAt(0).width() > canvas->width()/2); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().right() > canvas->width()/2); + + // reseted alignment should go back to following the text reading direction + text->resetHAlign(); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignRight); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2); + + // mirror the text item + QDeclarativeItemPrivate::get(text)->setLayoutMirror(true); + + // mirrored implicit alignment should continue to follow the reading direction of the text + QCOMPARE(text->hAlign(), QDeclarativeText::AlignRight); + QCOMPARE(text->effectiveHAlign(), QDeclarativeText::AlignRight); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2); + + // mirrored explicitly right aligned behaves as left aligned + text->setHAlign(QDeclarativeText::AlignRight); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignRight); + QCOMPARE(text->effectiveHAlign(), QDeclarativeText::AlignLeft); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2); + + // mirrored explicitly left aligned behaves as right aligned + text->setHAlign(QDeclarativeText::AlignLeft); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignLeft); + QCOMPARE(text->effectiveHAlign(), QDeclarativeText::AlignRight); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2); + + // disable mirroring + QDeclarativeItemPrivate::get(text)->setLayoutMirror(false); + text->resetHAlign(); + + // English text should be implicitly left aligned + text->setText("Hello world!"); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignLeft); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2); + +#ifndef Q_OS_MAC // QTBUG-18040 + // empty text with implicit alignment follows the system locale-based + // keyboard input direction from QApplication::keyboardInputDirection + text->setText(""); + QCOMPARE(text->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ? + QDeclarativeText::AlignLeft : QDeclarativeText::AlignRight); + text->setHAlign(QDeclarativeText::AlignRight); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignRight); +#endif delete canvas; + +#ifndef Q_OS_MAC // QTBUG-18040 + // alignment of Text with no text set to it + QString componentStr = "import QtQuick 1.0\nText {}"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeText *textObject = qobject_cast<QDeclarativeText*>(textComponent.create()); + QCOMPARE(textObject->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ? + QDeclarativeText::AlignLeft : QDeclarativeText::AlignRight); + delete textObject; +#endif } void tst_qdeclarativetext::verticalAlignment() @@ -1204,6 +1297,19 @@ void tst_qdeclarativetext::testQtQuick11Attributes_data() << ""; } +void tst_qdeclarativetext::qtbug_14734() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/qtbug_14734.qml"); + QVERIFY(canvas); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + delete canvas; +} + QTEST_MAIN(tst_qdeclarativetext) #include "tst_qdeclarativetext.moc" diff --git a/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_false_words.qml b/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_false_words.qml new file mode 100644 index 0000000..22a9871 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_false_words.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +TextEdit { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: false +} diff --git a/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_true_words.qml b/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_true_words.qml new file mode 100644 index 0000000..d61da46 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_true_words.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +TextEdit { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true +} diff --git a/tests/auto/declarative/qdeclarativetextedit/data/navigation.qml b/tests/auto/declarative/qdeclarativetextedit/data/navigation.qml index 9ee8a93..0e1caf6 100644 --- a/tests/auto/declarative/qdeclarativetextedit/data/navigation.qml +++ b/tests/auto/declarative/qdeclarativetextedit/data/navigation.qml @@ -15,6 +15,7 @@ Rectangle { KeyNavigation.right: lastItem KeyNavigation.up: firstItem KeyNavigation.down: lastItem + text: "a" } Item { id: lastItem diff --git a/tests/auto/declarative/qdeclarativetextedit/data/positionAt.qml b/tests/auto/declarative/qdeclarativetextedit/data/positionAt.qml new file mode 100644 index 0000000..e010135 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/positionAt.qml @@ -0,0 +1,9 @@ +import QtQuick 1.0 + +TextEdit { + focus: true + objectName: "myInput" + width: 50 + height: 25 + text: "This is\n a long piece of text" +} diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 2c3ec7c..f62c2c5 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -110,6 +110,9 @@ private slots: void persistentSelection(); void focusOnPress(); void selection(); + void isRightToLeft_data(); + void isRightToLeft(); + void keySelection(); void moveCursorSelection_data(); void moveCursorSelection(); void moveCursorSelectionSequence_data(); @@ -121,6 +124,8 @@ private slots: void dragMouseSelection(); void inputMethodHints(); + void positionAt(); + void cursorDelegate(); void cursorVisible(); void delegateLoading_data(); @@ -128,6 +133,8 @@ private slots: void navigation(); void readOnly(); void copyAndPaste(); + void canPaste(); + void canPasteEmpty(); void textInput(); void openInputPanelOnClick(); void openInputPanelOnFocus(); @@ -140,9 +147,10 @@ private slots: void preeditMicroFocus(); void inputContextMouseHandler(); + void inputMethodComposing(); private: - void simulateKey(QDeclarativeView *, int key); + void simulateKey(QDeclarativeView *, int key, Qt::KeyboardModifiers modifiers = 0); QDeclarativeView *createView(const QString &filename); QStringList standard; @@ -440,21 +448,109 @@ void tst_qdeclarativetextedit::hAlign_RightToLeft() QVERIFY(textEdit != 0); canvas->show(); + // implicit alignment should follow the reading direction of text + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignRight); QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); - // "Right" align + // explicitly left aligned + textEdit->setHAlign(QDeclarativeTextEdit::AlignLeft); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignLeft); + QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2); + + // explicitly right aligned textEdit->setHAlign(QDeclarativeTextEdit::AlignRight); QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignRight); + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + + QString textString = textEdit->text(); + textEdit->setText(QString("<i>") + textString + QString("</i>")); + textEdit->resetHAlign(); + + // implicitly aligned rich text should follow the reading direction of RTL text + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignRight); + QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign()); + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + + // explicitly left aligned rich text + textEdit->setHAlign(QDeclarativeTextEdit::AlignLeft); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignLeft); + QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign()); QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2); - // Center align - // Note that position 0 is on the right-hand side + // explicitly right aligned rich text + textEdit->setHAlign(QDeclarativeTextEdit::AlignRight); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignRight); + QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign()); + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + + textEdit->setText(textString); + + // explicitly center aligned textEdit->setHAlign(QDeclarativeTextEdit::AlignHCenter); QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignHCenter); - QVERIFY(textEdit->positionToRectangle(0).x() - textEdit->width() < canvas->width()/2); QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + // reseted alignment should go back to following the text reading direction + textEdit->resetHAlign(); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignRight); + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + + // mirror the text item + QDeclarativeItemPrivate::get(textEdit)->setLayoutMirror(true); + + // mirrored implicit alignment should continue to follow the reading direction of the text + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignRight); + QCOMPARE(textEdit->effectiveHAlign(), QDeclarativeTextEdit::AlignRight); + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + + // mirrored explicitly right aligned behaves as left aligned + textEdit->setHAlign(QDeclarativeTextEdit::AlignRight); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignRight); + QCOMPARE(textEdit->effectiveHAlign(), QDeclarativeTextEdit::AlignLeft); + QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2); + + // mirrored explicitly left aligned behaves as right aligned + textEdit->setHAlign(QDeclarativeTextEdit::AlignLeft); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignLeft); + QCOMPARE(textEdit->effectiveHAlign(), QDeclarativeTextEdit::AlignRight); + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + + // disable mirroring + QDeclarativeItemPrivate::get(textEdit)->setLayoutMirror(false); + textEdit->resetHAlign(); + + // English text should be implicitly left aligned + textEdit->setText("Hello world!"); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignLeft); + QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2); + +#ifndef Q_OS_MAC // QTBUG-18040 + // empty text with implicit alignment follows the system locale-based + // keyboard input direction from QApplication::keyboardInputDirection + textEdit->setText(""); + QCOMPARE(textEdit->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ? + QDeclarativeTextEdit::AlignLeft : QDeclarativeTextEdit::AlignRight); + if (QApplication::keyboardInputDirection() == Qt::LeftToRight) + QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2); + else + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + textEdit->setHAlign(QDeclarativeTextEdit::AlignRight); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignRight); + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); +#endif + delete canvas; + +#ifndef Q_OS_MAC // QTBUG-18040 + // alignment of TextEdit with no text set to it + QString componentStr = "import QtQuick 1.0\nTextEdit {}"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeTextEdit *textObject = qobject_cast<QDeclarativeTextEdit*>(textComponent.create()); + QCOMPARE(textObject->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ? + QDeclarativeTextEdit::AlignLeft : QDeclarativeTextEdit::AlignRight); + delete textObject; +#endif } void tst_qdeclarativetextedit::vAlign() @@ -757,6 +853,113 @@ void tst_qdeclarativetextedit::selection() QVERIFY(textEditObject->selectedText().isNull()); } +void tst_qdeclarativetextedit::isRightToLeft_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<bool>("emptyString"); + QTest::addColumn<bool>("firstCharacter"); + QTest::addColumn<bool>("lastCharacter"); + QTest::addColumn<bool>("middleCharacter"); + QTest::addColumn<bool>("startString"); + QTest::addColumn<bool>("midString"); + QTest::addColumn<bool>("endString"); + + const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647}; + QTest::newRow("Empty") << "" << false << false << false << false << false << false << false; + QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false; + QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false; + QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true; + QTest::newRow("Bidi RTL + LTR + RTL") << QString::fromUtf16(arabic_str, 11) + QString("Hello world") + QString::fromUtf16(arabic_str, 11) << false << true << true << false << true << true << true; + QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false; +} + +void tst_qdeclarativetextedit::isRightToLeft() +{ + QFETCH(QString, text); + QFETCH(bool, emptyString); + QFETCH(bool, firstCharacter); + QFETCH(bool, lastCharacter); + QFETCH(bool, middleCharacter); + QFETCH(bool, startString); + QFETCH(bool, midString); + QFETCH(bool, endString); + + QDeclarativeTextEdit textEdit; + textEdit.setText(text); + + // first test that the right string is delivered to the QString::isRightToLeft() + QCOMPARE(textEdit.isRightToLeft(0,0), text.mid(0,0).isRightToLeft()); + QCOMPARE(textEdit.isRightToLeft(0,1), text.mid(0,1).isRightToLeft()); + QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft()); + QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft()); + QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft()); + QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft()); + if (text.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start."); + QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft()); + + // then test that the feature actually works + QCOMPARE(textEdit.isRightToLeft(0,0), emptyString); + QCOMPARE(textEdit.isRightToLeft(0,1), firstCharacter); + QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), lastCharacter); + QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter); + QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), startString); + QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), midString); + if (text.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start."); + QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), endString); +} + +void tst_qdeclarativetextedit::keySelection() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml"); + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + canvas->setFocus(); + + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeTextEdit *input = qobject_cast<QDeclarativeTextEdit *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput"))); + + QVERIFY(input != 0); + QTRY_VERIFY(input->hasActiveFocus() == true); + + QSignalSpy spy(input, SIGNAL(selectionChanged())); + + simulateKey(canvas, Qt::Key_Right, Qt::ShiftModifier); + QVERIFY(input->hasActiveFocus() == true); + QCOMPARE(input->selectedText(), QString("a")); + QCOMPARE(spy.count(), 1); + simulateKey(canvas, Qt::Key_Right); + QVERIFY(input->hasActiveFocus() == true); + QCOMPARE(input->selectedText(), QString()); + QCOMPARE(spy.count(), 2); + simulateKey(canvas, Qt::Key_Right); + QVERIFY(input->hasActiveFocus() == false); + QCOMPARE(input->selectedText(), QString()); + QCOMPARE(spy.count(), 2); + + simulateKey(canvas, Qt::Key_Left); + QVERIFY(input->hasActiveFocus() == true); + QCOMPARE(spy.count(), 2); + simulateKey(canvas, Qt::Key_Left, Qt::ShiftModifier); + QVERIFY(input->hasActiveFocus() == true); + QCOMPARE(input->selectedText(), QString("a")); + QCOMPARE(spy.count(), 3); + simulateKey(canvas, Qt::Key_Left); + QVERIFY(input->hasActiveFocus() == true); + QCOMPARE(input->selectedText(), QString()); + QCOMPARE(spy.count(), 4); + simulateKey(canvas, Qt::Key_Left); + QVERIFY(input->hasActiveFocus() == false); + QCOMPARE(input->selectedText(), QString()); + QCOMPARE(spy.count(), 4); + + delete canvas; +} + void tst_qdeclarativetextedit::moveCursorSelection_data() { QTest::addColumn<QString>("testStr"); @@ -1102,6 +1305,8 @@ void tst_qdeclarativetextedit::mouseSelection_data() QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << true; QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << false; QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << false; + QTest::newRow("on word selection") << SRCDIR "/data/mouseselection_true_words.qml" << true; + QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << false; } void tst_qdeclarativetextedit::mouseSelection() @@ -1250,6 +1455,56 @@ void tst_qdeclarativetextedit::inputMethodHints() delete canvas; } +void tst_qdeclarativetextedit::positionAt() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml"); + QVERIFY(canvas->rootObject() != 0); + canvas->show(); + canvas->setFocus(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + + QDeclarativeTextEdit *texteditObject = qobject_cast<QDeclarativeTextEdit *>(canvas->rootObject()); + QVERIFY(texteditObject != 0); + + QFontMetrics fm(texteditObject->font()); + const int y0 = fm.height() / 2; + const int y1 = fm.height() * 3 / 2; + + int pos = texteditObject->positionAt(texteditObject->width()/2, y0); + int diff = abs(int(fm.width(texteditObject->text().left(pos))-texteditObject->width()/2)); + + // some tollerance for different fonts. +#ifdef Q_OS_LINUX + QVERIFY(diff < 2); +#else + QVERIFY(diff < 5); +#endif + + const qreal x0 = texteditObject->positionToRectangle(pos).x(); + const qreal x1 = texteditObject->positionToRectangle(pos + 1).x(); + + QString preeditText = texteditObject->text().mid(0, pos); + texteditObject->setText(texteditObject->text().mid(pos)); + texteditObject->setCursorPosition(0); + + QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>()); + QApplication::sendEvent(canvas, &inputEvent); + + // Check all points within the preedit text return the same position. + QCOMPARE(texteditObject->positionAt(0, y0), 0); + QCOMPARE(texteditObject->positionAt(x0 / 2, y0), 0); + QCOMPARE(texteditObject->positionAt(x0, y0), 0); + + // Verify positioning returns to normal after the preedit text. + QCOMPARE(texteditObject->positionAt(x1, y0), 1); + QCOMPARE(texteditObject->positionToRectangle(1).x(), x1); + + QVERIFY(texteditObject->positionAt(x0 / 2, y1) > 0); + + delete canvas; +} + void tst_qdeclarativetextedit::cursorDelegate() { QDeclarativeView* view = createView(SRCDIR "/data/cursorTest.qml"); @@ -1425,6 +1680,8 @@ void tst_qdeclarativetextedit::navigation() simulateKey(canvas, Qt::Key_Right); QVERIFY(input->hasActiveFocus() == true); simulateKey(canvas, Qt::Key_Right); + QVERIFY(input->hasActiveFocus() == true); + simulateKey(canvas, Qt::Key_Right); QVERIFY(input->hasActiveFocus() == false); simulateKey(canvas, Qt::Key_Left); QVERIFY(input->hasActiveFocus() == true); @@ -1492,6 +1749,42 @@ void tst_qdeclarativetextedit::copyAndPaste() { #endif } +void tst_qdeclarativetextedit::canPaste() { +#ifndef QT_NO_CLIPBOARD + + QApplication::clipboard()->setText("Some text"); + + QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello world!\" }"; + QDeclarativeComponent textEditComponent(&engine); + textEditComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextEdit *textEdit = qobject_cast<QDeclarativeTextEdit*>(textEditComponent.create()); + QVERIFY(textEdit != 0); + + // check initial value - QTBUG-17765 + QTextControl tc; + QCOMPARE(textEdit->canPaste(), tc.canPaste()); + +#endif +} + +void tst_qdeclarativetextedit::canPasteEmpty() { +#ifndef QT_NO_CLIPBOARD + + QApplication::clipboard()->clear(); + + QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello world!\" }"; + QDeclarativeComponent textEditComponent(&engine); + textEditComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextEdit *textEdit = qobject_cast<QDeclarativeTextEdit*>(textEditComponent.create()); + QVERIFY(textEdit != 0); + + // check initial value - QTBUG-17765 + QTextControl tc; + QCOMPARE(textEdit->canPaste(), tc.canPaste()); + +#endif +} + void tst_qdeclarativetextedit::readOnly() { QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml"); @@ -1516,10 +1809,10 @@ void tst_qdeclarativetextedit::readOnly() delete canvas; } -void tst_qdeclarativetextedit::simulateKey(QDeclarativeView *view, int key) +void tst_qdeclarativetextedit::simulateKey(QDeclarativeView *view, int key, Qt::KeyboardModifiers modifiers) { - QKeyEvent press(QKeyEvent::KeyPress, key, 0); - QKeyEvent release(QKeyEvent::KeyRelease, key, 0); + QKeyEvent press(QKeyEvent::KeyPress, key, modifiers); + QKeyEvent release(QKeyEvent::KeyRelease, key, modifiers); QApplication::sendEvent(view, &press); QApplication::sendEvent(view, &release); @@ -2079,6 +2372,43 @@ void tst_qdeclarativetextedit::inputContextMouseHandler() ic.eventType = QEvent::None; } +void tst_qdeclarativetextedit::inputMethodComposing() +{ + QString text = "supercalifragisiticexpialidocious!"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextEdit edit; + edit.setWidth(200); + edit.setText(text.mid(0, 12)); + edit.setCursorPosition(12); + edit.setPos(0, 0); + edit.setFocus(true); + scene.addItem(&edit); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + + QSignalSpy spy(&edit, SIGNAL(inputMethodComposingChanged())); + + QCOMPARE(edit.isInputMethodComposing(), false); + + ic.sendEvent(QInputMethodEvent(text.mid(3), QList<QInputMethodEvent::Attribute>())); + QCOMPARE(edit.isInputMethodComposing(), true); + QCOMPARE(spy.count(), 1); + + ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>())); + QCOMPARE(edit.isInputMethodComposing(), true); + QCOMPARE(spy.count(), 1); + + ic.sendEvent(QInputMethodEvent()); + QCOMPARE(edit.isInputMethodComposing(), false); + QCOMPARE(spy.count(), 2); +} + QTEST_MAIN(tst_qdeclarativetextedit) #include "tst_qdeclarativetextedit.moc" diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 49a05a3..45f38a4 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -89,6 +89,8 @@ private slots: void font(); void color(); void selection(); + void isRightToLeft_data(); + void isRightToLeft(); void moveCursorSelection_data(); void moveCursorSelection(); void moveCursorSelectionSequence_data(); @@ -111,8 +113,12 @@ private slots: void passwordCharacter(); void cursorDelegate(); void cursorVisible(); + void cursorRectangle(); void navigation(); + void navigation_RTL(); void copyAndPaste(); + void canPasteEmpty(); + void canPaste(); void readOnly(); void openInputPanelOnClick(); @@ -128,6 +134,7 @@ private slots: void preeditAutoScroll(); void preeditMicroFocus(); void inputContextMouseHandler(); + void inputMethodComposing(); private: void simulateKey(QDeclarativeView *, int key); @@ -143,7 +150,8 @@ tst_qdeclarativetextinput::tst_qdeclarativetextinput() standard << "the quick brown fox jumped over the lazy dog" << "It's supercalifragisiticexpialidocious!" << "Hello, world!" - << "!dlrow ,olleH"; + << "!dlrow ,olleH" + << " spacey text "; colorStrings << "aliceblue" << "antiquewhite" @@ -434,6 +442,63 @@ void tst_qdeclarativetextinput::selection() delete textinputObject; } +void tst_qdeclarativetextinput::isRightToLeft_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<bool>("emptyString"); + QTest::addColumn<bool>("firstCharacter"); + QTest::addColumn<bool>("lastCharacter"); + QTest::addColumn<bool>("middleCharacter"); + QTest::addColumn<bool>("startString"); + QTest::addColumn<bool>("midString"); + QTest::addColumn<bool>("endString"); + + const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647}; + QTest::newRow("Empty") << "" << false << false << false << false << false << false << false; + QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false; + QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false; + QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true; + QTest::newRow("Bidi RTL + LTR + RTL") << QString::fromUtf16(arabic_str, 11) + QString("Hello world") + QString::fromUtf16(arabic_str, 11) << false << true << true << false << true << true << true; + QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false; +} + +void tst_qdeclarativetextinput::isRightToLeft() +{ + QFETCH(QString, text); + QFETCH(bool, emptyString); + QFETCH(bool, firstCharacter); + QFETCH(bool, lastCharacter); + QFETCH(bool, middleCharacter); + QFETCH(bool, startString); + QFETCH(bool, midString); + QFETCH(bool, endString); + + QDeclarativeTextInput textInput; + textInput.setText(text); + + // first test that the right string is delivered to the QString::isRightToLeft() + QCOMPARE(textInput.isRightToLeft(0,0), text.mid(0,0).isRightToLeft()); + QCOMPARE(textInput.isRightToLeft(0,1), text.mid(0,1).isRightToLeft()); + QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft()); + QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft()); + QCOMPARE(textInput.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft()); + QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft()); + if (text.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start."); + QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft()); + + // then test that the feature actually works + QCOMPARE(textInput.isRightToLeft(0,0), emptyString); + QCOMPARE(textInput.isRightToLeft(0,1), firstCharacter); + QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), lastCharacter); + QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter); + QCOMPARE(textInput.isRightToLeft(0,text.count()/4), startString); + QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), midString); + if (text.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start."); + QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), endString); +} + void tst_qdeclarativetextinput::moveCursorSelection_data() { QTest::addColumn<QString>("testStr"); @@ -444,6 +509,9 @@ void tst_qdeclarativetextinput::moveCursorSelection_data() QTest::addColumn<int>("selectionEnd"); QTest::addColumn<bool>("reversible"); + // () contains the text selected by the cursor. + // <> contains the actual selection. + QTest::newRow("(t)he|characters") << standard[0] << 0 << 1 << QDeclarativeTextInput::SelectCharacters << 0 << 1 << true; QTest::newRow("do(g)|characters") @@ -581,6 +649,24 @@ void tst_qdeclarativetextinput::moveCursorSelection_data() << standard[3] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << true; QTest::newRow("!<()>dlrow|words") << standard[3] << 1 << 1 << QDeclarativeTextInput::SelectWords << 1 << 1 << true; + + QTest::newRow(" <s(pac)ey> text |words") + << standard[4] << 1 << 4 << QDeclarativeTextInput::SelectWords << 1 << 7 << true; + QTest::newRow(" spacey <t(ex)t> |words") + << standard[4] << 11 << 13 << QDeclarativeTextInput::SelectWords << 10 << 14 << false; // Should be reversible. QTBUG-11365 + QTest::newRow("<( )>spacey text |words|ltr") + << standard[4] << 0 << 1 << QDeclarativeTextInput::SelectWords << 0 << 1 << false; + QTest::newRow("<( )spacey> text |words|rtl") + << standard[4] << 1 << 0 << QDeclarativeTextInput::SelectWords << 0 << 7 << false; + QTest::newRow("spacey <text( )>|words|ltr") + << standard[4] << 14 << 15 << QDeclarativeTextInput::SelectWords << 10 << 15 << false; +// QTBUG-11365 +// QTest::newRow("spacey text<( )>|words|rtl") +// << standard[4] << 15 << 14 << QDeclarativeTextInput::SelectWords << 14 << 15 << false; + QTest::newRow("<()> spacey text |words") + << standard[4] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << false; + QTest::newRow(" spacey text <()>|words") + << standard[4] << 15 << 15 << QDeclarativeTextInput::SelectWords << 15 << 15 << false; } void tst_qdeclarativetextinput::moveCursorSelection() @@ -627,6 +713,11 @@ void tst_qdeclarativetextinput::moveCursorSelectionSequence_data() QTest::addColumn<int>("selection2Start"); QTest::addColumn<int>("selection2End"); + // () contains the text selected by the cursor. + // <> contains the actual selection. + // ^ is the revised cursor position. + // {} contains the revised selection. + QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr") << standard[0] << 9 << 13 << 17 @@ -739,6 +830,50 @@ void tst_qdeclarativetextinput::moveCursorSelectionSequence_data() << 11 << 9 << 5 << 8 << 13 << 1 << 13; + + QTest::newRow("{<(^} sp)acey> text |ltr") + << standard[4] + << 0 << 3 << 0 + << 0 << 7 + << 0 << 0; + QTest::newRow("{<( ^}sp)acey> text |ltr") + << standard[4] + << 0 << 3 << 1 + << 0 << 7 + << 0 << 1; + QTest::newRow("<( {s^p)acey>} text |rtl") + << standard[4] + << 3 << 0 << 2 + << 0 << 7 + << 1 << 7; + QTest::newRow("<( {^sp)acey>} text |rtl") + << standard[4] + << 3 << 0 << 1 + << 0 << 7 + << 1 << 7; + + QTest::newRow(" spacey <te(xt {^)>}|rtl") + << standard[4] + << 15 << 12 << 15 + << 10 << 15 + << 15 << 15; +// QTBUG-11365 +// QTest::newRow(" spacey <te(xt{^ )>}|rtl") +// << standard[4] +// << 15 << 12 << 14 +// << 10 << 15 +// << 14 << 15; + QTest::newRow(" spacey {<te(x^t} )>|ltr") + << standard[4] + << 12 << 15 << 13 + << 10 << 15 + << 10 << 14; +// QTBUG-11365 +// QTest::newRow(" spacey {<te(xt^} )>|ltr") +// << standard[4] +// << 12 << 15 << 14 +// << 10 << 15 +// << 10 << 14; } void tst_qdeclarativetextinput::moveCursorSelectionSequence() @@ -916,18 +1051,93 @@ void tst_qdeclarativetextinput::horizontalAlignment_RightToLeft() QVERIFY(textInputPrivate != 0); QVERIFY(-textInputPrivate->hscroll > canvas->width()/2); - // "Right" Align - textInput->setHAlign(QDeclarativeTextInput::AlignRight); + // implicit alignment should follow the reading direction of RTL text QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignRight); + QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); + QVERIFY(-textInputPrivate->hscroll > canvas->width()/2); + + // explicitly left aligned + textInput->setHAlign(QDeclarativeTextInput::AlignLeft); + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignLeft); + QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); QVERIFY(-textInputPrivate->hscroll < canvas->width()/2); - // Center Align + // explicitly right aligned + textInput->setHAlign(QDeclarativeTextInput::AlignRight); + QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignRight); + QVERIFY(-textInputPrivate->hscroll > canvas->width()/2); + + // explicitly center aligned textInput->setHAlign(QDeclarativeTextInput::AlignHCenter); + QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignHCenter); QVERIFY(-textInputPrivate->hscroll < canvas->width()/2); QVERIFY(-textInputPrivate->hscroll + textInputPrivate->width() > canvas->width()/2); + // reseted alignment should go back to following the text reading direction + textInput->resetHAlign(); + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignRight); + QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); + QVERIFY(-textInputPrivate->hscroll > canvas->width()/2); + + // mirror the text item + QDeclarativeItemPrivate::get(textInput)->setLayoutMirror(true); + + // mirrored implicit alignment should continue to follow the reading direction of the text + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignRight); + QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); + QVERIFY(-textInputPrivate->hscroll > canvas->width()/2); + + // explicitly right aligned behaves as left aligned + textInput->setHAlign(QDeclarativeTextInput::AlignRight); + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignRight); + QCOMPARE(textInput->effectiveHAlign(), QDeclarativeTextInput::AlignLeft); + QVERIFY(-textInputPrivate->hscroll < canvas->width()/2); + + // mirrored explicitly left aligned behaves as right aligned + textInput->setHAlign(QDeclarativeTextInput::AlignLeft); + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignLeft); + QCOMPARE(textInput->effectiveHAlign(), QDeclarativeTextInput::AlignRight); + QVERIFY(-textInputPrivate->hscroll > canvas->width()/2); + + // disable mirroring + QDeclarativeItemPrivate::get(textInput)->setLayoutMirror(false); + QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); + textInput->resetHAlign(); + + // English text should be implicitly left aligned + textInput->setText("Hello world!"); + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignLeft); + QVERIFY(-textInputPrivate->hscroll < canvas->width()/2); + +#ifndef Q_OS_MAC // QTBUG-18040 + // empty text with implicit alignment follows the system locale-based + // keyboard input direction from QApplication::keyboardInputDirection + textInput->setText(""); + QCOMPARE(textInput->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ? + QDeclarativeTextInput::AlignLeft : QDeclarativeTextInput::AlignRight); + if (QApplication::keyboardInputDirection() == Qt::LeftToRight) + QVERIFY(-textInputPrivate->hscroll < canvas->width()/2); + else + QVERIFY(-textInputPrivate->hscroll > canvas->width()/2); + textInput->setHAlign(QDeclarativeTextInput::AlignRight); + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignRight); + QVERIFY(-textInputPrivate->hscroll > canvas->width()/2); +#endif + delete canvas; + +#ifndef Q_OS_MAC // QTBUG-18040 + // alignment of TextInput with no text set to it + QString componentStr = "import QtQuick 1.0\nTextInput {}"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeTextInput *textObject = qobject_cast<QDeclarativeTextInput*>(textComponent.create()); + QCOMPARE(textObject->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ? + QDeclarativeTextInput::AlignLeft : QDeclarativeTextInput::AlignRight); + delete textObject; +#endif } void tst_qdeclarativetextinput::positionAt() @@ -955,6 +1165,10 @@ void tst_qdeclarativetextinput::positionAt() QVERIFY(diff < 5); #endif + int x = textinputObject->positionToRectangle(pos + 1).x() - 1; + QCOMPARE(textinputObject->positionAt(x, QDeclarativeTextInput::CursorBetweenCharacters), pos + 1); + QCOMPARE(textinputObject->positionAt(x, QDeclarativeTextInput::CursorOnCharacter), pos); + // Check without autoscroll... textinputObject->setAutoScroll(false); pos = textinputObject->positionAt(textinputObject->width()/2); @@ -967,6 +1181,29 @@ void tst_qdeclarativetextinput::positionAt() QVERIFY(diff < 5); #endif + x = textinputObject->positionToRectangle(pos + 1).x() - 1; + QCOMPARE(textinputObject->positionAt(x, QDeclarativeTextInput::CursorBetweenCharacters), pos + 1); + QCOMPARE(textinputObject->positionAt(x, QDeclarativeTextInput::CursorOnCharacter), pos); + + const qreal x0 = textinputObject->positionToRectangle(pos).x(); + const qreal x1 = textinputObject->positionToRectangle(pos + 1).x(); + + QString preeditText = textinputObject->text().mid(0, pos); + textinputObject->setText(textinputObject->text().mid(pos)); + textinputObject->setCursorPosition(0); + + QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>()); + QApplication::sendEvent(canvas, &inputEvent); + + // Check all points within the preedit text return the same position. + QCOMPARE(textinputObject->positionAt(0), 0); + QCOMPARE(textinputObject->positionAt(x0 / 2), 0); + QCOMPARE(textinputObject->positionAt(x0), 0); + + // Verify positioning returns to normal after the preedit text. + QCOMPARE(textinputObject->positionAt(x1), 1); + QCOMPARE(textinputObject->positionToRectangle(1).x(), x1); + delete canvas; } @@ -1145,6 +1382,24 @@ void tst_qdeclarativetextinput::inputMethods() QApplication::sendEvent(canvas, &event); QCOMPARE(input->text(), QString("My Hello world!")); + input->setCursorPosition(2); + event.setCommitString("Your", -2, 2); + QApplication::sendEvent(canvas, &event); + QCOMPARE(input->text(), QString("Your Hello world!")); + QCOMPARE(input->cursorPosition(), 4); + + input->setCursorPosition(7); + event.setCommitString("Goodbye", -2, 5); + QApplication::sendEvent(canvas, &event); + QCOMPARE(input->text(), QString("Your Goodbye world!")); + QCOMPARE(input->cursorPosition(), 12); + + input->setCursorPosition(8); + event.setCommitString("Our", -8, 4); + QApplication::sendEvent(canvas, &event); + QCOMPARE(input->text(), QString("Our Goodbye world!")); + QCOMPARE(input->cursorPosition(), 7); + delete canvas; } @@ -1194,6 +1449,45 @@ void tst_qdeclarativetextinput::navigation() delete canvas; } +void tst_qdeclarativetextinput::navigation_RTL() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml"); + canvas->show(); + canvas->setFocus(); + + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeTextInput *input = qobject_cast<QDeclarativeTextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput"))); + + QVERIFY(input != 0); + const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647}; + input->setText(QString::fromUtf16(arabic_str, 11)); + + input->setCursorPosition(0); + QTRY_VERIFY(input->hasActiveFocus() == true); + + // move off + simulateKey(canvas, Qt::Key_Right); + QVERIFY(input->hasActiveFocus() == false); + + // move back + simulateKey(canvas, Qt::Key_Left); + QVERIFY(input->hasActiveFocus() == true); + + input->setCursorPosition(input->text().length()); + QVERIFY(input->hasActiveFocus() == true); + + // move off + simulateKey(canvas, Qt::Key_Left); + QVERIFY(input->hasActiveFocus() == false); + + // move back + simulateKey(canvas, Qt::Key_Right); + QVERIFY(input->hasActiveFocus() == true); + + delete canvas; +} + void tst_qdeclarativetextinput::copyAndPaste() { #ifndef QT_NO_CLIPBOARD @@ -1273,6 +1567,42 @@ void tst_qdeclarativetextinput::copyAndPaste() { #endif } +void tst_qdeclarativetextinput::canPasteEmpty() { +#ifndef QT_NO_CLIPBOARD + + QApplication::clipboard()->clear(); + + QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }"; + QDeclarativeComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextInput *textInput = qobject_cast<QDeclarativeTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QLineControl lc; + bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0; + QCOMPARE(textInput->canPaste(), cp); + +#endif +} + +void tst_qdeclarativetextinput::canPaste() { +#ifndef QT_NO_CLIPBOARD + + QApplication::clipboard()->setText("Some text"); + + QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }"; + QDeclarativeComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextInput *textInput = qobject_cast<QDeclarativeTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QLineControl lc; + bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0; + QCOMPARE(textInput->canPaste(), cp); + +#endif +} + void tst_qdeclarativetextinput::passwordCharacter() { QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\"; font.family: \"Helvetica\"; echoMode: TextInput.Password }"; @@ -1386,6 +1716,45 @@ void tst_qdeclarativetextinput::cursorVisible() #endif } +void tst_qdeclarativetextinput::cursorRectangle() +{ + QString text = "Hello World!"; + + QDeclarativeTextInput input; + input.setText(text); + QFontMetricsF fm(input.font()); + input.setWidth(fm.width(text.mid(0, 5))); + + QRect r; + + for (int i = 0; i <= 5; ++i) { + input.setCursorPosition(i); + r = input.cursorRectangle(); + int textWidth = fm.width(text.mid(0, i)); + + QVERIFY(r.left() < textWidth); + QVERIFY(r.right() > textWidth); + QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r); + } + + // Check the cursor rectangle remains within the input bounding rect when auto scrolling. + QVERIFY(r.left() < input.boundingRect().width()); + QVERIFY(r.right() >= input.width()); + + for (int i = 6; i < text.length(); ++i) { + input.setCursorPosition(i); + QCOMPARE(r, input.cursorRectangle()); + QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r); + } + + for (int i = text.length() - 2; i >= 0; --i) { + input.setCursorPosition(i); + r = input.cursorRectangle(); + QVERIFY(r.right() >= 0); + QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r); + } +} + void tst_qdeclarativetextinput::readOnly() { QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml"); @@ -1460,13 +1829,23 @@ void tst_qdeclarativetextinput::echoMode() QCOMPARE(input->inputMethodHints(), ref); QCOMPARE(input->text(), initial); QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ")); + QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("QQQQQQQQ")); QTest::keyPress(canvas, Qt::Key_A);//Clearing previous entry is part of PasswordEchoOnEdit QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10); QCOMPARE(input->text(), QLatin1String("a")); QCOMPARE(input->displayText(), QLatin1String("a")); + QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("a")); input->setFocus(false); QVERIFY(input->hasActiveFocus() == false); QCOMPARE(input->displayText(), QLatin1String("Q")); + QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("Q")); + input->setFocus(true); + QInputMethodEvent inputEvent; + inputEvent.setCommitString(initial); + QApplication::sendEvent(canvas, &inputEvent); + QCOMPARE(input->text(), initial); + QCOMPARE(input->displayText(), initial); + QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial); delete canvas; } @@ -1840,7 +2219,8 @@ void tst_qdeclarativetextinput::preeditAutoScroll() MyInputContext ic; view.setInputContext(&ic); QDeclarativeTextInput input; - input.setWidth(QFontMetricsF(input.font()).width(committedText)); + QFontMetricsF fm(input.font()); + input.setWidth(fm.width(committedText)); input.setText(committedText); input.setPos(0, 0); input.setFocus(true); @@ -1853,7 +2233,7 @@ void tst_qdeclarativetextinput::preeditAutoScroll() // test the text is scrolled so the preedit is visible. ic.sendPreeditText(preeditText.mid(0, 3), 1); QVERIFY(input.positionAt(0) != 0); - QCOMPARE(input.positionAt(input.width()), 8); + QVERIFY(input.cursorRectangle().left() < input.boundingRect().width()); // test the text is scrolled back when the preedit is removed. ic.sendEvent(QInputMethodEvent()); @@ -1862,26 +2242,31 @@ void tst_qdeclarativetextinput::preeditAutoScroll() // test if the preedit is larger than the text input that the // character preceding the cursor is still visible. + qreal x = input.positionToRectangle(0).x(); for (int i = 0; i < 3; ++i) { ic.sendPreeditText(preeditText, i + 1); - QCOMPARE(input.positionAt(0), 5 + i); + QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i))); + QVERIFY(input.positionToRectangle(0).x() < x); + x = input.positionToRectangle(0).x(); } for (int i = 1; i >= 0; --i) { ic.sendPreeditText(preeditText, i + 1); - QCOMPARE(input.positionAt(0), 5 + i); + QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i))); + QVERIFY(input.positionToRectangle(0).x() > x); + x = input.positionToRectangle(0).x(); } // Test incrementing the preedit cursor doesn't cause further // scrolling when right most text is visible. ic.sendPreeditText(preeditText, preeditText.length() - 3); - int position = input.positionAt(0); + x = input.positionToRectangle(0).x(); for (int i = 2; i >= 0; --i) { ic.sendPreeditText(preeditText, preeditText.length() - i); - QCOMPARE(input.positionAt(0), position); + QCOMPARE(input.positionToRectangle(0).x(), x); } for (int i = 1; i < 3; ++i) { ic.sendPreeditText(preeditText, preeditText.length() - i); - QCOMPARE(input.positionAt(0), position); + QCOMPARE(input.positionToRectangle(0).x(), x); } // Test disabling auto scroll. @@ -1903,6 +2288,7 @@ void tst_qdeclarativetextinput::preeditMicroFocus() view.setInputContext(&ic); QDeclarativeTextInput input; input.setPos(0, 0); + input.setAutoScroll(false); input.setFocus(true); scene.addItem(&input); view.show(); @@ -2066,6 +2452,43 @@ void tst_qdeclarativetextinput::inputContextMouseHandler() ic.eventType = QEvent::None; } +void tst_qdeclarativetextinput::inputMethodComposing() +{ + QString text = "supercalifragisiticexpialidocious!"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextInput input; + input.setWidth(200); + input.setText(text.mid(0, 12)); + input.setCursorPosition(12); + input.setPos(0, 0); + input.setFocus(true); + scene.addItem(&input); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + + QSignalSpy spy(&input, SIGNAL(inputMethodComposingChanged())); + + QCOMPARE(input.isInputMethodComposing(), false); + + ic.sendEvent(QInputMethodEvent(text.mid(3), QList<QInputMethodEvent::Attribute>())); + QCOMPARE(input.isInputMethodComposing(), true); + QCOMPARE(spy.count(), 1); + + ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>())); + QCOMPARE(input.isInputMethodComposing(), true); + QCOMPARE(spy.count(), 1); + + ic.sendEvent(QInputMethodEvent()); + QCOMPARE(input.isInputMethodComposing(), false); + QCOMPARE(spy.count(), 2); +} + QTEST_MAIN(tst_qdeclarativetextinput) #include "tst_qdeclarativetextinput.moc" diff --git a/tests/auto/declarative/qdeclarativewebview/data/basic.html b/tests/auto/declarative/qdeclarativewebview/data/basic.html deleted file mode 100644 index 22e3e24..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/basic.html +++ /dev/null @@ -1,17 +0,0 @@ -<html> -<head><title>Basic</title> -<link rel="icon" sizes="48x48" href="basic.png"> -<script type="text/javascript"> -<!-- -window.onload = function(){ window.status = "status here"; } -// --> -</script> -</head> -<body leftmargin="0" marginwidth="0"> -<table width="123"> -<tbody> -<tr><td>This is a basic test.</td></tr> -</tbody> -</table> -</body> -</html> diff --git a/tests/auto/declarative/qdeclarativewebview/data/basic.ico b/tests/auto/declarative/qdeclarativewebview/data/basic.ico Binary files differdeleted file mode 100644 index 8f3d05e..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/basic.ico +++ /dev/null diff --git a/tests/auto/declarative/qdeclarativewebview/data/basic.png b/tests/auto/declarative/qdeclarativewebview/data/basic.png Binary files differdeleted file mode 100644 index 35717cc..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/basic.png +++ /dev/null diff --git a/tests/auto/declarative/qdeclarativewebview/data/basic.qml b/tests/auto/declarative/qdeclarativewebview/data/basic.qml deleted file mode 100644 index 73330cd..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/basic.qml +++ /dev/null @@ -1,6 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -WebView { - url: "basic.html" -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/elements.html b/tests/auto/declarative/qdeclarativewebview/data/elements.html deleted file mode 100644 index 9236867..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/elements.html +++ /dev/null @@ -1,14 +0,0 @@ -<body leftmargin=0 topmargin=0> -<table width="300px" border=1 cellpadding=0 cellspacing=0> -<tr> -<td align=center width=25%%><p>A</p></td> -<td width=75% height=50px> - <table width=100% border=1 cellpadding=0 cellspacing=0> - <tr> - <td align=center width=50% height=50px><p>B</p></td> - <td align=center width=50% height=50px><p>C</p></td> - </tr> - </table> -</td> -</tr> -</table> diff --git a/tests/auto/declarative/qdeclarativewebview/data/elements.qml b/tests/auto/declarative/qdeclarativewebview/data/elements.qml deleted file mode 100644 index b86dd9d..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/elements.qml +++ /dev/null @@ -1,8 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -WebView { - url: "elements.html" - width: 310 - height: 100 -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/forward.html b/tests/auto/declarative/qdeclarativewebview/data/forward.html deleted file mode 100644 index 62ab62d..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/forward.html +++ /dev/null @@ -1,12 +0,0 @@ -<html> -<head><title>Forward</title> -<link rel="icon" sizes="32x32" href="forward.png"> -</head> -<body leftmargin="0" marginwidth="0"> -<table width="123"> -<tbody> -<tr><td>This is more.</td></tr> -</tbody> -</table> -</body> -</html> diff --git a/tests/auto/declarative/qdeclarativewebview/data/forward.png b/tests/auto/declarative/qdeclarativewebview/data/forward.png Binary files differdeleted file mode 100644 index a82533e..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/forward.png +++ /dev/null diff --git a/tests/auto/declarative/qdeclarativewebview/data/javaScript.html b/tests/auto/declarative/qdeclarativewebview/data/javaScript.html deleted file mode 100644 index 35270bc..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/javaScript.html +++ /dev/null @@ -1,11 +0,0 @@ -<html> -<head><title>JavaScript</title> -<link rel="icon" sizes="48x48" href="basic.png"> -<script type="text/javascript"> -<!-- -window.onload = function(){ window.status = "status here"; } -// --> -</script> -</head> -<body> -This is a JS test. diff --git a/tests/auto/declarative/qdeclarativewebview/data/javaScript.qml b/tests/auto/declarative/qdeclarativewebview/data/javaScript.qml deleted file mode 100644 index 527e3b9..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/javaScript.qml +++ /dev/null @@ -1,12 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -WebView { - url: "javaScript.html" - javaScriptWindowObjects: [ - QtObject { - property string qmlprop: "qmlvalue" - WebView.windowObjectName: "myjsname" - } - ] -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/loadError.qml b/tests/auto/declarative/qdeclarativewebview/data/loadError.qml deleted file mode 100644 index baab1a0..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/loadError.qml +++ /dev/null @@ -1,6 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -WebView { - url: "does-not-exist.html" -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/newwindows.html b/tests/auto/declarative/qdeclarativewebview/data/newwindows.html deleted file mode 100644 index dd541f9..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/newwindows.html +++ /dev/null @@ -1,16 +0,0 @@ -<html> -<head> -<script type="text/javascript"> -<!-- -function clickTheLink() -{ - var ev = document.createEvent('MouseEvents'); - ev.initEvent( "click", true, false ); - document.getElementById('thelink').dispatchEvent(ev); -} -// --> -</script> -</head> -<h1>Multiple windows...</h1> - -<a id=thelink target="_blank" href="newwindows.html">Popup!</a> diff --git a/tests/auto/declarative/qdeclarativewebview/data/newwindows.qml b/tests/auto/declarative/qdeclarativewebview/data/newwindows.qml deleted file mode 100644 index e66631d..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/newwindows.qml +++ /dev/null @@ -1,34 +0,0 @@ -// Demonstrates opening new WebViews from HTML - -import QtQuick 1.0 -import QtWebKit 1.0 - -Grid { - columns: 3 - id: pages - height: 300; width: 600 - property int total: 0 - - Component { - id: webViewPage - Rectangle { - width: webView.width - height: webView.height - border.color: "gray" - - WebView { - id: webView - width: 150 // force predictable for test - newWindowComponent: webViewPage - newWindowParent: pages - url: "newwindows.html" - Timer { - interval: 10; running: total<4; repeat: false; - onTriggered: { if (webView.status==WebView.Ready) { total++; webView.evaluateJavaScript("clickTheLink()") } } - } - } - } - } - - Loader { sourceComponent: webViewPage } -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/pixelCache.html b/tests/auto/declarative/qdeclarativewebview/data/pixelCache.html deleted file mode 100644 index 9412674..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/pixelCache.html +++ /dev/null @@ -1,10 +0,0 @@ -<html> -<body topmargin=0 leftmargin=0> -<table width=120 cellpadding=0 cellspacing=0> -<tr><td> -<h1>Pixel Cache</h1> -This test is for the pixel cache. Because this is a long document, -as it scrolls, more of the document will need to be rendered. -If the pixelCacheSize is small, the first parts of the document will -no longer be in the cache when it returns. -</table> diff --git a/tests/auto/declarative/qdeclarativewebview/data/pixelCache.qml b/tests/auto/declarative/qdeclarativewebview/data/pixelCache.qml deleted file mode 100644 index 08e4d65..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/pixelCache.qml +++ /dev/null @@ -1,6 +0,0 @@ -import Test 1.0 - -MyWebView { - anchors.fill: parent - url: "pixelCache.html" -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/propertychanges.qml b/tests/auto/declarative/qdeclarativewebview/data/propertychanges.qml deleted file mode 100644 index db06887..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/propertychanges.qml +++ /dev/null @@ -1,34 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -Item { - width: 240 - height: 160 - Grid { - anchors.fill: parent - objectName: "newWindowParent" - id: newWindowParent - } - - Row { - anchors.fill: parent - id: oldWindowParent - objectName: "oldWindowParent" - } - - Loader { - sourceComponent: webViewComponent - } - Component { - id: webViewComponent - WebView { - id: webView - objectName: "webView" - newWindowComponent: webViewComponent - newWindowParent: oldWindowParent - url: "basic.html" - renderingEnabled: true - pressGrabTime: 200 - } - } -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/sethtml.qml b/tests/auto/declarative/qdeclarativewebview/data/sethtml.qml deleted file mode 100644 index 7889704..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/sethtml.qml +++ /dev/null @@ -1,6 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -WebView { - html: "<p>This is a <b>string</b> set on the WebView" -} diff --git a/tests/auto/declarative/qdeclarativewebview/qdeclarativewebview.pro b/tests/auto/declarative/qdeclarativewebview/qdeclarativewebview.pro deleted file mode 100644 index af13d33..0000000 --- a/tests/auto/declarative/qdeclarativewebview/qdeclarativewebview.pro +++ /dev/null @@ -1,16 +0,0 @@ -load(qttest_p4) -contains(QT_CONFIG,declarative): QT += declarative -contains(QT_CONFIG,webkit): QT += webkit -macx:CONFIG -= app_bundle - -SOURCES += tst_qdeclarativewebview.cpp - -symbian: { - importFiles.files = data - importFiles.path = . - DEPLOYMENT += importFiles -} else { - DEFINES += SRCDIR=\\\"$$PWD\\\" -} - -CONFIG += parallel_test diff --git a/tests/auto/declarative/qdeclarativewebview/tst_qdeclarativewebview.cpp b/tests/auto/declarative/qdeclarativewebview/tst_qdeclarativewebview.cpp deleted file mode 100644 index 9f99e83..0000000 --- a/tests/auto/declarative/qdeclarativewebview/tst_qdeclarativewebview.cpp +++ /dev/null @@ -1,520 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <qtest.h> -#include <QtTest/QSignalSpy> -#include "../../../shared/util.h" -#include <QtDeclarative/qdeclarativeengine.h> -#include <QtDeclarative/qdeclarativecomponent.h> -#include <private/qdeclarativepositioners_p.h> -#include <QtWebKit/qwebpage.h> -#include <QtWebKit/qwebframe.h> -#include <QtCore/qdir.h> -#include <QtCore/qfile.h> -#include <QtGui/qpainter.h> - -#ifdef Q_OS_SYMBIAN -// In Symbian OS test data is located in applications private dir -#define SRCDIR "." -#endif - -class tst_qdeclarativewebview : public QObject -{ - Q_OBJECT -public: - tst_qdeclarativewebview() {} - -private slots: - void initTestCase(); - void basicProperties(); - void settings(); - void historyNav(); - void multipleWindows(); - void elementAreaAt(); - void loadError(); - void setHtml(); - void javaScript(); - void cleanupTestCase(); - //void pixelCache(); - void newWindowParent(); - void newWindowComponent(); - void renderingEnabled(); - void pressGrabTime(); - -private: - void checkNoErrors(const QDeclarativeComponent& component); - QDeclarativeEngine engine; - QString tmpDir() const - { - static QString tmpd = QDir::tempPath()+"/tst_qdeclarativewebview-" - + QDateTime::currentDateTime().toString(QLatin1String("yyyyMMddhhmmss")); - return tmpd; - } -}; - -void tst_qdeclarativewebview::initTestCase() -{ -} - -static QString strippedHtml(QString html) -{ - html.replace(QRegExp("\\s+"),""); - return html; -} - -static QString fileContents(const QString& filename) -{ - QFile file(filename); - file.open(QIODevice::ReadOnly); - return QString::fromUtf8(file.readAll()); -} - - -static void removeRecursive(const QString& dirname) -{ - QDir dir(dirname); - QFileInfoList entries(dir.entryInfoList(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot)); - for (int i = 0; i < entries.count(); ++i) - if (entries[i].isDir()) - removeRecursive(entries[i].filePath()); - else - dir.remove(entries[i].fileName()); - QDir().rmdir(dirname); -} - -void tst_qdeclarativewebview::cleanupTestCase() -{ - removeRecursive(tmpDir()); -} - -void tst_qdeclarativewebview::checkNoErrors(const QDeclarativeComponent& component) -{ - // Wait until the component is ready - QTRY_VERIFY(component.isReady() || component.isError()); - - if (component.isError()) { - QList<QDeclarativeError> errors = component.errors(); - for (int ii = 0; ii < errors.count(); ++ii) { - const QDeclarativeError &error = errors.at(ii); - QByteArray errorStr = QByteArray::number(error.line()) + ":" + - QByteArray::number(error.column()) + ":" + - error.description().toUtf8(); - qWarning() << errorStr; - } - } - QVERIFY(!component.isError()); -} - -void tst_qdeclarativewebview::basicProperties() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml")); - checkNoErrors(component); - QWebSettings::enablePersistentStorage(tmpDir()); - - QObject *wv = component.create(); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("title").toString(),QString("Basic")); - QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 48); - QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")),QPixmap(SRCDIR "/data/basic.png")); - QCOMPARE(wv->property("statusText").toString(),QString("status here")); - QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/basic.html")), strippedHtml(wv->property("html").toString())); - QCOMPARE(wv->property("preferredWidth").toInt(), 0); - QCOMPARE(wv->property("preferredHeight").toInt(), 0); - QCOMPARE(wv->property("url").toUrl(), QUrl::fromLocalFile(SRCDIR "/data/basic.html")); - QCOMPARE(wv->property("status").toInt(), 1 /*QDeclarativeWebView::Ready*/); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("back"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("back"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("forward"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("forward"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("stop"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("stop"))->isEnabled()); - - wv->setProperty("pixelCacheSize", 0); // mainly testing that it doesn't crash or anything! - QCOMPARE(wv->property("pixelCacheSize").toInt(),0); - qvariant_cast<QAction*>(wv->property("reload"))->trigger(); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); -} - -void tst_qdeclarativewebview::settings() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml")); - checkNoErrors(component); - QObject *wv = component.create(); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - - QObject *s = QDeclarativeProperty(wv,"settings").object(); - QVERIFY(s != 0); - - // merely tests that setting gets stored (in QWebSettings) - // behavioural tests are in WebKit. - for (int b=0; b<=1; ++b) { - bool on = !!b; - - s->setProperty("autoLoadImages", on); - s->setProperty("developerExtrasEnabled", on); - s->setProperty("javaEnabled", on); - s->setProperty("javascriptCanAccessClipboard", on); - s->setProperty("javascriptCanOpenWindows", on); - s->setProperty("javascriptEnabled", on); - s->setProperty("linksIncludedInFocusChain", on); - s->setProperty("localContentCanAccessRemoteUrls", on); - s->setProperty("localStorageDatabaseEnabled", on); - s->setProperty("offlineStorageDatabaseEnabled", on); - s->setProperty("offlineWebApplicationCacheEnabled", on); - s->setProperty("pluginsEnabled", on); - s->setProperty("printElementBackgrounds", on); - s->setProperty("privateBrowsingEnabled", on); - s->setProperty("zoomTextOnly", on); - - QVERIFY(s->property("autoLoadImages") == on); - QVERIFY(s->property("developerExtrasEnabled") == on); - QVERIFY(s->property("javaEnabled") == on); - QVERIFY(s->property("javascriptCanAccessClipboard") == on); - QVERIFY(s->property("javascriptCanOpenWindows") == on); - QVERIFY(s->property("javascriptEnabled") == on); - QVERIFY(s->property("linksIncludedInFocusChain") == on); - QVERIFY(s->property("localContentCanAccessRemoteUrls") == on); - QVERIFY(s->property("localStorageDatabaseEnabled") == on); - QVERIFY(s->property("offlineStorageDatabaseEnabled") == on); - QVERIFY(s->property("offlineWebApplicationCacheEnabled") == on); - QVERIFY(s->property("pluginsEnabled") == on); - QVERIFY(s->property("printElementBackgrounds") == on); - QVERIFY(s->property("privateBrowsingEnabled") == on); - QVERIFY(s->property("zoomTextOnly") == on); - - QVERIFY(s->property("autoLoadImages") == on); - QVERIFY(s->property("developerExtrasEnabled") == on); - QVERIFY(s->property("javaEnabled") == on); - QVERIFY(s->property("javascriptCanAccessClipboard") == on); - QVERIFY(s->property("javascriptCanOpenWindows") == on); - QVERIFY(s->property("javascriptEnabled") == on); - QVERIFY(s->property("linksIncludedInFocusChain") == on); - QVERIFY(s->property("localContentCanAccessRemoteUrls") == on); - QVERIFY(s->property("localStorageDatabaseEnabled") == on); - QVERIFY(s->property("offlineStorageDatabaseEnabled") == on); - QVERIFY(s->property("offlineWebApplicationCacheEnabled") == on); - QVERIFY(s->property("pluginsEnabled") == on); - QVERIFY(s->property("printElementBackgrounds") == on); - QVERIFY(s->property("privateBrowsingEnabled") == on); - QVERIFY(s->property("zoomTextOnly") == on); - } -} - -void tst_qdeclarativewebview::historyNav() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml")); - checkNoErrors(component); - QWebSettings::enablePersistentStorage(tmpDir()); - - QObject *wv = component.create(); - QVERIFY(wv != 0); - for (int i=1; i<=2; ++i) { - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("title").toString(),QString("Basic")); - QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 48); - QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")),QPixmap(SRCDIR "/data/basic.png")); - QCOMPARE(wv->property("statusText").toString(),QString("status here")); - QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/basic.html")), strippedHtml(wv->property("html").toString())); - QCOMPARE(wv->property("preferredWidth").toDouble(), 0.0); - QCOMPARE(wv->property("url").toUrl(), QUrl::fromLocalFile(SRCDIR "/data/basic.html")); - QCOMPARE(wv->property("status").toInt(), 1 /*QDeclarativeWebView::Ready*/); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("back"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("back"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("forward"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("forward"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("stop"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("stop"))->isEnabled()); - - qvariant_cast<QAction*>(wv->property("reload"))->trigger(); - } - - wv->setProperty("url", QUrl::fromLocalFile(SRCDIR "/data/forward.html")); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("title").toString(),QString("Forward")); - QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 32); - QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")),QPixmap(SRCDIR "/data/forward.png")); - QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/forward.html")), strippedHtml(wv->property("html").toString())); - QCOMPARE(wv->property("url").toUrl(), QUrl::fromLocalFile(SRCDIR "/data/forward.html")); - QCOMPARE(wv->property("status").toInt(), 1 /*QDeclarativeWebView::Ready*/); - QCOMPARE(wv->property("statusText").toString(),QString("")); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("back"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("back"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("forward"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("forward"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("stop"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("stop"))->isEnabled()); - - qvariant_cast<QAction*>(wv->property("back"))->trigger(); - - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("title").toString(),QString("Basic")); - QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/basic.html")), strippedHtml(wv->property("html").toString())); - QCOMPARE(wv->property("url").toUrl(), QUrl::fromLocalFile(SRCDIR "/data/basic.html")); - QCOMPARE(wv->property("status").toInt(), 1 /*QDeclarativeWebView::Ready*/); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("back"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("back"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("forward"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("forward"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("stop"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("stop"))->isEnabled()); -} - -void tst_qdeclarativewebview::multipleWindows() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/newwindows.qml")); - checkNoErrors(component); - - QDeclarativeGrid *grid = qobject_cast<QDeclarativeGrid*>(component.create()); - QVERIFY(grid != 0); - QTRY_COMPARE(grid->children().count(), 2+4); // Component, Loader (with 1 WebView), 4 new-window WebViews - QDeclarativeItem* popup = qobject_cast<QDeclarativeItem*>(grid->children().at(2)); // first popup after Component and Loader. - QVERIFY(popup != 0); - QTRY_COMPARE(popup->x(), 150.0); -} - -void tst_qdeclarativewebview::loadError() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/loadError.qml")); - checkNoErrors(component); - QWebSettings::enablePersistentStorage(tmpDir()); - - QObject *wv = component.create(); - QVERIFY(wv != 0); - for (int i=1; i<=2; ++i) { - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("title").toString(),QString("")); - QCOMPARE(wv->property("statusText").toString(),QString("")); // HTML 'status bar' text, not error message - QCOMPARE(wv->property("url").toUrl(), QUrl::fromLocalFile(SRCDIR "/data/does-not-exist.html")); // Unlike QWebPage, which loses url - QCOMPARE(wv->property("status").toInt(), 3 /*QDeclarativeWebView::Error*/); - - qvariant_cast<QAction*>(wv->property("reload"))->trigger(); - } -} - -void tst_qdeclarativewebview::setHtml() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/sethtml.qml")); - checkNoErrors(component); - QObject *wv = component.create(); - QVERIFY(wv != 0); - QCOMPARE(wv->property("html").toString(),QString("<html><head></head><body><p>This is a <b>string</b> set on the WebView</p></body></html>")); - - QSignalSpy spy(wv, SIGNAL(htmlChanged())); - wv->setProperty("html", QString("<html><head><title>Basic</title></head><body><p>text</p></body></html>")); - QCOMPARE(spy.count(),1); -} - -void tst_qdeclarativewebview::elementAreaAt() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/elements.qml")); - checkNoErrors(component); - QObject *wv = component.create(); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - - /* not now it's a plugin... - QCOMPARE(wv->elementAreaAt(40,30,100,100),QRect(1,1,75,54)); // Area A in data/elements.html - QCOMPARE(wv->elementAreaAt(130,30,200,100),QRect(78,3,110,50)); // Area B - QCOMPARE(wv->elementAreaAt(40,30,400,400),QRect(0,0,310,100)); // Whole view - QCOMPARE(wv->elementAreaAt(130,30,280,280),QRect(76,1,223,54)); // Area BC - QCOMPARE(wv->elementAreaAt(130,30,400,400),QRect(0,0,310,100)); // Whole view - */ -} - -void tst_qdeclarativewebview::javaScript() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/javaScript.qml")); - checkNoErrors(component); - QObject *wv = component.create(); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - /* not now it's a plugin... - QCOMPARE(wv->evaluateJavaScript("123").toInt(), 123); - QCOMPARE(wv->evaluateJavaScript("window.status").toString(), QString("status here")); - QCOMPARE(wv->evaluateJavaScript("window.myjsname.qmlprop").toString(), QString("qmlvalue")); - */ -} - -/* -Cannot be done now that webkit is a plugin - -void tst_qdeclarativewebview::pixelCache() -{ - - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/pixelCache.qml")); - checkNoErrors(component); - MyWebView *wv = qobject_cast<MyWebView*>(component.create()); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress"), 1.0); - QPixmap pm(150,150); - QPainter p(&pm); - wv->paint(&p,0,0); - const int expected = 120*(150+128); // 120 = width of HTML page, 150=pixmap height, 128=cache extra area - QCOMPARE(wv->property("pixelsPainted"), expected); - wv->paint(&p,0,0); - QCOMPARE(wv->property("pixelsPainted"), expected); // nothing new needed to be painted - wv->setProperty("pixelCacheSize", 0); // clears the cache - wv->paint(&p,0,0); - QCOMPARE(wv->property("pixelsPainted"), expected*2); // everything needed to be painted - // Note that painted things always go into the cache (even if they don't "fit"), - // just that they will be removed if anything else needs to be painted. - wv->setProperty("pixelCacheSize", expected); // won't clear the cache - wv->paint(&p,0,0); - QCOMPARE(wv->property("pixelsPainted"), expected*2); // still there - wv->setProperty("pixelCacheSize", expected-1); // too small - will clear the cache - wv->paint(&p,0,0); - QCOMPARE(wv->property("pixelsPainted"), expected*3); // repainted -} -*/ - -void tst_qdeclarativewebview::newWindowParent() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml")); - checkNoErrors(component); - QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(component.create()); - QObject *wv = rootItem->findChild<QObject*>("webView"); - QVERIFY(rootItem != 0); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - - QDeclarativeItem* oldWindowParent = rootItem->findChild<QDeclarativeItem*>("oldWindowParent"); - QCOMPARE(qvariant_cast<QDeclarativeItem*>(wv->property("newWindowParent")), oldWindowParent); - QSignalSpy newWindowParentSpy(wv, SIGNAL(newWindowParentChanged())); - - QDeclarativeItem* newWindowParent = rootItem->findChild<QDeclarativeItem*>("newWindowParent"); - wv->setProperty("newWindowParent", QVariant::fromValue(newWindowParent)); - QVERIFY(newWindowParent); - QVERIFY(oldWindowParent); - QVERIFY(oldWindowParent->childItems().count() == 0); - QCOMPARE(wv->property("newWindowParent"), QVariant::fromValue(newWindowParent)); - QCOMPARE(newWindowParentSpy.count(),1); - - wv->setProperty("newWindowParent", QVariant::fromValue(newWindowParent)); - QCOMPARE(newWindowParentSpy.count(),1); - - wv->setProperty("newWindowParent", QVariant::fromValue((QDeclarativeItem*)0)); - QCOMPARE(newWindowParentSpy.count(),2); -} - -void tst_qdeclarativewebview::newWindowComponent() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml")); - checkNoErrors(component); - QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(component.create()); - QObject *wv = rootItem->findChild<QObject*>("webView"); - QVERIFY(rootItem != 0); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - - QDeclarativeComponent substituteComponent(&engine); - substituteComponent.setData("import QtQuick 1.0; WebView { objectName: 'newWebView'; url: 'basic.html'; }", QUrl::fromLocalFile("")); - QSignalSpy newWindowComponentSpy(wv, SIGNAL(newWindowComponentChanged())); - - wv->setProperty("newWindowComponent", QVariant::fromValue(&substituteComponent)); - QCOMPARE(wv->property("newWindowComponent"), QVariant::fromValue(&substituteComponent)); - QCOMPARE(newWindowComponentSpy.count(),1); - - wv->setProperty("newWindowComponent", QVariant::fromValue(&substituteComponent)); - QCOMPARE(newWindowComponentSpy.count(),1); - - wv->setProperty("newWindowComponent", QVariant::fromValue((QDeclarativeComponent*)0)); - QCOMPARE(newWindowComponentSpy.count(),2); -} - -void tst_qdeclarativewebview::renderingEnabled() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml")); - checkNoErrors(component); - QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(component.create()); - QObject *wv = rootItem->findChild<QObject*>("webView"); - QVERIFY(rootItem != 0); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - - QVERIFY(wv->property("renderingEnabled").toBool()); - QSignalSpy renderingEnabledSpy(wv, SIGNAL(renderingEnabledChanged())); - - wv->setProperty("renderingEnabled", false); - QVERIFY(!wv->property("renderingEnabled").toBool()); - QCOMPARE(renderingEnabledSpy.count(),1); - - wv->setProperty("renderingEnabled", false); - QCOMPARE(renderingEnabledSpy.count(),1); - - wv->setProperty("renderingEnabled", true); - QCOMPARE(renderingEnabledSpy.count(),2); -} - -void tst_qdeclarativewebview::pressGrabTime() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml")); - checkNoErrors(component); - QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(component.create()); - QObject *wv = rootItem->findChild<QObject*>("webView"); - QVERIFY(rootItem != 0); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("pressGrabTime").toInt(), 200); - QSignalSpy pressGrabTimeSpy(wv, SIGNAL(pressGrabTimeChanged())); - - wv->setProperty("pressGrabTime", 100); - QCOMPARE(wv->property("pressGrabTime").toInt(), 100); - QCOMPARE(pressGrabTimeSpy.count(),1); - - wv->setProperty("pressGrabTime", 100); - QCOMPARE(pressGrabTimeSpy.count(),1); - - wv->setProperty("pressGrabTime", 0); - QCOMPARE(pressGrabTimeSpy.count(),2); -} - -QTEST_MAIN(tst_qdeclarativewebview) - -#include "tst_qdeclarativewebview.moc" diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/Global.js b/tests/auto/declarative/qdeclarativeworkerscript/data/Global.js new file mode 100644 index 0000000..6bdb4a5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/Global.js @@ -0,0 +1 @@ +var data = "World" diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/script_include.js b/tests/auto/declarative/qdeclarativeworkerscript/data/script_include.js new file mode 100644 index 0000000..0385d91 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/script_include.js @@ -0,0 +1,5 @@ +WorkerScript.onMessage = function(msg) { + var res = Qt.include("Global.js"); + WorkerScript.sendMessage(msg + " " + data) +} + diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/worker_include.qml b/tests/auto/declarative/qdeclarativeworkerscript/data/worker_include.qml new file mode 100644 index 0000000..595cb2b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/worker_include.qml @@ -0,0 +1,5 @@ +import QtQuick 1.0 + +BaseWorker { + source: "script_include.js" +} diff --git a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp index 4b922fb..b64e10c 100644 --- a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp +++ b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp @@ -79,6 +79,7 @@ private slots: void messaging_sendQObjectList(); void messaging_sendJsObject(); void script_with_pragma(); + void script_included(); void scriptError_onLoad(); void scriptError_onCall(); @@ -226,6 +227,24 @@ void tst_QDeclarativeWorkerScript::script_with_pragma() delete worker; } +void tst_QDeclarativeWorkerScript::script_included() +{ + QDeclarativeComponent component(&m_engine, SRCDIR "/data/worker_include.qml"); + QDeclarativeWorkerScript *worker = qobject_cast<QDeclarativeWorkerScript*>(component.create()); + QVERIFY(worker != 0); + + QString value("Hello"); + + QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value))); + waitForEchoMessage(worker); + + const QMetaObject *mo = worker->metaObject(); + QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).toString(), value + " World"); + + qApp->processEvents(); + delete worker; +} + static QString qdeclarativeworkerscript_lastWarning; static void qdeclarativeworkerscript_warningsHandler(QtMsgType type, const char *msg) { diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.0.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.0.png Binary files differnew file mode 100644 index 0000000..160155e --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.0.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.1.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.1.png Binary files differnew file mode 100644 index 0000000..160155e --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.1.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.10.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.10.png Binary files differnew file mode 100644 index 0000000..1ccab41 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.10.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.11.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.11.png Binary files differnew file mode 100644 index 0000000..160155e --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.11.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.12.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.12.png Binary files differnew file mode 100644 index 0000000..f25bd7c --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.12.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.2.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.2.png Binary files differnew file mode 100644 index 0000000..f25bd7c --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.2.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.3.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.3.png Binary files differnew file mode 100644 index 0000000..dad1de4 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.3.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.4.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.4.png Binary files differnew file mode 100644 index 0000000..cd4f23a --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.4.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.5.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.5.png Binary files differnew file mode 100644 index 0000000..160155e --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.5.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.6.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.6.png Binary files differnew file mode 100644 index 0000000..160155e --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.6.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.7.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.7.png Binary files differnew file mode 100644 index 0000000..f25bd7c --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.7.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.8.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.8.png Binary files differnew file mode 100644 index 0000000..160155e --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.8.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.9.png b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.9.png Binary files differnew file mode 100644 index 0000000..160155e --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.9.png diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.qml b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.qml new file mode 100644 index 0000000..e858c11 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/data/reanchor.qml @@ -0,0 +1,1499 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "reanchor.0.png" + } + Frame { + msec: 32 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 48 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 64 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 80 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 96 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 112 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 128 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 144 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 160 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 176 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 192 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 208 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 224 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 240 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 256 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 272 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 288 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 304 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 320 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 336 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 352 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 368 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 384 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 400 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 416 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 432 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 448 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 464 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 480 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 496 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 512 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 528 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 544 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 560 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 576 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 592 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 608 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 624 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 640 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 656 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 672 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 688 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 704 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 720 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 736 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 752 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 768 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 784 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 800 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 816 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 832 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 848 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 864 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 880 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 896 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 912 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 928 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 944 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 960 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 976 + image: "reanchor.1.png" + } + Frame { + msec: 992 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 1008 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 1024 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 1040 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 1056 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 164; y: 196 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1072 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 1088 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 1104 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 1120 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 1136 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 164; y: 196 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1152 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 1168 + hash: "f7814217626627ce70ca0e9487354ba9" + } + Frame { + msec: 1184 + hash: "7825b2b77e441ca6f46dbca80c7fe602" + } + Frame { + msec: 1200 + hash: "0ac443a9946b0bcf8db768af7d16d51e" + } + Frame { + msec: 1216 + hash: "c943d5d46f0d527690f38a9c8bd7be51" + } + Frame { + msec: 1232 + hash: "38151db0c9964d33bcb2ff155ebd468c" + } + Frame { + msec: 1248 + hash: "0fb8c53587a95a12cced6d30018edec1" + } + Frame { + msec: 1264 + hash: "2c684a649652270a638aca41a80e327c" + } + Frame { + msec: 1280 + hash: "60dd5c448ef8b97ec13ad3140a584229" + } + Frame { + msec: 1296 + hash: "d564f28f9d528daca729db6fab163b6c" + } + Frame { + msec: 1312 + hash: "4c07b33632ec4f30ee31141099c15a88" + } + Frame { + msec: 1328 + hash: "9facfd27fa16ee9d493e7fb7bcfadbf8" + } + Frame { + msec: 1344 + hash: "fc0fbb8aac8f389841e615be1e7b06de" + } + Frame { + msec: 1360 + hash: "579c18fa201b5609276c761ffd42df33" + } + Frame { + msec: 1376 + hash: "5b3630c37acfc2599a5a8b2e11aaa34c" + } + Frame { + msec: 1392 + hash: "2c1ee8aca06dccf0d39287721bf76aa7" + } + Frame { + msec: 1408 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1424 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1440 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1456 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1472 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1488 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1504 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1520 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1536 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1552 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1568 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1584 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1600 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1616 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1632 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1648 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1664 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1680 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1696 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1712 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1728 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1744 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1760 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1776 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1792 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1808 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1824 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1840 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1856 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1872 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1888 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1904 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1920 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1936 + image: "reanchor.2.png" + } + Frame { + msec: 1952 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1968 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 1984 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 2000 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 2016 + hash: "c03bb338fff252a100b080366ac907b5" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 170; y: 120 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2032 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 2048 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 2064 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 2080 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 2096 + hash: "c03bb338fff252a100b080366ac907b5" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 170; y: 120 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2112 + hash: "c03bb338fff252a100b080366ac907b5" + } + Frame { + msec: 2128 + hash: "e9d7372c17ca1510eb15faff5d0794b2" + } + Frame { + msec: 2144 + hash: "60f897e2b9594c4b5c02ce2fbdf9ae3c" + } + Frame { + msec: 2160 + hash: "c35ead9a8e682e8f3c0a091d232310f7" + } + Frame { + msec: 2176 + hash: "272632b0568391022590edc09ea30e28" + } + Frame { + msec: 2192 + hash: "9d4cdb31b01e86a31627e3ff9bb64100" + } + Frame { + msec: 2208 + hash: "5ee65b0290721fe47508c6435c18554b" + } + Frame { + msec: 2224 + hash: "8dd65e1a9417318d793d2027de4fe6ae" + } + Frame { + msec: 2240 + hash: "bcce6d1fd7d2c1539ad9ac42c0552d5e" + } + Frame { + msec: 2256 + hash: "e01f5850113c178da3383406fe73d6e0" + } + Frame { + msec: 2272 + hash: "968fc6b2bf6b7d43e05254339cf6123f" + } + Frame { + msec: 2288 + hash: "30f25fdde31e13934e328fa1d2655ccb" + } + Frame { + msec: 2304 + hash: "f58a21e96037813c9dd7f933405c9b11" + } + Frame { + msec: 2320 + hash: "1fe42c887f2eaf7696fcf0b8b884d0fd" + } + Frame { + msec: 2336 + hash: "848a27b9e4f4c0bcc1a11d6dba7ce92b" + } + Frame { + msec: 2352 + hash: "ca92736257db83e39f54b04325201942" + } + Frame { + msec: 2368 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 2384 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 134; y: 106 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2400 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 2416 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 2432 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 2448 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 2464 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 134; y: 106 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2480 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 2496 + hash: "9082504eee5e0c3cbef9fd9545f09dcb" + } + Frame { + msec: 2512 + hash: "dbe5169edb4400c74841a8af64e0949f" + } + Frame { + msec: 2528 + hash: "d588405fc5e2423cdb954c5624172209" + } + Frame { + msec: 2544 + hash: "ed2b273ea36fb7d8feaca4d5dae72f81" + } + Frame { + msec: 2560 + hash: "5249e4824eb169b5ee3f7fb52fe09aa7" + } + Frame { + msec: 2576 + hash: "2838eff2a1a299c9e47cf78be99172ca" + } + Frame { + msec: 2592 + hash: "c47f6a937a4a6ef045159d7ba04de8af" + } + Frame { + msec: 2608 + hash: "fd3bc1b9ba2629bccb0fec04deffcdad" + } + Frame { + msec: 2624 + hash: "54c9b8599a32ac95aff324977b34f7e6" + } + Frame { + msec: 2640 + hash: "cc5652a05828146cdc9c9b8430f5f59c" + } + Frame { + msec: 2656 + hash: "ce5815fb51a4bd697a2fde46084e118b" + } + Frame { + msec: 2672 + hash: "01dfd2604263f1fd24382ce876af10f9" + } + Frame { + msec: 2688 + hash: "45ea282d20ee9e345eb2cac8c22c42e0" + } + Frame { + msec: 2704 + hash: "afd26ac9776e57c94e4b52ebfeb7206c" + } + Frame { + msec: 2720 + hash: "97aeed321d4d92cb1ec236d2a98fbe9b" + } + Mouse { + type: 4 + button: 1 + buttons: 1 + x: 134; y: 106 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2736 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 2752 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 2768 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 2784 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 2800 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 134; y: 106 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2816 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 2832 + hash: "81b8228c6aeefe8072b7704f11e6707e" + } + Frame { + msec: 2848 + hash: "617e416bf117a51b756c90321ebb1449" + } + Frame { + msec: 2864 + hash: "656d8d5d54c9ee137aceb519aff72cce" + } + Frame { + msec: 2880 + hash: "94ba3b6f558c010cdd32f54cce436388" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 134; y: 106 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2896 + image: "reanchor.3.png" + } + Frame { + msec: 2912 + hash: "0bc822fdd4caac17aab80e8601d3a523" + } + Frame { + msec: 2928 + hash: "886d0407ac76d7344f7a314f07b3efff" + } + Frame { + msec: 2944 + hash: "eb6c46af5037f24348edbe0dda48fb62" + } + Frame { + msec: 2960 + hash: "1c578a1eeb67c6833241bcb3214f06fb" + } + Frame { + msec: 2976 + hash: "55f1631ef567217a5945b2a23c59b549" + } + Frame { + msec: 2992 + hash: "25fdd4d54ddb035b082dc3a0d0816114" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 134; y: 106 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3008 + hash: "25fdd4d54ddb035b082dc3a0d0816114" + } + Frame { + msec: 3024 + hash: "efd61e7c1aaffec77bd3d2de6645b2c0" + } + Frame { + msec: 3040 + hash: "02ac5ca0fa7d2ec3903fccd5dc556fa5" + } + Frame { + msec: 3056 + hash: "daf52e45b8fc68f74e424554074678cc" + } + Frame { + msec: 3072 + hash: "9e2def87e83b0c4b9f26684665aa1e51" + } + Frame { + msec: 3088 + hash: "0e72fc762cc9a061e91692376d65d292" + } + Frame { + msec: 3104 + hash: "c5ac37e4a5250b35a4976bcb31505cca" + } + Frame { + msec: 3120 + hash: "eefe6bb7963c580c68198ee6098a36f4" + } + Frame { + msec: 3136 + hash: "7b78d77ac11b72d1fb827ebb66a04c8e" + } + Frame { + msec: 3152 + hash: "ce5815fb51a4bd697a2fde46084e118b" + } + Frame { + msec: 3168 + hash: "94ba3b6f558c010cdd32f54cce436388" + } + Frame { + msec: 3184 + hash: "61a56140e5a6a2bfcee5c6322b37e130" + } + Frame { + msec: 3200 + hash: "a67b22c0a966fe3fbe869497dc00960f" + } + Frame { + msec: 3216 + hash: "4edd212676ac93ae761039e80f989349" + } + Frame { + msec: 3232 + hash: "fea5797441d65625c400238f73d94807" + } + Frame { + msec: 3248 + hash: "23e9209ff0257343016cffdf7ea6571c" + } + Frame { + msec: 3264 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3280 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3296 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3312 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3328 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3344 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3360 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3376 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3392 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3408 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3424 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3440 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3456 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3472 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3488 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3504 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3520 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3536 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3552 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3568 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3584 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3600 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3616 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3632 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3648 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3664 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3680 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3696 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3712 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3728 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3744 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3760 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3776 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3792 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3808 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3824 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3840 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3856 + image: "reanchor.4.png" + } + Frame { + msec: 3872 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3888 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3904 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3920 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3936 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3952 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3968 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 3984 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4000 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4016 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4032 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4048 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4064 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4080 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4096 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4112 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4128 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4144 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4160 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4176 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 124; y: 113 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4192 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4208 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4224 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4240 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4256 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 124; y: 113 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4272 + hash: "3a1fc9be558078e35a9828e411847c19" + } + Frame { + msec: 4288 + hash: "81b8228c6aeefe8072b7704f11e6707e" + } + Frame { + msec: 4304 + hash: "617e416bf117a51b756c90321ebb1449" + } + Frame { + msec: 4320 + hash: "656d8d5d54c9ee137aceb519aff72cce" + } + Frame { + msec: 4336 + hash: "94ba3b6f558c010cdd32f54cce436388" + } + Frame { + msec: 4352 + hash: "5b0679ff3730cba4ac026e89c7811fbe" + } + Frame { + msec: 4368 + hash: "0bc822fdd4caac17aab80e8601d3a523" + } + Frame { + msec: 4384 + hash: "886d0407ac76d7344f7a314f07b3efff" + } + Frame { + msec: 4400 + hash: "eb6c46af5037f24348edbe0dda48fb62" + } + Frame { + msec: 4416 + hash: "1c578a1eeb67c6833241bcb3214f06fb" + } + Frame { + msec: 4432 + hash: "55f1631ef567217a5945b2a23c59b549" + } + Frame { + msec: 4448 + hash: "25fdd4d54ddb035b082dc3a0d0816114" + } + Frame { + msec: 4464 + hash: "295ea6ff4d3c2c7de0cfbc29b2bd2c38" + } + Frame { + msec: 4480 + hash: "26b978ab645c04731703bcf15ac34a11" + } + Frame { + msec: 4496 + hash: "0db4c2515b89506df51732c4b9bf75dc" + } + Frame { + msec: 4512 + hash: "3cf30f3a06e325e195a4a7dec1e04c01" + } + Frame { + msec: 4528 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4544 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4560 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4576 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4592 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4608 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4624 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4640 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4656 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4672 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4688 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4704 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4720 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4736 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4752 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4768 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4784 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4800 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4816 + image: "reanchor.5.png" + } + Frame { + msec: 4832 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4848 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4864 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4880 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4896 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4912 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4928 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4944 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4960 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4976 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 4992 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5008 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5024 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5040 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5056 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5072 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5088 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5104 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5120 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5136 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5152 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5168 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5184 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5200 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5216 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5232 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5248 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5264 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5280 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5296 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5312 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5328 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5344 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5360 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5376 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5392 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5408 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5424 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5440 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5456 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5472 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5488 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5504 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5520 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5536 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5552 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5568 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } + Frame { + msec: 5584 + hash: "0009d8bfdfaed2a4f05aacb7a7992234" + } +} diff --git a/tests/auto/declarative/qmlvisual/animation/reanchorRTL/reanchor.qml b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/reanchor.qml new file mode 100644 index 0000000..ba37737 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/animation/reanchorRTL/reanchor.qml @@ -0,0 +1,69 @@ +import QtQuick 1.1 + +Rectangle { + id: container + width: 200; height: 200 + Rectangle { + id: myRect + anchors.layoutDirection: Qt.RightToLeft + objectName: "MyRect" + color: "green"; + anchors.left: parent.left + anchors.right: rightGuideline.left + anchors.top: topGuideline.top + anchors.bottom: container.bottom + } + Item { id: leftGuideline; x: 10 } + Item { id: rightGuideline; x: 150 } + Item { id: topGuideline; y: 10 } + Item { id: bottomGuideline; y: 150 } + Item { id: topGuideline2; y: 50 } + Item { id: bottomGuideline2; y: 175 } + MouseArea { + id: wholeArea + anchors.fill: parent + onClicked: { + if (container.state == "") { + container.state = "reanchored"; + } else if (container.state == "reanchored") { + container.state = "reanchored2"; + } else if (container.state == "reanchored2") + container.state = "reanchored"; + } + } + + states: [ State { + name: "reanchored" + AnchorChanges { + target: myRect; + anchors.left: leftGuideline.left + anchors.right: container.right + anchors.top: container.top + anchors.bottom: bottomGuideline.bottom + } + }, State { + name: "reanchored2" + AnchorChanges { + target: myRect; + anchors.left: undefined + anchors.right: undefined + anchors.top: topGuideline2.top + anchors.bottom: bottomGuideline2.bottom + } + }] + + transitions: Transition { + AnchorAnimation { } + } + + MouseArea { + width: 50; height: 50 + anchors.right: parent.right + anchors.bottom: parent.bottom + onClicked: { + container.state = ""; + } + } + + state: "reanchored" +} diff --git a/tests/auto/declarative/qperformancetimer/tst_qperformancetimer.cpp b/tests/auto/declarative/qperformancetimer/tst_qperformancetimer.cpp index 2029c8a..057a8ca 100644 --- a/tests/auto/declarative/qperformancetimer/tst_qperformancetimer.cpp +++ b/tests/auto/declarative/qperformancetimer/tst_qperformancetimer.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index 356a98d..8dc7b5f 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -112,6 +112,7 @@ SUBDIRS=\ qmimedata \ qmouseevent_modal \ qmovie \ + qvolatileimage \ qnetworkaccessmanager_and_qprogressdialog \ qpaintengine \ qpainterpath \ diff --git a/tests/auto/lancelot/lancelot.pro b/tests/auto/lancelot/lancelot.pro index 93841a3..11beb7e 100644 --- a/tests/auto/lancelot/lancelot.pro +++ b/tests/auto/lancelot/lancelot.pro @@ -3,11 +3,11 @@ QT += xml svg contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2):QT += opengl SOURCES += tst_lancelot.cpp \ - $$QT_SOURCE_TREE/tests/arthur/common/paintcommands.cpp -HEADERS += $$QT_SOURCE_TREE/tests/arthur/common/paintcommands.h -RESOURCES += $$QT_SOURCE_TREE/tests/arthur/common/images.qrc + $$PWD/../../arthur/common/paintcommands.cpp +HEADERS += $$PWD/../../arthur/common/paintcommands.h +RESOURCES += $$PWD/../../arthur/common/images.qrc -include($$QT_SOURCE_TREE/tests/arthur/common/qbaselinetest.pri) +include($$PWD/../../arthur/common/qbaselinetest.pri) !symbian:!wince*:DEFINES += SRCDIR=\\\"$$PWD\\\" linux-g++-maemo:DEFINES += USE_RUNTIME_DIR diff --git a/tests/auto/lancelot/tst_lancelot.cpp b/tests/auto/lancelot/tst_lancelot.cpp index 0e8757b..e515c48 100644 --- a/tests/auto/lancelot/tst_lancelot.cpp +++ b/tests/auto/lancelot/tst_lancelot.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/mediaobject/dummy/dummy.pro b/tests/auto/mediaobject/dummy/dummy.pro index 88b864b..c81411c 100644 --- a/tests/auto/mediaobject/dummy/dummy.pro +++ b/tests/auto/mediaobject/dummy/dummy.pro @@ -1,7 +1,7 @@ TEMPLATE = lib isEmpty(QT_MAJOR_VERSION) { - VERSION=4.6.4 + VERSION=4.7.3 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } diff --git a/tests/auto/moc/tst_moc.cpp b/tests/auto/moc/tst_moc.cpp index bbfa91f..203f0ae 100644 --- a/tests/auto/moc/tst_moc.cpp +++ b/tests/auto/moc/tst_moc.cpp @@ -495,6 +495,10 @@ private slots: void notifyError(); void QTBUG17635_invokableAndProperty(); void revisions(); + void warnings_data(); + void warnings(); + + signals: void sigWithUnsignedArg(unsigned foo); void sigWithSignedArg(signed foo); @@ -1524,8 +1528,126 @@ void tst_Moc::revisions() revisions_T<VersionTestNotify>(); } -QTEST_APPLESS_MAIN(tst_Moc) -#include "tst_moc.moc" +void tst_Moc::warnings_data() +{ + QTest::addColumn<QByteArray>("input"); + QTest::addColumn<QStringList>("args"); + QTest::addColumn<int>("exitCode"); + QTest::addColumn<QString>("expectedStdOut"); + QTest::addColumn<QString>("expectedStdErr"); + + // empty input should result in "no relevant classes" note + QTest::newRow("No relevant classes") + << QByteArray(" ") + << QStringList() + << 0 + << QString() + << QString("standard input:0: Note: No relevant classes found. No output generated."); + + // passing "-nn" should suppress "no relevant classes" note + QTest::newRow("-nn") + << QByteArray(" ") + << (QStringList() << "-nn") + << 0 + << QString() + << QString(); + + // passing "-nw" should also suppress "no relevant classes" note + QTest::newRow("-nw") + << QByteArray(" ") + << (QStringList() << "-nw") + << 0 + << QString() + << QString(); + + // This should output a warning + QTest::newRow("Invalid property warning") + << QByteArray("class X : public QObject { Q_OBJECT Q_PROPERTY(int x) };") + << QStringList() + << 0 + << QString("IGNORE_ALL_STDOUT") + << QString("standard input:1: Warning: Property declaration x has no READ accessor function. The property will be invalid."); + + // Passing "-nn" should NOT suppress the warning + QTest::newRow("Invalid property warning") + << QByteArray("class X : public QObject { Q_OBJECT Q_PROPERTY(int x) };") + << (QStringList() << "-nn") + << 0 + << QString("IGNORE_ALL_STDOUT") + << QString("standard input:1: Warning: Property declaration x has no READ accessor function. The property will be invalid."); + + // Passing "-nw" should suppress the warning + QTest::newRow("Invalid property warning") + << QByteArray("class X : public QObject { Q_OBJECT Q_PROPERTY(int x) };") + << (QStringList() << "-nw") + << 0 + << QString("IGNORE_ALL_STDOUT") + << QString(); + + // This should output an error + QTest::newRow("Does not inherit QObject") + << QByteArray("class X { Q_OBJECT };") + << QStringList() + << 1 + << QString() + << QString("standard input:1: Error: Class contains Q_OBJECT macro but does not inherit from QObject"); + + // "-nn" should not suppress the error + QTest::newRow("Does not inherit QObject with -nn") + << QByteArray("class X { Q_OBJECT };") + << (QStringList() << "-nn") + << 1 + << QString() + << QString("standard input:1: Error: Class contains Q_OBJECT macro but does not inherit from QObject"); + + // "-nw" should not suppress the error + QTest::newRow("Does not inherit QObject with -nn") + << QByteArray("class X { Q_OBJECT };") + << (QStringList() << "-nw") + << 1 + << QString() + << QString("standard input:1: Error: Class contains Q_OBJECT macro but does not inherit from QObject"); +} + +void tst_Moc::warnings() +{ +#ifdef MOC_CROSS_COMPILED + QSKIP("Not tested when cross-compiled", SkipAll); +#endif + QFETCH(QByteArray, input); + QFETCH(QStringList, args); + QFETCH(int, exitCode); + QFETCH(QString, expectedStdOut); + QFETCH(QString, expectedStdErr); + +#ifdef Q_CC_MSVC + // for some reasons, moc compiled with MSVC uses a different output format + QRegExp lineNumberRe(":(\\d+):"); + lineNumberRe.setMinimal(true); + expectedStdErr.replace(lineNumberRe, "(\\1):"); +#endif + QProcess proc; + proc.start("moc", args); + QVERIFY(proc.waitForStarted()); + + QCOMPARE(proc.write(input), qint64(input.size())); + + proc.closeWriteChannel(); + + QVERIFY(proc.waitForFinished()); + + QCOMPARE(proc.exitCode(), exitCode); + QCOMPARE(proc.exitStatus(), QProcess::NormalExit); + + // magic value "IGNORE_ALL_STDOUT" ignores stdout + if (expectedStdOut != "IGNORE_ALL_STDOUT") + QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardOutput()).trimmed(), expectedStdOut); + QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()).trimmed(), expectedStdErr); + + } + +QTEST_APPLESS_MAIN(tst_Moc) +#include "tst_moc.moc" diff --git a/tests/auto/nativeimagehandleprovider/nativeimagehandleprovider.pro b/tests/auto/nativeimagehandleprovider/nativeimagehandleprovider.pro new file mode 100644 index 0000000..fb8ecb0 --- /dev/null +++ b/tests/auto/nativeimagehandleprovider/nativeimagehandleprovider.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +SOURCES += tst_nativeimagehandleprovider.cpp +symbian { + LIBS += -lfbscli -lbitgdi + contains(QT_CONFIG, openvg): QT *= openvg +} diff --git a/tests/auto/nativeimagehandleprovider/tst_nativeimagehandleprovider.cpp b/tests/auto/nativeimagehandleprovider/tst_nativeimagehandleprovider.cpp new file mode 100644 index 0000000..3a315f2 --- /dev/null +++ b/tests/auto/nativeimagehandleprovider/tst_nativeimagehandleprovider.cpp @@ -0,0 +1,237 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <QtGui/private/qpixmapdata_p.h> +#include <QtGui/private/qnativeimagehandleprovider_p.h> +#include <QScopedPointer> +#include <QPixmap> +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) +#include <fbs.h> +#include <bitdev.h> +#include <QtOpenVG/private/qpixmapdata_vg_p.h> +#endif + +QPixmap pixmapFromNativeImageHandleProvider(QNativeImageHandleProvider *source) +{ +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) + if (!source) + return QPixmap(); + QScopedPointer<QPixmapData> pd(QPixmapData::create(0, 0, QPixmapData::PixmapType)); + pd->fromNativeType(source, QPixmapData::NativeImageHandleProvider); + return QPixmap(pd.take()); +#else + Q_UNUSED(source); + return QPixmap(); +#endif +} + +class DummyProvider : public QNativeImageHandleProvider +{ +public: + void get(void **handle, QString *type); + void release(void *handle, const QString &type); +}; + +void DummyProvider::get(void **handle, QString *type) +{ + *handle = (void *) 0x12345678; + *type = "some dummy type"; +} + +void DummyProvider::release(void *handle, const QString &type) +{ + Q_UNUSED(handle); + Q_UNUSED(type); +} + +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) +class BitmapProvider : public QNativeImageHandleProvider +{ +public: + BitmapProvider() : bmp(0), refCount(0), w(50), h(60) { } + void get(void **handle, QString *type); + void release(void *handle, const QString &type); + + CFbsBitmap *bmp; + int refCount, w, h; + void *returnedHandle; + QString returnedType; +}; + +void BitmapProvider::get(void **handle, QString *type) +{ + // There may not be a release() if the get() fails so don't bother with + // refcounting in such cases. + if (bmp) + ++refCount; + returnedType = QLatin1String("CFbsBitmap"); + returnedHandle = bmp; + *handle = returnedHandle; + *type = returnedType; +} + +void BitmapProvider::release(void *handle, const QString &type) +{ + if (handle == returnedHandle && type == returnedType && returnedHandle) { + --refCount; + } +} +#endif // symbian & openvg + +class tst_NativeImageHandleProvider : public QObject +{ + Q_OBJECT + +public: + tst_NativeImageHandleProvider() { } + +private slots: + void create(); + void bitmap(); + void hibernate(); +}; + +void tst_NativeImageHandleProvider::create() +{ + QPixmap pm = pixmapFromNativeImageHandleProvider(0); + QVERIFY(pm.isNull()); + QPixmap tmp(10, 20); + if (tmp.pixmapData()->classId() == QPixmapData::OpenVGClass) { + // Verify that null pixmap is properly returned when get() provides bogus results. + DummyProvider prov; + pm = pixmapFromNativeImageHandleProvider(&prov); + QVERIFY(pm.isNull()); + pm = QPixmap(); + } else { + QSKIP("Not openvg, skipping non-trivial tests", SkipSingle); + } +} + +void tst_NativeImageHandleProvider::bitmap() +{ +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) + QPixmap tmp(10, 20); + if (tmp.pixmapData()->classId() == QPixmapData::OpenVGClass) { + BitmapProvider prov; + + // This should fail because of null ptr. + QPixmap pm = pixmapFromNativeImageHandleProvider(&prov); + QVERIFY(pm.isNull()); + pm = QPixmap(); + QCOMPARE(prov.refCount, 0); + + prov.bmp = new CFbsBitmap; + QCOMPARE(prov.bmp->Create(TSize(prov.w, prov.h), EColor16MAP), KErrNone); + CFbsBitmapDevice *bitmapDevice = CFbsBitmapDevice::NewL(prov.bmp); + CBitmapContext *bitmapContext = 0; + QCOMPARE(bitmapDevice->CreateBitmapContext(bitmapContext), KErrNone); + TRgb symbianColor = TRgb(255, 200, 100); + bitmapContext->SetBrushColor(symbianColor); + bitmapContext->Clear(); + delete bitmapContext; + delete bitmapDevice; + + pm = pixmapFromNativeImageHandleProvider(&prov); + QVERIFY(!pm.isNull()); + QCOMPARE(pm.width(), prov.w); + QCOMPARE(pm.height(), prov.h); + QVERIFY(prov.refCount == 1); + QImage img = pm.toImage(); + QVERIFY(prov.refCount == 1); + QRgb pix = img.pixel(QPoint(1, 2)); + QCOMPARE(qRed(pix), symbianColor.Red()); + QCOMPARE(qGreen(pix), symbianColor.Green()); + QCOMPARE(qBlue(pix), symbianColor.Blue()); + + pm = QPixmap(); // should result in calling release + QCOMPARE(prov.refCount, 0); + delete prov.bmp; + } else { + QSKIP("Not openvg", SkipSingle); + } +#else + QSKIP("Not applicable", SkipSingle); +#endif +} + +void tst_NativeImageHandleProvider::hibernate() +{ +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) + QPixmap tmp(10, 20); + if (tmp.pixmapData()->classId() == QPixmapData::OpenVGClass) { + BitmapProvider prov; + prov.bmp = new CFbsBitmap; + QCOMPARE(prov.bmp->Create(TSize(prov.w, prov.h), EColor16MAP), KErrNone); + + QPixmap pm = pixmapFromNativeImageHandleProvider(&prov); + QCOMPARE(prov.refCount, 1); + + QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pm.pixmapData()); + vgpd->hibernate(); + QCOMPARE(prov.refCount, 0); + + // Calling toVGImage() may cause some warnings as we don't have a gui initialized, + // but the only thing we care about here is get() being called. + vgpd->toVGImage(); + QCOMPARE(prov.refCount, 1); + + pm = QPixmap(); + QCOMPARE(prov.refCount, 0); + delete prov.bmp; + } else { + QSKIP("Not openvg", SkipSingle); + } +#else + QSKIP("Not applicable", SkipSingle); +#endif +} + +int main(int argc, char *argv[]) +{ + QApplication::setGraphicsSystem("openvg"); + QApplication app(argc, argv); + tst_NativeImageHandleProvider tc; + return QTest::qExec(&tc, argc, argv); +} + +#include "tst_nativeimagehandleprovider.moc" diff --git a/tests/auto/other.pro b/tests/auto/other.pro index 512cd25..8819879 100644 --- a/tests/auto/other.pro +++ b/tests/auto/other.pro @@ -34,7 +34,8 @@ SUBDIRS=\ qvariant \ qwidget \ qworkspace \ - windowsmobile + windowsmobile \ + nativeimagehandleprovider contains(QT_CONFIG, OdfWriter):SUBDIRS += qzip qtextodfwriter mac: { diff --git a/tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp b/tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp index 5952252..1178169 100644 --- a/tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp +++ b/tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qclipboard/tst_qclipboard.cpp b/tests/auto/qclipboard/tst_qclipboard.cpp index c05bbac..7840974 100644 --- a/tests/auto/qclipboard/tst_qclipboard.cpp +++ b/tests/auto/qclipboard/tst_qclipboard.cpp @@ -205,7 +205,7 @@ void tst_QClipboard::testSignals() void tst_QClipboard::copy_exit_paste() { #ifndef QT_NO_PROCESS -#if defined Q_WS_X11 || defined Q_WS_QWS +#if defined Q_WS_X11 || defined Q_WS_QWS || defined (Q_WS_QPA) QSKIP("This test does not make sense on X11 and embedded, copied data disappears from the clipboard when the application exits ", SkipAll); // ### It's still possible to test copy/paste - just keep the apps running #elif defined (Q_OS_SYMBIAN) && defined (Q_CC_NOKIAX86) diff --git a/tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp b/tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp index 0256b82..f66b849 100644 --- a/tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp +++ b/tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp @@ -127,7 +127,7 @@ void tst_QDesktopWidget::screenNumberForQWidget() QWidget widget; widget.show(); - QApplication::processEvents(); + QTest::qWaitForWindowShown(&widget); QVERIFY(widget.isVisible()); int widgetScreen = desktop.screenNumber(&widget); @@ -142,7 +142,9 @@ void tst_QDesktopWidget::screenNumberForQPoint() QRect allScreens; for (int i = 0; i < desktopWidget->numScreens(); ++i) { QRect screenGeometry = desktopWidget->screenGeometry(i); +#if !defined(Q_OS_SYMBIAN) QCOMPARE(desktopWidget->screenNumber(screenGeometry.center()), i); +#endif allScreens |= screenGeometry; } @@ -180,7 +182,6 @@ void tst_QDesktopWidget::screenGeometry() total = desktopWidget->screenGeometry(i); available = desktopWidget->availableGeometry(i); } - QVERIFY(total.contains(r)); } QTEST_MAIN(tst_QDesktopWidget) diff --git a/tests/auto/qfilesystementry/tst_qfilesystementry.cpp b/tests/auto/qfilesystementry/tst_qfilesystementry.cpp index 4375f99..dea6d2e 100644 --- a/tests/auto/qfilesystementry/tst_qfilesystementry.cpp +++ b/tests/auto/qfilesystementry/tst_qfilesystementry.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qfont/tst_qfont.cpp b/tests/auto/qfont/tst_qfont.cpp index 82c8f65..dabe3fa 100644 --- a/tests/auto/qfont/tst_qfont.cpp +++ b/tests/auto/qfont/tst_qfont.cpp @@ -150,6 +150,13 @@ void tst_QFont::exactMatch() return; #endif +#ifdef Q_WS_X11 + QVERIFY(QFont("sans").exactMatch()); + QVERIFY(QFont("sans-serif").exactMatch()); + QVERIFY(QFont("serif").exactMatch()); + QVERIFY(QFont("monospace").exactMatch()); +#endif + QSKIP("This test is bogus on Unix with support for font aliases in fontconfig", SkipAll); return; diff --git a/tests/auto/qglfunctions/tst_qglfunctions.cpp b/tests/auto/qglfunctions/tst_qglfunctions.cpp index 73e63b5..8756438 100644 --- a/tests/auto/qglfunctions/tst_qglfunctions.cpp +++ b/tests/auto/qglfunctions/tst_qglfunctions.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qglyphs/tst_qglyphs.cpp b/tests/auto/qglyphs/tst_qglyphs.cpp index da91063..1c0aa9e 100644 --- a/tests/auto/qglyphs/tst_qglyphs.cpp +++ b/tests/auto/qglyphs/tst_qglyphs.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp index bac17b1..837df78 100644 --- a/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp +++ b/tests/auto/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp @@ -2541,7 +2541,7 @@ void tst_QGraphicsGridLayout::geometries_data() << QRectF(0, 0, 50,10) << QRectF(50, 0, 50,10) << QRectF(0, 10, 50,100) << QRectF(50, 10, 50,400) ); -#if 0 + QTest::newRow("hfw-100x470") << (ItemList() << ItemDesc(0,0) .minSize(QSizeF(1,1)) @@ -2556,9 +2556,9 @@ void tst_QGraphicsGridLayout::geometries_data() .preferredSize(QSizeF(50,10)) .maxSize(QSizeF(100, 100)) << ItemDesc(1,1) - .minSize(QSizeF(40,40)) - .preferredSize(QSizeF(50,400)) - .maxSize(QSizeF(500, 500)) + .sizeHint(Qt::MinimumSize, QSizeF(40,40)) + .sizeHint(Qt::PreferredSize, QSizeF(50,400)) + .sizeHint(Qt::MaximumSize, QSizeF(500,500)) .dynamicConstraint(hfw1, Qt::Vertical) ) << QSizeF(100, 470) @@ -2567,7 +2567,6 @@ void tst_QGraphicsGridLayout::geometries_data() << QRectF(0, 70, 50,100) << QRectF(50, 70, 50,400) ); - // change layout width and verify QTest::newRow("hfw-100x401") << (ItemList() << ItemDesc(0,0) @@ -2583,9 +2582,9 @@ void tst_QGraphicsGridLayout::geometries_data() .preferredSize(QSizeF(50,10)) .maxSize(QSizeF(100, 100)) << ItemDesc(1,1) - .minSize(QSizeF(40,40)) - .preferredSize(QSizeF(50,400)) - .maxSize(QSizeF(5000, 5000)) + .minSize(QSizeF(-1,-1)) + .preferredSize(QSizeF(-1,-1)) + .maxSize(QSizeF(-1, -1)) .dynamicConstraint(hfw1, Qt::Vertical) ) << QSizeF(100, 401) @@ -2594,7 +2593,7 @@ void tst_QGraphicsGridLayout::geometries_data() << QRectF( 0, 1, 50, 100) << QRectF( 50, 1, 50, 400) ); - QTest::newRow("hfw-160x400") << (ItemList() + QTest::newRow("hfw-160x350") << (ItemList() << ItemDesc(0,0) .minSize(QSizeF(1,1)) .preferredSize(QSizeF(50,10)) @@ -2608,18 +2607,17 @@ void tst_QGraphicsGridLayout::geometries_data() .preferredSize(QSizeF(50,10)) .maxSize(QSizeF(100, 100)) << ItemDesc(1,1) - .minSize(QSizeF(40,40)) - .preferredSize(QSizeF(50,400)) - .maxSize(QSizeF(5000, 5000)) - .dynamicConstraint(hfw1, Qt::Vertical) + .sizeHint(Qt::MinimumSize, QSizeF(40,40)) + .sizeHint(Qt::PreferredSize, QSizeF(50,400)) + .sizeHint(Qt::MaximumSize, QSizeF(5000,5000)) + .dynamicConstraint(hfw1, Qt::Vertical) ) - << QSizeF(160, 400) + << QSizeF(160, 350) << (RectList() << QRectF( 0, 0, 80, 100) << QRectF( 80, 0, 80, 100) << QRectF( 0, 100, 80, 100) << QRectF( 80, 100, 80, 250) ); - QTest::newRow("hfw-160x300") << (ItemList() << ItemDesc(0,0) .minSize(QSizeF(1,1)) @@ -2634,9 +2632,9 @@ void tst_QGraphicsGridLayout::geometries_data() .preferredSize(QSizeF(50,10)) .maxSize(QSizeF(100, 100)) << ItemDesc(1,1) - .minSize(QSizeF(40,40)) - .preferredSize(QSizeF(50,400)) - .maxSize(QSizeF(5000, 5000)) + .sizeHint(Qt::MinimumSize, QSizeF(40,40)) + .sizeHint(Qt::PreferredSize, QSizeF(50,400)) + .sizeHint(Qt::MaximumSize, QSizeF(5000, 5000)) .dynamicConstraint(hfw1, Qt::Vertical) ) << QSizeF(160, 300) @@ -2647,11 +2645,11 @@ void tst_QGraphicsGridLayout::geometries_data() QTest::newRow("hfw-20x40") << (ItemList() << ItemDesc(0,0) - .minSize(QSizeF(1,1)) + .minSize(QSizeF(1,10)) .preferredSize(QSizeF(50,50)) .maxSize(QSizeF(100, 100)) << ItemDesc(0,1) - .minSize(QSizeF(1,10)) + .minSize(QSizeF(1,1)) .preferredSize(QSizeF(50,50)) .maxSize(QSizeF(100, 100)) << ItemDesc(1,0) @@ -2659,9 +2657,9 @@ void tst_QGraphicsGridLayout::geometries_data() .preferredSize(QSizeF(50,50)) .maxSize(QSizeF(100, 100)) << ItemDesc(1,1) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,50)) - .maxSize(QSizeF(100, 100)) + .sizeHint(Qt::MinimumSize, QSizeF(1, 1)) + .sizeHint(Qt::PreferredSize, QSizeF(50, 50)) + .sizeHint(Qt::MaximumSize, QSizeF(100, 100)) .dynamicConstraint(hfw3, Qt::Vertical) ) << QSizeF(20, 40) @@ -2684,9 +2682,9 @@ void tst_QGraphicsGridLayout::geometries_data() .preferredSize(QSizeF(10,50)) .maxSize(QSizeF(100, 100)) << ItemDesc(1,1) - .minSize(QSizeF(10,10)) - .preferredSize(QSizeF(400,50)) - .maxSize(QSizeF(5000, 5000)) + .sizeHint(Qt::MinimumSize, QSizeF(10,10)) + .sizeHint(Qt::PreferredSize, QSizeF(400,50)) + .sizeHint(Qt::MaximumSize, QSizeF(5000, 5000)) .dynamicConstraint(wfh1, Qt::Horizontal) ) << QSizeF(300, 160) @@ -2711,9 +2709,9 @@ void tst_QGraphicsGridLayout::geometries_data() .preferredSize(QSizeF(50,50)) .maxSize(QSizeF(100, 100)) << ItemDesc(1,1) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,50)) - .maxSize(QSizeF(100, 100)) + .sizeHint(Qt::MinimumSize, QSizeF(1,1)) + .sizeHint(Qt::PreferredSize, QSizeF(50,50)) + .sizeHint(Qt::MaximumSize, QSizeF(100, 100)) .dynamicConstraint(wfh2, Qt::Horizontal) ) << QSizeF(40, 20) @@ -2736,9 +2734,9 @@ void tst_QGraphicsGridLayout::geometries_data() .preferredSize(QSizeF(50,50)) .maxSize(QSizeF(100, 100)) << ItemDesc(1,1) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(50,50)) - .maxSize(QSizeF(100, 100)) + .sizeHint(Qt::MinimumSize, QSizeF(1,1)) + .sizeHint(Qt::PreferredSize, QSizeF(50,50)) + .sizeHint(Qt::MaximumSize, QSizeF(100, 100)) .dynamicConstraint(wfh2, Qt::Horizontal) ) @@ -2767,9 +2765,9 @@ void tst_QGraphicsGridLayout::geometries_data() .preferredSize(QSizeF(10,50)) .maxSize(QSizeF(100, 100)) << ItemDesc(1,1) - .minSize(QSizeF(1,1)) - .preferredSize(QSizeF(10,50)) - .maxSize(QSizeF(500, 500)) + .sizeHint(Qt::MinimumSize, QSizeF(1,1)) + .sizeHint(Qt::PreferredSize, QSizeF(10,50)) + .sizeHint(Qt::MaximumSize, QSizeF(500, 500)) .dynamicConstraint(wfh2, Qt::Horizontal) ) << QSizeF(160, 100) @@ -2777,7 +2775,6 @@ void tst_QGraphicsGridLayout::geometries_data() << QRectF(0, 0, 80, 50) << QRectF( 80, 0, 80, 50) << QRectF(0, 50, 80, 50) << QRectF( 80, 50, 50, 50) ); -#endif QTest::newRow("hfw-h470") << (ItemList() << ItemDesc(0,0) @@ -2804,7 +2801,6 @@ void tst_QGraphicsGridLayout::geometries_data() << QRectF(0, 70, 50,100) << QRectF(50, 70, 50,400) ); - // change layout width and verify QTest::newRow("hfw-w100") << (ItemList() << ItemDesc(0,0) @@ -3069,25 +3065,24 @@ void tst_QGraphicsGridLayout::heightForWidth() layout->setSpacing(0); RectWidget *w00 = new RectWidget; w00->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); - w00->setSizeHint(Qt::PreferredSize, QSizeF(50,50)); + w00->setSizeHint(Qt::PreferredSize, QSizeF(10,10)); w00->setSizeHint(Qt::MaximumSize, QSizeF(100,100)); layout->addItem(w00, 0, 0); RectWidget *w01 = new RectWidget; w01->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); - w01->setSizeHint(Qt::PreferredSize, QSizeF(50,50)); + w01->setSizeHint(Qt::PreferredSize, QSizeF(10,10)); w01->setSizeHint(Qt::MaximumSize, QSizeF(100,100)); layout->addItem(w01, 0, 1); RectWidget *w10 = new RectWidget; w10->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); - w10->setSizeHint(Qt::PreferredSize, QSizeF(50,50)); + w10->setSizeHint(Qt::PreferredSize, QSizeF(10,10)); w10->setSizeHint(Qt::MaximumSize, QSizeF(100,100)); layout->addItem(w10, 1, 0); RectWidget *w11 = new RectWidget; w11->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); - w11->setSizeHint(Qt::PreferredSize, QSizeF(50,400)); w11->setSizeHint(Qt::MaximumSize, QSizeF(30000,30000)); w11->setConstraintFunction(hfw); QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred); @@ -3096,34 +3091,37 @@ void tst_QGraphicsGridLayout::heightForWidth() layout->addItem(w11, 1, 1); QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, -1)), QSizeF(2, 2)); - QEXPECT_FAIL("", "QTBUG-14693", Continue); QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1)), QSizeF(210, 110)); QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, -1)), QSizeF(30100, 30100)); QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(2, -1)), QSizeF(2, 20001)); - QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 20050)); + QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 20010)); QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(2, -1)), QSizeF(2, 20100)); - QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(20, -1)), QSizeF(20, 1 + 2000)); - QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(20, -1)), QSizeF(20, 50 + 2000)); - QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(20, -1)), QSizeF(20, 100 + 2000)); + // Since 20 is somewhere between "minimum width hint" (2) and + // "preferred width hint" (210), it will try to do distribution by + // stretching them with different factors. + // Since column 1 has a "preferred width" of 200 it means that + // column 1 will be a bit wider than column 0. Thus it will also be a bit + // shorter than 2001, (the expected height if all columns had width=10) + QSizeF sh = layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(20, -1)); + // column 1 cannot be wider than 19, which means that it must be taller than 20000/19~=1052 + QVERIFY(sh.height() < 2000 + 1 && sh.height() > 1052 + 1); + + sh = layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(20, -1)); + QVERIFY(sh.height() < 2000 + 10 && sh.height() > 1052 + 10); - QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(300, -1)), QSizeF(300, 1 + 100)); - QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(300, -1)), QSizeF(300, 50 + 100)); - QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(300, -1)), QSizeF(300, 100 + 100)); + sh = layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(20, -1)); + QVERIFY(sh.height() < 2000 + 100 && sh.height() > 1052 + 100); // the height of the hfw widget is shorter than the one to the left, which is 100, so // the total height of the last row is 100 (which leaves the layout height to be 200) QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(500, -1)), QSizeF(500, 100 + 100)); - // hfw item size: (500, 40) -> preferred size is maxed up to preferred size of item w10 (50) - QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(600, -1)), QSizeF(600, 50 + 50)); - } void tst_QGraphicsGridLayout::widthForHeight() { -#if 0 QGraphicsWidget *widget = new QGraphicsWidget; QGraphicsGridLayout *layout = new QGraphicsGridLayout; widget->setLayout(layout); @@ -3150,9 +3148,10 @@ void tst_QGraphicsGridLayout::widthForHeight() layout->addItem(w10, 1, 0); RectWidget *w11 = new RectWidget; - w11->setMinimumSize(1,1); - w11->setPreferredSize(50, 50); - w11->setMaximumSize(30000,30000); + w11->setSizeHint(Qt::MinimumSize, QSizeF(1,1)); + w11->setSizeHint(Qt::PreferredSize, QSizeF(50,50)); + w11->setSizeHint(Qt::MaximumSize, QSizeF(30000,30000)); + // This will make sure its always square. w11->setConstraintFunction(wfh); QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred); @@ -3196,7 +3195,6 @@ void tst_QGraphicsGridLayout::widthForHeight() QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 300)), QSizeF(1 + 200, 300)); QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 300)), QSizeF(50 + 200, 300)); QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 300)), QSizeF(100 + 200, 300)); -#endif } void tst_QGraphicsGridLayout::heightForWidthWithSpanning() diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index dacb61e..168f75e 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -447,7 +447,8 @@ private slots: void updateMicroFocus(); void textItem_shortcuts(); void scroll(); - void stopClickFocusPropagation(); + void focusHandling_data(); + void focusHandling(); void deviceCoordinateCache_simpleRotations(); // task specific tests below me @@ -10537,8 +10538,39 @@ void tst_QGraphicsItem::scroll() QCOMPARE(item2->lastExposedRect, expectedItem2Expose); } -void tst_QGraphicsItem::stopClickFocusPropagation() +Q_DECLARE_METATYPE(QGraphicsItem::GraphicsItemFlag); + +void tst_QGraphicsItem::focusHandling_data() { + QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("focusFlag"); + QTest::addColumn<bool>("useStickyFocus"); + QTest::addColumn<int>("expectedFocusItem"); // 0: none, 1: focusableUnder, 2: itemWithFocus + + QTest::newRow("Focus goes through.") + << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << false << 1; + + QTest::newRow("Focus goes through, even with sticky scene.") + << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << true << 1; + + QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (but can still focus-out).") + << QGraphicsItem::ItemStopsClickFocusPropagation << false << 0; + + QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (and cannot focus-out if scene is sticky).") + << QGraphicsItem::ItemStopsClickFocusPropagation << true << 2; + + QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses.") + << QGraphicsItem::ItemStopsFocusHandling << false << 2; + + QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses (even if scene is sticky).") + << QGraphicsItem::ItemStopsFocusHandling << true << 2; +} + +void tst_QGraphicsItem::focusHandling() +{ + QFETCH(QGraphicsItem::GraphicsItemFlag, focusFlag); + QFETCH(bool, useStickyFocus); + QFETCH(int, expectedFocusItem); + class MyItem : public QGraphicsRectItem { public: @@ -10549,12 +10581,9 @@ void tst_QGraphicsItem::stopClickFocusPropagation() } }; - QGraphicsScene scene(-50, -50, 400, 400); - scene.setStickyFocus(true); - QGraphicsRectItem *noFocusOnTop = new MyItem; + noFocusOnTop->setFlag(QGraphicsItem::ItemIsFocusable, false); noFocusOnTop->setBrush(Qt::yellow); - noFocusOnTop->setFlag(QGraphicsItem::ItemStopsClickFocusPropagation); QGraphicsRectItem *focusableUnder = new MyItem; focusableUnder->setBrush(Qt::blue); @@ -10566,9 +10595,13 @@ void tst_QGraphicsItem::stopClickFocusPropagation() itemWithFocus->setFlag(QGraphicsItem::ItemIsFocusable); itemWithFocus->setPos(250, 10); + QGraphicsScene scene(-50, -50, 400, 400); scene.addItem(noFocusOnTop); scene.addItem(focusableUnder); scene.addItem(itemWithFocus); + scene.setStickyFocus(useStickyFocus); + + noFocusOnTop->setFlag(focusFlag); focusableUnder->stackBefore(noFocusOnTop); itemWithFocus->setFocus(); @@ -10580,14 +10613,28 @@ void tst_QGraphicsItem::stopClickFocusPropagation() QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); QVERIFY(itemWithFocus->hasFocus()); - QPointF mousePressPoint = noFocusOnTop->mapToScene(QPointF()); - mousePressPoint.rx() += 60; - mousePressPoint.ry() += 60; + const QPointF mousePressPoint = noFocusOnTop->mapToScene(noFocusOnTop->boundingRect().center()); const QList<QGraphicsItem *> itemsAtMousePressPosition = scene.items(mousePressPoint); - QVERIFY(itemsAtMousePressPosition.contains(focusableUnder)); + QVERIFY(itemsAtMousePressPosition.contains(noFocusOnTop)); sendMousePress(&scene, mousePressPoint); - QVERIFY(itemWithFocus->hasFocus()); + + switch (expectedFocusItem) { + case 0: + QCOMPARE(scene.focusItem(), static_cast<QGraphicsRectItem *>(0)); + break; + case 1: + QCOMPARE(scene.focusItem(), focusableUnder); + break; + case 2: + QCOMPARE(scene.focusItem(), itemWithFocus); + break; + } + + // Sanity check - manually setting the focus must work regardless of our + // focus handling flags: + focusableUnder->setFocus(); + QCOMPARE(scene.focusItem(), focusableUnder); } void tst_QGraphicsItem::deviceCoordinateCache_simpleRotations() diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index d446ca7..9ff086c 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -289,6 +289,7 @@ private slots: void taskQTBUG_7863_paintIntoCacheWithTransparentParts(); void taskQT_3674_doNotCrash(); void taskQTBUG_15977_renderWithDeviceCoordinateCache(); + void taskQTBUG_16401_focusItem(); }; void tst_QGraphicsScene::initTestCase() @@ -4680,5 +4681,35 @@ void tst_QGraphicsScene::taskQTBUG_15977_renderWithDeviceCoordinateCache() QCOMPARE(image, expected); } +void tst_QGraphicsScene::taskQTBUG_16401_focusItem() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100); + rect->setFlag(QGraphicsItem::ItemIsFocusable); + + view.show(); + QTest::qWaitForWindowShown(&view); + QApplication::setActiveWindow(&view); + + QVERIFY(!scene.focusItem()); + + rect->setFocus(); + QCOMPARE(scene.focusItem(), rect); + QFocusEvent focusOut(QEvent::FocusOut); + QApplication::sendEvent(&view, &focusOut); + QVERIFY(!scene.focusItem()); + QFocusEvent focusIn(QEvent::FocusIn); + QApplication::sendEvent(&view, &focusIn); + QCOMPARE(scene.focusItem(), rect); + + rect->clearFocus(); + QVERIFY(!scene.focusItem()); + QApplication::sendEvent(&view, &focusOut); + QVERIFY(!scene.focusItem()); + QApplication::sendEvent(&view, &focusIn); + QVERIFY(!scene.focusItem()); +} + QTEST_MAIN(tst_QGraphicsScene) #include "tst_qgraphicsscene.moc" diff --git a/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp b/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp index 79f2213..9434a0b 100644 --- a/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp +++ b/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp @@ -163,10 +163,11 @@ static inline bool fuzzyCompare(qreal p1, qreal p2) { // increase delta on small machines using float instead of double if (sizeof(qreal) == sizeof(float)) - return (qAbs(p1 - p2) <= 0.00002f * qMin(qAbs(p1), qAbs(p2))); + return (qAbs(p1 - p2) <= 0.00003f * qMin(qAbs(p1), qAbs(p2))); else return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2))); } + static bool fuzzyCompare(const QTransform& t1, const QTransform& t2) { return fuzzyCompare(t1.m11(), t2.m11()) && @@ -180,6 +181,15 @@ static bool fuzzyCompare(const QTransform& t1, const QTransform& t2) fuzzyCompare(t1.m33(), t2.m33()); } +static inline bool fuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2) +{ + bool ok = true; + for (int y = 0; y < 4; ++y) + for (int x = 0; x < 4; ++x) + ok &= fuzzyCompare(m1(y, x), m2(y, x)); + return ok; +} + void tst_QGraphicsTransform::rotation() { QGraphicsRotation rotation; @@ -267,7 +277,7 @@ void tst_QGraphicsTransform::rotation3d() // because the deg2rad value in QTransform is not accurate // enough to match what QMatrix4x4 is doing. } else { - QVERIFY(qFuzzyCompare(t, r)); + QVERIFY(fuzzyCompare(t, r)); } //now let's check that a null vector will not change the transform diff --git a/tests/auto/qheaderview/tst_qheaderview.cpp b/tests/auto/qheaderview/tst_qheaderview.cpp index db71e39..9a25fb6 100644 --- a/tests/auto/qheaderview/tst_qheaderview.cpp +++ b/tests/auto/qheaderview/tst_qheaderview.cpp @@ -195,6 +195,8 @@ private slots: void QTBUG8650_crashOnInsertSections(); void QTBUG12268_hiddenMovedSectionSorting(); + void initialSortOrderRole(); + protected: QWidget *topLevel; QHeaderView *view; @@ -2097,5 +2099,40 @@ void tst_QHeaderView::QTBUG12268_hiddenMovedSectionSorting() QCOMPARE(view.horizontalHeader()->hiddenSectionCount(), 1); } +void tst_QHeaderView::initialSortOrderRole() +{ + QTableView view; + QStandardItemModel *model = new QStandardItemModel(4, 3, &view); + for (int i = 0; i< model->rowCount(); ++i) + for (int j = 0; j< model->columnCount(); ++j) + model->setData(model->index(i,j), QString("item [%1,%2]").arg(i).arg(j)); + QStandardItem *ascendingItem = new QStandardItem(); + QStandardItem *descendingItem = new QStandardItem(); + ascendingItem->setData(Qt::AscendingOrder, Qt::InitialSortOrderRole); + descendingItem->setData(Qt::DescendingOrder, Qt::InitialSortOrderRole); + model->setHorizontalHeaderItem(1, ascendingItem); + model->setHorizontalHeaderItem(2, descendingItem); + view.setModel(model); + view.setSortingEnabled(true); + view.sortByColumn(0, Qt::AscendingOrder); + view.show(); + QTest::qWaitForWindowShown(&view); + + const int column1Pos = view.horizontalHeader()->sectionViewportPosition(1) + 5; // +5 not to be on the handle + QTest::mouseClick(view.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(column1Pos, 0)); + QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 1); + QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::AscendingOrder); + + const int column2Pos = view.horizontalHeader()->sectionViewportPosition(2) + 5; // +5 not to be on the handle + QTest::mouseClick(view.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(column2Pos, 0)); + QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 2); + QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::DescendingOrder); + + const int column0Pos = view.horizontalHeader()->sectionViewportPosition(0) + 5; // +5 not to be on the handle + QTest::mouseClick(view.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(column0Pos, 0)); + QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 0); + QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::AscendingOrder); +} + QTEST_MAIN(tst_QHeaderView) #include "tst_qheaderview.moc" diff --git a/tests/auto/qlocale/tst_qlocale.cpp b/tests/auto/qlocale/tst_qlocale.cpp index 16846de..6f4de91 100644 --- a/tests/auto/qlocale/tst_qlocale.cpp +++ b/tests/auto/qlocale/tst_qlocale.cpp @@ -140,6 +140,11 @@ private slots: #endif void ampm(); + void currency(); + void quoteString(); + void uiLanguages(); + void weekendDays(); + void listPatterns(); private: QString m_decimal, m_thousand, m_sdate, m_ldate, m_time; @@ -181,6 +186,7 @@ void tst_QLocale::ctor() QCOMPARE(l.language(), QLocale::C); QCOMPARE(l.country(), QLocale::AnyCountry); } + TEST_CTOR(AnyLanguage, AnyCountry, default_lang, default_country) TEST_CTOR(C, AnyCountry, QLocale::C, QLocale::AnyCountry) TEST_CTOR(Aymara, AnyCountry, default_lang, default_country) TEST_CTOR(Aymara, France, default_lang, default_country) @@ -306,6 +312,7 @@ void tst_QLocale::ctor() TEST_CTOR("en@", English, UnitedStates) TEST_CTOR("en.@", English, UnitedStates) TEST_CTOR("en_", English, UnitedStates) + TEST_CTOR("en_U", English, UnitedStates) TEST_CTOR("en_.", English, UnitedStates) TEST_CTOR("en_.@", English, UnitedStates) TEST_CTOR("en.bla", English, UnitedStates) @@ -316,6 +323,8 @@ void tst_QLocale::ctor() TEST_CTOR("en_GB.bla", English, UnitedKingdom) TEST_CTOR("en_GB@.bla", English, UnitedKingdom) TEST_CTOR("en_GB@bla", English, UnitedKingdom) + TEST_CTOR("en-GB", English, UnitedKingdom) + TEST_CTOR("en-GB@bla", English, UnitedKingdom) Q_ASSERT(QLocale::Norwegian == QLocale::NorwegianBokmal); TEST_CTOR("no", Norwegian, Norway) @@ -326,13 +335,38 @@ void tst_QLocale::ctor() TEST_CTOR("nn_NO", NorwegianNynorsk, Norway) TEST_CTOR("es_ES", Spanish, Spain) TEST_CTOR("es_419", Spanish, LatinAmericaAndTheCaribbean) + TEST_CTOR("es-419", Spanish, LatinAmericaAndTheCaribbean) // test default countries for languages + TEST_CTOR("zh", Chinese, China) + TEST_CTOR("zh-Hans", Chinese, China) TEST_CTOR("mn", Mongolian, Mongolia) TEST_CTOR("ne", Nepali, Nepal) #undef TEST_CTOR +#define TEST_CTOR(req_lc, exp_lang, exp_script, exp_country) \ + { \ + QLocale l(req_lc); \ + QVERIFY2(l.language() == QLocale::exp_lang \ + && l.script() == QLocale::exp_script \ + && l.country() == QLocale::exp_country, \ + QString("requested: \"" + QString(req_lc) + "\", got: " \ + + QLocale::languageToString(l.language()) \ + + "/" + QLocale::scriptToString(l.script()) \ + + "/" + QLocale::countryToString(l.country())).toLatin1().constData()); \ + } + + TEST_CTOR("zh_CN", Chinese, AnyScript, China) + TEST_CTOR("zh_Hans_CN", Chinese, SimplifiedHanScript, China) + TEST_CTOR("zh_Hans", Chinese, SimplifiedHanScript, China) + TEST_CTOR("zh_Hant", Chinese, TraditionalHanScript, HongKong) + TEST_CTOR("zh_Hans_MO", Chinese, SimplifiedHanScript, Macau) + TEST_CTOR("zh_Hant_MO", Chinese, TraditionalHanScript, Macau) + TEST_CTOR("az_Latn_AZ", Azerbaijani, LatinScript, Azerbaijan) + TEST_CTOR("ha_Arab_NG", Hausa, ArabicScript, Nigeria) + TEST_CTOR("ha_Latn_NG", Hausa, LatinScript, Nigeria) +#undef TEST_CTOR } void tst_QLocale::emptyCtor() @@ -405,11 +439,12 @@ void tst_QLocale::emptyCtor() TEST_CTOR("nb_NO", "nb_NO") TEST_CTOR("nn_NO", "nn_NO") + TEST_CTOR("DE", "de_DE"); + TEST_CTOR("EN", "en_US"); + TEST_CTOR("en/", defaultLoc) - TEST_CTOR("DE", defaultLoc); TEST_CTOR("asdfghj", defaultLoc); TEST_CTOR("123456", defaultLoc); - TEST_CTOR("EN", defaultLoc); #undef TEST_CTOR #endif @@ -1095,6 +1130,11 @@ void tst_QLocale::macDefaultLocale() const QString timeString = locale.toString(QTime(1,2,3), QLocale::LongFormat); QVERIFY(timeString.contains(QString("1:02:03"))); + QCOMPARE(locale.toCurrencyString(qulonglong(1234)), QString("$1,234")); + QCOMPARE(locale.toCurrencyString(qlonglong(-1234)), QString("$-1,234")); + QCOMPARE(locale.toCurrencyString(double(1234.56)), QString("$1,234.56")); + QCOMPARE(locale.toCurrencyString(double(-1234.56)), QString("$-1,234.56")); + // Depending on the configured time zone, the time string might not // contain a GMT specifier. (Sometimes it just names the zone, like "CEST") if (timeString.contains(QString("GMT"))) { @@ -1113,6 +1153,13 @@ void tst_QLocale::macDefaultLocale() QCOMPARE(locale.dayName(7), QString("Sunday")); QCOMPARE(locale.monthName(1), QString("January")); QCOMPARE(locale.monthName(12), QString("December")); + QCOMPARE(locale.firstDayOfWeek(), Qt::Sunday); + QCOMPARE(locale.quoteString("string"), QString::fromUtf8("\xe2\x80\x9c" "string" "\xe2\x80\x9d")); + QCOMPARE(locale.quoteString("string", QLocale::AlternateQuotation), QString::fromUtf8("\xe2\x80\x98" "string" "\xe2\x80\x99")); + + QList<Qt::DayOfWeek> days; + days << Qt::Monday << Qt::Tuesday << Qt::Wednesday << Qt::Thursday << Qt::Friday; + QCOMPARE(locale.weekdays(), days); } @@ -1768,6 +1815,7 @@ void tst_QLocale::measurementSystems_data() void tst_QLocale::measurementSystems() { + QSKIP("Meh, skip the test as we do not reread the environment variables anymore", SkipAll); QFETCH(QString, localeName); QFETCH(int, mSystem); @@ -1829,6 +1877,7 @@ void tst_QLocale::systemMeasurementSystems_data() void tst_QLocale::systemMeasurementSystems() { + QSKIP("Meh, skip the test as we do not reread the environment variables anymore", SkipAll); // Theoretically, we could include HPUX in this test, but its setenv implementation // stinks. It's called putenv, and it requires you to keep the variable you pass // to it around forever. @@ -1951,6 +2000,7 @@ void tst_QLocale::queryMeasureSystem_data() void tst_QLocale::queryMeasureSystem() { + QSKIP("Meh, skip the test as we do not reread the environment variables anymore", SkipAll); // Theoretically, we could include HPUX in this test, but its setenv implementation // stinks. It's called putenv, and it requires you to keep the variable you pass // to it around forever. @@ -2066,6 +2116,10 @@ void tst_QLocale::monthName() QCOMPARE(ru.monthName(1, QLocale::LongFormat), QString::fromUtf8("\321\217\320\275\320\262\320\260\321\200\321\217")); QCOMPARE(ru.monthName(1, QLocale::ShortFormat), QString::fromUtf8("\321\217\320\275\320\262\56")); QCOMPARE(ru.monthName(1, QLocale::NarrowFormat), QString::fromUtf8("\320\257")); + + // check that our CLDR scripts handle surrogate pairs correctly + QLocale dsrt("en-Dsrt-US"); + QCOMPARE(dsrt.monthName(1, QLocale::LongFormat), QString::fromUtf8("\xf0\x90\x90\x96\xf0\x90\x90\xb0\xf0\x90\x91\x8c\xf0\x90\x90\xb7\xf0\x90\x90\xad\xf0\x90\x90\xaf\xf0\x90\x91\x89\xf0\x90\x90\xa8")); } void tst_QLocale::standaloneMonthName() @@ -2123,5 +2177,102 @@ void tst_QLocale::symbianSystemLocale() } #endif +void tst_QLocale::currency() +{ + const QLocale c(QLocale::C); + QCOMPARE(c.toCurrencyString(qulonglong(1234)), QString("1234")); + QCOMPARE(c.toCurrencyString(qlonglong(-1234)), QString("-1234")); + QCOMPARE(c.toCurrencyString(double(1234.56)), QString("1234.56")); + QCOMPARE(c.toCurrencyString(double(-1234.56)), QString("-1234.56")); + + const QLocale ru_RU("ru_RU"); + QCOMPARE(ru_RU.toCurrencyString(qulonglong(1234)), QString::fromUtf8("1234\xc2\xa0\xd1\x80\xd1\x83\xd0\xb1.")); + QCOMPARE(ru_RU.toCurrencyString(qlonglong(-1234)), QString::fromUtf8("-1234\xc2\xa0\xd1\x80\xd1\x83\xd0\xb1.")); + QCOMPARE(ru_RU.toCurrencyString(double(1234.56)), QString::fromUtf8("1234,56\xc2\xa0\xd1\x80\xd1\x83\xd0\xb1.")); + QCOMPARE(ru_RU.toCurrencyString(double(-1234.56)), QString::fromUtf8("-1234,56\xc2\xa0\xd1\x80\xd1\x83\xd0\xb1.")); + + const QLocale de_DE("de_DE"); + QCOMPARE(de_DE.toCurrencyString(qulonglong(1234)), QString::fromUtf8("1234\xc2\xa0\xe2\x82\xac")); + QCOMPARE(de_DE.toCurrencyString(qulonglong(1234), QLatin1String("BAZ")), QString::fromUtf8("1234\xc2\xa0" "BAZ")); + QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234)), QString::fromUtf8("-1234\xc2\xa0\xe2\x82\xac")); + QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234), QLatin1String("BAZ")), QString::fromUtf8("-1234\xc2\xa0" "BAZ")); + QCOMPARE(de_DE.toCurrencyString(double(1234.56)), QString::fromUtf8("1234,56\xc2\xa0\xe2\x82\xac")); + QCOMPARE(de_DE.toCurrencyString(double(-1234.56)), QString::fromUtf8("-1234,56\xc2\xa0\xe2\x82\xac")); + QCOMPARE(de_DE.toCurrencyString(double(-1234.56), QLatin1String("BAZ")), QString::fromUtf8("-1234,56\xc2\xa0" "BAZ")); + + const QLocale system = QLocale::system(); + QVERIFY(system.toCurrencyString(1, QLatin1String("FOO")).contains(QLatin1String("FOO"))); +} + +void tst_QLocale::quoteString() +{ + const QString someText("text"); + const QLocale c(QLocale::C); + QCOMPARE(c.quoteString(someText), QString::fromUtf8("\x22" "text" "\x22")); + QCOMPARE(c.quoteString(someText, QLocale::AlternateQuotation), QString::fromUtf8("\x27" "text" "\x27")); + + const QLocale de_CH("de_CH"); + QCOMPARE(de_CH.quoteString(someText), QString::fromUtf8("\xc2\xab" "text" "\xc2\xbb")); + QCOMPARE(de_CH.quoteString(someText, QLocale::AlternateQuotation), QString::fromUtf8("\xe2\x80\xb9" "text" "\xe2\x80\xba")); + +} + +void tst_QLocale::uiLanguages() +{ + const QLocale c(QLocale::C); + QCOMPARE(c.uiLanguages().size(), 1); + QCOMPARE(c.uiLanguages().at(0), QLatin1String("C")); + + const QLocale en_US("en_US"); + QCOMPARE(en_US.uiLanguages().size(), 1); + QCOMPARE(en_US.uiLanguages().at(0), QLatin1String("en-US")); + + const QLocale ru_RU("ru_RU"); + QCOMPARE(ru_RU.uiLanguages().size(), 1); + QCOMPARE(ru_RU.uiLanguages().at(0), QLatin1String("ru-RU")); +} + +void tst_QLocale::weekendDays() +{ + const QLocale c(QLocale::C); + QList<Qt::DayOfWeek> days; + days << Qt::Monday << Qt::Tuesday << Qt::Wednesday << Qt::Thursday << Qt::Friday; + QCOMPARE(c.weekdays(), days); +} + +void tst_QLocale::listPatterns() +{ + QStringList sl1; + QStringList sl2; + sl2 << "aaa"; + QStringList sl3; + sl3 << "aaa" << "bbb"; + QStringList sl4; + sl4 << "aaa" << "bbb" << "ccc"; + QStringList sl5; + sl5 << "aaa" << "bbb" << "ccc" << "ddd"; + + const QLocale c(QLocale::C); + QCOMPARE(c.createSeparatedList(sl1), QString("")); + QCOMPARE(c.createSeparatedList(sl2), QString("aaa")); + QCOMPARE(c.createSeparatedList(sl3), QString("aaa, bbb")); + QCOMPARE(c.createSeparatedList(sl4), QString("aaa, bbb, ccc")); + QCOMPARE(c.createSeparatedList(sl5), QString("aaa, bbb, ccc, ddd")); + + const QLocale en_US("en_US"); + QCOMPARE(en_US.createSeparatedList(sl1), QString("")); + QCOMPARE(en_US.createSeparatedList(sl2), QString("aaa")); + QCOMPARE(en_US.createSeparatedList(sl3), QString("aaa and bbb")); + QCOMPARE(en_US.createSeparatedList(sl4), QString("aaa, bbb, and ccc")); + QCOMPARE(en_US.createSeparatedList(sl5), QString("aaa, bbb, ccc, and ddd")); + + const QLocale zh_CN("zh_CN"); + QCOMPARE(zh_CN.createSeparatedList(sl1), QString("")); + QCOMPARE(zh_CN.createSeparatedList(sl2), QString("aaa")); + QCOMPARE(zh_CN.createSeparatedList(sl3), QString::fromUtf8("aaa" "\xe5\x92\x8c" "bbb")); + QCOMPARE(zh_CN.createSeparatedList(sl4), QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe5\x92\x8c" "ccc")); + QCOMPARE(zh_CN.createSeparatedList(sl5), QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe3\x80\x81" "ccc" "\xe5\x92\x8c" "ddd")); +} + QTEST_APPLESS_MAIN(tst_QLocale) #include "tst_qlocale.moc" diff --git a/tests/auto/qmdiarea/tst_qmdiarea.cpp b/tests/auto/qmdiarea/tst_qmdiarea.cpp index d44e632..67d3d0d 100644 --- a/tests/auto/qmdiarea/tst_qmdiarea.cpp +++ b/tests/auto/qmdiarea/tst_qmdiarea.cpp @@ -287,6 +287,8 @@ private slots: void setActivationOrder(); void tabBetweenSubWindows(); void setViewMode(); + void setTabsClosable(); + void setTabsMovable(); void setTabShape(); void setTabPosition_data(); void setTabPosition(); @@ -2464,6 +2466,77 @@ void tst_QMdiArea::setViewMode() QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView); } +void tst_QMdiArea::setTabsClosable() +{ + QMdiArea mdiArea; + mdiArea.addSubWindow(new QWidget); + + // test default + QCOMPARE(mdiArea.tabsClosable(), false); + + // change value before tab bar exists + QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea); + QVERIFY(!tabBar); + mdiArea.setTabsClosable(true); + QCOMPARE(mdiArea.tabsClosable(), true); + + // force tab bar creation + mdiArea.setViewMode(QMdiArea::TabbedView); + tabBar = qFindChild<QTabBar *>(&mdiArea); + QVERIFY(tabBar); + + // value must've been propagated + QCOMPARE(tabBar->tabsClosable(), true); + + // change value when tab bar exists + mdiArea.setTabsClosable(false); + QCOMPARE(mdiArea.tabsClosable(), false); + QCOMPARE(tabBar->tabsClosable(), false); +} + +void tst_QMdiArea::setTabsMovable() +{ + QMdiArea mdiArea; + QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(new QWidget); + QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(new QWidget); + QMdiSubWindow *subWindow3 = mdiArea.addSubWindow(new QWidget); + + // test default + QCOMPARE(mdiArea.tabsMovable(), false); + + // change value before tab bar exists + QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea); + QVERIFY(!tabBar); + mdiArea.setTabsMovable(true); + QCOMPARE(mdiArea.tabsMovable(), true); + + // force tab bar creation + mdiArea.setViewMode(QMdiArea::TabbedView); + tabBar = qFindChild<QTabBar *>(&mdiArea); + QVERIFY(tabBar); + + // value must've been propagated + QCOMPARE(tabBar->isMovable(), true); + + // test tab moving + QList<QMdiSubWindow *> subWindows; + subWindows << subWindow1 << subWindow2 << subWindow3; + QCOMPARE(mdiArea.subWindowList(QMdiArea::CreationOrder), subWindows); + tabBar->moveTab(1, 2); // 1,3,2 + subWindows.clear(); + subWindows << subWindow1 << subWindow3 << subWindow2; + QCOMPARE(mdiArea.subWindowList(QMdiArea::CreationOrder), subWindows); + tabBar->moveTab(0, 2); // 3,2,1 + subWindows.clear(); + subWindows << subWindow3 << subWindow2 << subWindow1; + QCOMPARE(mdiArea.subWindowList(QMdiArea::CreationOrder), subWindows); + + // change value when tab bar exists + mdiArea.setTabsMovable(false); + QCOMPARE(mdiArea.tabsMovable(), false); + QCOMPARE(tabBar->isMovable(), false); +} + void tst_QMdiArea::setTabShape() { QMdiArea mdiArea; diff --git a/tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp b/tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp index 42bb069..f7c5ca1 100644 --- a/tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp +++ b/tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp @@ -58,6 +58,7 @@ public: tst_QNetworkAccessManager_And_QProgressDialog(); private slots: void downloadCheck(); + void downloadCheck_data(); }; class DownloadCheckWidget : public QWidget @@ -72,9 +73,14 @@ public: QMetaObject::invokeMethod(this, "go", Qt::QueuedConnection); } bool lateReadyRead; + bool zeroCopy; public slots: void go() { + QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile")); + if (zeroCopy) + request.setAttribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute, 10*1024*1024); + QNetworkReply *reply = netmanager.get( QNetworkRequest( QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile") @@ -106,20 +112,30 @@ public slots: QTestEventLoop::instance().exitLoop(); } - private: QProgressDialog progressDlg; QNetworkAccessManager netmanager; }; + tst_QNetworkAccessManager_And_QProgressDialog::tst_QNetworkAccessManager_And_QProgressDialog() { Q_SET_DEFAULT_IAP } +void tst_QNetworkAccessManager_And_QProgressDialog::downloadCheck_data() +{ + QTest::addColumn<bool>("useZeroCopy"); + QTest::newRow("with-zeroCopy") << true; + QTest::newRow("without-zeroCopy") << false; +} + void tst_QNetworkAccessManager_And_QProgressDialog::downloadCheck() { + QFETCH(bool, useZeroCopy); + DownloadCheckWidget widget; + widget.zeroCopy = useZeroCopy; widget.show(); // run and exit on finished() QTestEventLoop::instance().enterLoop(10); diff --git a/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp b/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp index 0c89013..91dfe47 100644 --- a/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp +++ b/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp @@ -171,16 +171,16 @@ void tst_QNetworkCookie::parseSingleCookie_data() QTest::newRow("with-value7") << "a = b" << cookie; QTest::newRow("with-value8") << "a = b " << cookie; - cookie.setValue(","); + cookie.setValue("\",\""); QTest::newRow("with-value-with-special1") << "a = \",\" " << cookie; - cookie.setValue(";"); + cookie.setValue("\";\""); QTest::newRow("with-value-with-special2") << "a = \";\" " << cookie; - cookie.setValue(" "); + cookie.setValue("\" \""); QTest::newRow("with-value-with-special3") << "a = \" \" " << cookie; - cookie.setValue("\""); - QTest::newRow("with-value-with-special3") << "a = \"\\\"\" " << cookie; - cookie.setValue("\"a, b; c\""); - QTest::newRow("with-value-with-special4") << "a = \"\\\"a, b; c\\\"\"" << cookie; + cookie.setValue("\"\\\"\""); + QTest::newRow("with-value-with-special4") << "a = \"\\\"\" " << cookie; + cookie.setValue("\"\\\"a, b; c\\\"\""); + QTest::newRow("with-value-with-special5") << "a = \"\\\"a, b; c\\\"\"" << cookie; cookie.setValue("b"); cookie.setSecure(true); @@ -568,10 +568,18 @@ void tst_QNetworkCookie::parseSingleCookie_data() cookie.setDomain("mail.yahoo.com"); QTest::newRow("network3") << "YM.LC=v=2&m=9993_262838_159_1558_1063_0_5649_4012_3776161073,9426_260205_549_1295_1336_0_5141_4738_3922731647,6733_258196_952_1364_643_0_3560_-1_0,3677_237633_1294_1294_19267_0_3244_29483_4102206176,1315_235149_1693_1541_941_0_3224_1691_1861378060,1858_214311_2100_1298_19538_0_2873_30900_716411652,6258_212007_2506_1285_1017_0_2868_3606_4288540264,3743_207884_2895_1362_2759_0_2545_7114_3388520216,2654_205253_3257_1297_1332_0_2504_4682_3048534803,1891_184881_3660_1291_19079_0_978_29178_2592538685&f=1&n=20&s=date&o=down&e=1196548712&b=Inbox&u=removed; path=/; domain=mail.yahoo.com" << cookie; - cookie = QNetworkCookie("__ac", "c2hhdXNtYW46U2FTYW80Wm8%3D"); + cookie = QNetworkCookie("__ac", "\"c2hhdXNtYW46U2FTYW80Wm8%3D\""); cookie.setPath("/"); cookie.setExpirationDate(QDateTime(QDate(2008, 8, 30), QTime(20, 21, 49), Qt::UTC)); QTest::newRow("network4") << "__ac=\"c2hhdXNtYW46U2FTYW80Wm8%3D\"; Path=/; Expires=Sat, 30 Aug 2008 20:21:49 +0000" << cookie; + + // linkedin.com sends cookies in quotes and expects the cookie in quotes + cookie = QNetworkCookie("leo_auth_token", "\"GST:UroVXaxYA3sVSkoVjMNH9bj4dZxVzK2yekgrAUxMfUsyLTNyPjoP60:1298974875:b675566ae32ab36d7a708c0efbf446a5c22b9fca\""); + cookie.setPath("/"); + cookie.setExpirationDate(QDateTime(QDate(2011, 3, 1), QTime(10, 51, 14), Qt::UTC)); + QTest::newRow("network5") << "leo_auth_token=\"GST:UroVXaxYA3sVSkoVjMNH9bj4dZxVzK2yekgrAUxMfUsyLTNyPjoP60:1298974875:b675566ae32ab36d7a708c0efbf446a5c22b9fca\"; Version=1; Max-Age=1799; Expires=Tue, 01-Mar-2011 10:51:14 GMT; Path=/" << cookie; + + } void tst_QNetworkCookie::parseSingleCookie() diff --git a/tests/auto/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp b/tests/auto/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp index 41da16e..2baee27 100644 --- a/tests/auto/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp +++ b/tests/auto/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qnetworkreply/image1.jpg b/tests/auto/qnetworkreply/image1.jpg Binary files differnew file mode 100644 index 0000000..dba31c1 --- /dev/null +++ b/tests/auto/qnetworkreply/image1.jpg diff --git a/tests/auto/qnetworkreply/image2.jpg b/tests/auto/qnetworkreply/image2.jpg Binary files differnew file mode 100644 index 0000000..72936e2 --- /dev/null +++ b/tests/auto/qnetworkreply/image2.jpg diff --git a/tests/auto/qnetworkreply/image3.jpg b/tests/auto/qnetworkreply/image3.jpg Binary files differnew file mode 100644 index 0000000..cede519 --- /dev/null +++ b/tests/auto/qnetworkreply/image3.jpg diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index a5f1577..4b8dc3b 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -61,6 +61,8 @@ #include <QtNetwork/qnetworkrequest.h> #include <QtNetwork/qnetworkreply.h> #include <QtNetwork/qnetworkcookie.h> +#include <QtNetwork/QHttpPart> +#include <QtNetwork/QHttpMultiPart> #ifndef QT_NO_OPENSSL #include <QtNetwork/qsslerror.h> #include <QtNetwork/qsslconfiguration.h> @@ -89,6 +91,8 @@ Q_DECLARE_METATYPE(QNetworkProxyQuery) Q_DECLARE_METATYPE(QList<QNetworkProxy>) Q_DECLARE_METATYPE(QNetworkReply::NetworkError) Q_DECLARE_METATYPE(QBuffer*) +Q_DECLARE_METATYPE(QHttpMultiPart *) +Q_DECLARE_METATYPE(QList<QFile*>) // for multiparts class QNetworkReplyPtr: public QSharedPointer<QNetworkReply> { @@ -150,6 +154,8 @@ public: ~tst_QNetworkReply(); QString runSimpleRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QNetworkReplyPtr &reply, const QByteArray &data = QByteArray()); + QString runMultipartRequest(const QNetworkRequest &request, QNetworkReplyPtr &reply, + QHttpMultiPart *multiPart, const QByteArray &verb); QString runCustomRequest(const QNetworkRequest &request, QNetworkReplyPtr &reply, const QByteArray &verb, QIODevice *data); @@ -196,10 +202,14 @@ private Q_SLOTS: void putToHttp(); void putToHttpSynchronous_data(); void putToHttpSynchronous(); + void putToHttpMultipart_data(); + void putToHttpMultipart(); void postToHttp_data(); void postToHttp(); void postToHttpSynchronous_data(); void postToHttpSynchronous(); + void postToHttpMultipart_data(); + void postToHttpMultipart(); void deleteFromHttp_data(); void deleteFromHttp(); void putGetDeleteGetFromHttp_data(); @@ -348,6 +358,8 @@ private Q_SLOTS: void qtbug15311doubleContentLength(); + void qtbug18232gzipContentLengthZero(); + void synchronousRequest_data(); void synchronousRequest(); #ifndef QT_NO_OPENSSL @@ -356,6 +368,8 @@ private Q_SLOTS: void httpAbort(); + void dontInsertPartialContentIntoTheCache(); + // NOTE: This test must be last! void parentingRepliesToTheApp(); }; @@ -516,7 +530,6 @@ public slots: if (doClose && client->bytesToWrite() == 0) { client->disconnectFromHost(); disconnect(client, 0, this, 0); - client = 0; } } @@ -613,6 +626,63 @@ public: Q_DECLARE_METATYPE(MyMemoryCache::CachedContent) Q_DECLARE_METATYPE(MyMemoryCache::CacheData) +class MySpyMemoryCache: public QAbstractNetworkCache +{ +public: + MySpyMemoryCache(QObject *parent) : QAbstractNetworkCache(parent) {} + ~MySpyMemoryCache() + { + qDeleteAll(m_buffers); + m_buffers.clear(); + } + + QHash<QUrl, QIODevice*> m_buffers; + QList<QUrl> m_insertedUrls; + + QNetworkCacheMetaData metaData(const QUrl &) + { + return QNetworkCacheMetaData(); + } + + void updateMetaData(const QNetworkCacheMetaData &) + { + } + + QIODevice *data(const QUrl &) + { + return 0; + } + + bool remove(const QUrl &url) + { + delete m_buffers.take(url); + return m_insertedUrls.removeAll(url) > 0; + } + + qint64 cacheSize() const + { + return 0; + } + + QIODevice *prepare(const QNetworkCacheMetaData &metaData) + { + QBuffer* buffer = new QBuffer; + buffer->open(QIODevice::ReadWrite); + buffer->setProperty("url", metaData.url()); + m_buffers.insert(metaData.url(), buffer); + return buffer; + } + + void insert(QIODevice *buffer) + { + QUrl url = buffer->property("url").toUrl(); + m_insertedUrls << url; + delete m_buffers.take(url); + } + + void clear() { m_insertedUrls.clear(); } +}; + class DataReader: public QObject { Q_OBJECT @@ -993,6 +1063,7 @@ tst_QNetworkReply::tst_QNetworkReply() #ifndef QT_NO_OPENSSL qRegisterMetaType<QList<QSslError> >(); #endif + qRegisterMetaType<QNetworkReply::NetworkError>(); Q_SET_DEFAULT_IAP @@ -1054,6 +1125,38 @@ void tst_QNetworkReply::storeSslConfiguration() } #endif +QString tst_QNetworkReply::runMultipartRequest(const QNetworkRequest &request, + QNetworkReplyPtr &reply, + QHttpMultiPart *multiPart, + const QByteArray &verb) +{ + if (verb == "POST") + reply = manager.post(request, multiPart); + else + reply = manager.put(request, multiPart); + + // the code below is copied from tst_QNetworkReply::runSimpleRequest, see below + reply->setParent(this); + connect(reply, SIGNAL(finished()), SLOT(finished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError())); + multiPart->setParent(reply); + + returnCode = Timeout; + loop = new QEventLoop; + QTimer::singleShot(25000, loop, SLOT(quit())); + int code = returnCode == Timeout ? loop->exec() : returnCode; + delete loop; + loop = 0; + + switch (code) { + case Failure: + return "Request failed: " + reply->errorString(); + case Timeout: + return "Network timeout"; + } + return QString(); +} + QString tst_QNetworkReply::runSimpleRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QNetworkReplyPtr &reply, @@ -1817,6 +1920,307 @@ void tst_QNetworkReply::postToHttpSynchronous() QCOMPARE(uploadedData, md5sum.toHex()); } +void tst_QNetworkReply::postToHttpMultipart_data() +{ + QTest::addColumn<QUrl>("url"); + QTest::addColumn<QHttpMultiPart *>("multiPart"); + QTest::addColumn<QByteArray>("expectedReplyData"); + QTest::addColumn<QByteArray>("contentType"); + + QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/multipart.cgi"); + QByteArray expectedData; + + + // empty parts + + QHttpMultiPart *emptyMultiPart = new QHttpMultiPart; + QTest::newRow("empty") << url << emptyMultiPart << expectedData << QByteArray("mixed"); + + QHttpMultiPart *emptyRelatedMultiPart = new QHttpMultiPart; + emptyRelatedMultiPart->setContentType(QHttpMultiPart::RelatedType); + QTest::newRow("empty-related") << url << emptyRelatedMultiPart << expectedData << QByteArray("related"); + + QHttpMultiPart *emptyAlternativeMultiPart = new QHttpMultiPart; + emptyAlternativeMultiPart->setContentType(QHttpMultiPart::AlternativeType); + QTest::newRow("empty-alternative") << url << emptyAlternativeMultiPart << expectedData << QByteArray("alternative"); + + + // text-only parts + + QHttpPart textPart; + textPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); + textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\"")); + textPart.setBody("7 bytes"); + QHttpMultiPart *multiPart1 = new QHttpMultiPart; + multiPart1->setContentType(QHttpMultiPart::FormDataType); + multiPart1->append(textPart); + expectedData = "key: text, value: 7 bytes\n"; + QTest::newRow("text") << url << multiPart1 << expectedData << QByteArray("form-data"); + + QHttpMultiPart *customMultiPart = new QHttpMultiPart; + customMultiPart->append(textPart); + expectedData = "header: Content-Type, value: 'text/plain'\n" + "header: Content-Disposition, value: 'form-data; name=\"text\"'\n" + "content: 7 bytes\n" + "\n"; + QTest::newRow("text-custom") << url << customMultiPart << expectedData << QByteArray("custom"); + + QHttpPart textPart2; + textPart2.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); + textPart2.setRawHeader("myRawHeader", "myValue"); + textPart2.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text2\"")); + textPart2.setBody("some more bytes"); + textPart2.setBodyDevice((QIODevice *) 1); // test whether setting and unsetting of the device works + textPart2.setBodyDevice(0); + QHttpMultiPart *multiPart2 = new QHttpMultiPart; + multiPart2->setContentType(QHttpMultiPart::FormDataType); + multiPart2->append(textPart); + multiPart2->append(textPart2); + expectedData = "key: text2, value: some more bytes\n" + "key: text, value: 7 bytes\n"; + QTest::newRow("text-text") << url << multiPart2 << expectedData << QByteArray("form-data"); + + + QHttpPart textPart3; + textPart3.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); + textPart3.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text3\"")); + textPart3.setRawHeader("Content-Location", "http://my.test.location.tld"); + textPart3.setBody("even more bytes"); + QHttpMultiPart *multiPart3 = new QHttpMultiPart; + multiPart3->setContentType(QHttpMultiPart::AlternativeType); + multiPart3->append(textPart); + multiPart3->append(textPart2); + multiPart3->append(textPart3); + expectedData = "header: Content-Type, value: 'text/plain'\n" + "header: Content-Disposition, value: 'form-data; name=\"text\"'\n" + "content: 7 bytes\n" + "\n" + "header: Content-Type, value: 'text/plain'\n" + "header: myRawHeader, value: 'myValue'\n" + "header: Content-Disposition, value: 'form-data; name=\"text2\"'\n" + "content: some more bytes\n" + "\n" + "header: Content-Type, value: 'text/plain'\n" + "header: Content-Disposition, value: 'form-data; name=\"text3\"'\n" + "header: Content-Location, value: 'http://my.test.location.tld'\n" + "content: even more bytes\n\n"; + QTest::newRow("text-text-text") << url << multiPart3 << expectedData << QByteArray("alternative"); + + + + // text and image parts + + QHttpPart imagePart11; + imagePart11.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart11.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage\"")); + imagePart11.setRawHeader("Content-Location", "http://my.test.location.tld"); + imagePart11.setRawHeader("Content-ID", "my@id.tld"); + QFile *file11 = new QFile(SRCDIR "/image1.jpg"); + file11->open(QIODevice::ReadOnly); + imagePart11.setBodyDevice(file11); + QHttpMultiPart *imageMultiPart1 = new QHttpMultiPart(QHttpMultiPart::FormDataType); + imageMultiPart1->append(imagePart11); + file11->setParent(imageMultiPart1); + expectedData = "key: testImage, value: 87ef3bb319b004ba9e5e9c9fa713776e\n"; // md5 sum of file + QTest::newRow("image") << url << imageMultiPart1 << expectedData << QByteArray("form-data"); + + QHttpPart imagePart21; + imagePart21.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart21.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage1\"")); + imagePart21.setRawHeader("Content-Location", "http://my.test.location.tld"); + imagePart21.setRawHeader("Content-ID", "my@id.tld"); + QFile *file21 = new QFile(SRCDIR "/image1.jpg"); + file21->open(QIODevice::ReadOnly); + imagePart21.setBodyDevice(file21); + QHttpMultiPart *imageMultiPart2 = new QHttpMultiPart(); + imageMultiPart2->setContentType(QHttpMultiPart::FormDataType); + imageMultiPart2->append(textPart); + imageMultiPart2->append(imagePart21); + file21->setParent(imageMultiPart2); + QHttpPart imagePart22; + imagePart22.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart22.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage2\"")); + QFile *file22 = new QFile(SRCDIR "/image2.jpg"); + file22->open(QIODevice::ReadOnly); + imagePart22.setBodyDevice(file22); + imageMultiPart2->append(imagePart22); + file22->setParent(imageMultiPart2); + expectedData = "key: testImage1, value: 87ef3bb319b004ba9e5e9c9fa713776e\n" + "key: text, value: 7 bytes\n" + "key: testImage2, value: 483761b893f7fb1bd2414344cd1f3dfb\n"; + QTest::newRow("text-image-image") << url << imageMultiPart2 << expectedData << QByteArray("form-data"); + + + QHttpPart imagePart31; + imagePart31.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart31.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage1\"")); + imagePart31.setRawHeader("Content-Location", "http://my.test.location.tld"); + imagePart31.setRawHeader("Content-ID", "my@id.tld"); + QFile *file31 = new QFile(SRCDIR "/image1.jpg"); + file31->open(QIODevice::ReadOnly); + imagePart31.setBodyDevice(file31); + QHttpMultiPart *imageMultiPart3 = new QHttpMultiPart(QHttpMultiPart::FormDataType); + imageMultiPart3->append(imagePart31); + file31->setParent(imageMultiPart3); + QHttpPart imagePart32; + imagePart32.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart32.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage2\"")); + QFile *file32 = new QFile(SRCDIR "/image2.jpg"); + file32->open(QIODevice::ReadOnly); + imagePart32.setBodyDevice(file31); // check that resetting works + imagePart32.setBodyDevice(file32); + imageMultiPart3->append(imagePart32); + file32->setParent(imageMultiPart3); + QHttpPart imagePart33; + imagePart33.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart33.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage3\"")); + QFile *file33 = new QFile(SRCDIR "/image3.jpg"); + file33->open(QIODevice::ReadOnly); + imagePart33.setBodyDevice(file33); + imageMultiPart3->append(imagePart33); + file33->setParent(imageMultiPart3); + expectedData = "key: testImage1, value: 87ef3bb319b004ba9e5e9c9fa713776e\n" + "key: testImage2, value: 483761b893f7fb1bd2414344cd1f3dfb\n" + "key: testImage3, value: ab0eb6fd4fcf8b4436254870b4513033\n"; + QTest::newRow("3-images") << url << imageMultiPart3 << expectedData << QByteArray("form-data"); + + + // note: nesting multiparts is not working currently; for that, the outputDevice would need to be public + +// QHttpPart imagePart41; +// imagePart41.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); +// QFile *file41 = new QFile(SRCDIR "/image1.jpg"); +// file41->open(QIODevice::ReadOnly); +// imagePart41.setBodyDevice(file41); +// +// QHttpMultiPart *innerMultiPart = new QHttpMultiPart(); +// innerMultiPart->setContentType(QHttpMultiPart::FormDataType); +// textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant()); +// innerMultiPart->append(textPart); +// innerMultiPart->append(imagePart41); +// textPart2.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant()); +// innerMultiPart->append(textPart2); +// +// QHttpPart nestedPart; +// nestedPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"nestedMessage")); +// nestedPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("multipart/alternative; boundary=\"" + innerMultiPart->boundary() + "\"")); +// innerMultiPart->outputDevice()->open(QIODevice::ReadOnly); +// nestedPart.setBodyDevice(innerMultiPart->outputDevice()); +// +// QHttpMultiPart *outerMultiPart = new QHttpMultiPart; +// outerMultiPart->setContentType(QHttpMultiPart::FormDataType); +// outerMultiPart->append(textPart); +// outerMultiPart->append(nestedPart); +// outerMultiPart->append(textPart2); +// expectedData = "nothing"; // the CGI.pm module running on the test server does not understand nested multiparts +// openFiles.clear(); +// openFiles << file41; +// QTest::newRow("nested") << url << outerMultiPart << expectedData << openFiles; + + + // test setting large chunks of content with a byte array instead of a device (DISCOURAGED because of high memory consumption, + // but we need to test that the behavior is correct) + QHttpPart imagePart51; + imagePart51.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart51.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage\"")); + QFile *file51 = new QFile(SRCDIR "/image1.jpg"); + file51->open(QIODevice::ReadOnly); + QByteArray imageData = file51->readAll(); + file51->close(); + delete file51; + imagePart51.setBody("7 bytes"); // check that resetting works + imagePart51.setBody(imageData); + QHttpMultiPart *imageMultiPart5 = new QHttpMultiPart; + imageMultiPart5->setContentType(QHttpMultiPart::FormDataType); + imageMultiPart5->append(imagePart51); + expectedData = "key: testImage, value: 87ef3bb319b004ba9e5e9c9fa713776e\n"; // md5 sum of file + QTest::newRow("image-as-content") << url << imageMultiPart5 << expectedData << QByteArray("form-data"); +} + +void tst_QNetworkReply::postToHttpMultipart() +{ + QFETCH(QUrl, url); + + static QSet<QByteArray> boundaries; + + QNetworkRequest request(url); + QNetworkReplyPtr reply; + + QFETCH(QHttpMultiPart *, multiPart); + QFETCH(QByteArray, expectedReplyData); + QFETCH(QByteArray, contentType); + + // hack for testing the setting of the content-type header by hand: + if (contentType == "custom") { + QByteArray contentType("multipart/custom; boundary=\"" + multiPart->boundary() + "\""); + request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); + } + + QVERIFY2(! boundaries.contains(multiPart->boundary()), "boundary '" + multiPart->boundary() + "' has been created twice"); + boundaries.insert(multiPart->boundary()); + + RUN_REQUEST(runMultipartRequest(request, reply, multiPart, "POST")); + multiPart->deleteLater(); + + QCOMPARE(reply->url(), url); + QCOMPARE(reply->error(), QNetworkReply::NoError); + + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok + + QVERIFY(multiPart->boundary().count() > 20); // check that there is randomness after the "boundary_.oOo._" string + QVERIFY(multiPart->boundary().count() < 70); + QByteArray replyData = reply->readAll(); + + expectedReplyData.prepend("content type: multipart/" + contentType + "; boundary=\"" + multiPart->boundary() + "\"\n"); +// QEXPECT_FAIL("nested", "the server does not understand nested multipart messages", Continue); // see above + QCOMPARE(replyData, expectedReplyData); +} + +void tst_QNetworkReply::putToHttpMultipart_data() +{ + postToHttpMultipart_data(); +} + +void tst_QNetworkReply::putToHttpMultipart() +{ + QSKIP("test server script cannot handle PUT data yet", SkipAll); + QFETCH(QUrl, url); + + static QSet<QByteArray> boundaries; + + QNetworkRequest request(url); + QNetworkReplyPtr reply; + + QFETCH(QHttpMultiPart *, multiPart); + QFETCH(QByteArray, expectedReplyData); + QFETCH(QByteArray, contentType); + + // hack for testing the setting of the content-type header by hand: + if (contentType == "custom") { + QByteArray contentType("multipart/custom; boundary=\"" + multiPart->boundary() + "\""); + request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); + } + + QVERIFY2(! boundaries.contains(multiPart->boundary()), "boundary '" + multiPart->boundary() + "' has been created twice"); + boundaries.insert(multiPart->boundary()); + + RUN_REQUEST(runMultipartRequest(request, reply, multiPart, "PUT")); + multiPart->deleteLater(); + + QCOMPARE(reply->url(), url); + QCOMPARE(reply->error(), QNetworkReply::NoError); + + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok + + QVERIFY(multiPart->boundary().count() > 20); // check that there is randomness after the "boundary_.oOo._" string + QVERIFY(multiPart->boundary().count() < 70); + QByteArray replyData = reply->readAll(); + + expectedReplyData.prepend("content type: multipart/" + contentType + "; boundary=\"" + multiPart->boundary() + "\"\n"); +// QEXPECT_FAIL("nested", "the server does not understand nested multipart messages", Continue); // see above + QCOMPARE(replyData, expectedReplyData); +} + void tst_QNetworkReply::deleteFromHttp_data() { QTest::addColumn<QUrl>("url"); @@ -2647,6 +3051,9 @@ void tst_QNetworkReply::ioGetFromHttpBrokenServer_data() QTest::newRow("justHalfStatus+disconnect") << QByteArray("HTTP/1.1") << true; QTest::newRow("justStatus+disconnect") << QByteArray("HTTP/1.1 200 OK\r\n") << true; QTest::newRow("justStatusAndHalfHeaders+disconnect") << QByteArray("HTTP/1.1 200 OK\r\nContent-L") << true; + + QTest::newRow("halfContent+disconnect") << QByteArray("HTTP/1.1 200 OK\r\nContent-Length: 4\r\n\r\nAB") << true; + } void tst_QNetworkReply::ioGetFromHttpBrokenServer() @@ -2658,29 +3065,35 @@ void tst_QNetworkReply::ioGetFromHttpBrokenServer() QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); QNetworkReplyPtr reply = manager.get(request); + QSignalSpy spy(reply, SIGNAL(error(QNetworkReply::NetworkError))); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(reply->url(), request.url()); + QCOMPARE(spy.count(), 1); QVERIFY(reply->error() != QNetworkReply::NoError); } void tst_QNetworkReply::ioGetFromHttpStatus100_data() { QTest::addColumn<QByteArray>("dataToSend"); - QTest::newRow("normal") << QByteArray("HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); - QTest::newRow("minimal") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); - QTest::newRow("minimal2") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.0 200 OK\r\n\r\n"); - QTest::newRow("minimal3") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.0 200 OK\n\n"); - QTest::newRow("with_headers") << QByteArray("HTTP/1.1 100 Continue\r\nBla: x\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); - QTest::newRow("with_headers2") << QByteArray("HTTP/1.1 100 Continue\nBla: x\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + QTest::addColumn<int>("statusCode"); + QTest::newRow("normal") << QByteArray("HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200; + QTest::newRow("minimal") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200; + QTest::newRow("minimal2") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.0 200 OK\r\n\r\n") << 200; + QTest::newRow("minimal3") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.0 200 OK\n\n") << 200; + QTest::newRow("minimal+404") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.0 204 No Content\r\n\r\n") << 204; + QTest::newRow("with_headers") << QByteArray("HTTP/1.1 100 Continue\r\nBla: x\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200; + QTest::newRow("with_headers2") << QByteArray("HTTP/1.1 100 Continue\nBla: x\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200; } void tst_QNetworkReply::ioGetFromHttpStatus100() { QFETCH(QByteArray, dataToSend); + QFETCH(int, statusCode); MiniHttpServer server(dataToSend); server.doClose = true; @@ -2693,7 +3106,7 @@ void tst_QNetworkReply::ioGetFromHttpStatus100() QCOMPARE(reply->url(), request.url()); QCOMPARE(reply->error(), QNetworkReply::NoError); - QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), statusCode); QVERIFY(reply->rawHeader("bla").isNull()); } @@ -2728,6 +3141,7 @@ void tst_QNetworkReply::ioGetFromHttpWithCache_data() QTest::addColumn<QString>("body"); QTest::addColumn<MyMemoryCache::CachedContent>("cachedReply"); QTest::addColumn<int>("cacheMode"); + QTest::addColumn<QStringList>("extraHttpHeaders"); QTest::addColumn<bool>("loadedFromCache"); QTest::addColumn<bool>("networkUsed"); @@ -2745,11 +3159,11 @@ void tst_QNetworkReply::ioGetFromHttpWithCache_data() "\r\n"; QTest::newRow("not-cached,always-network") - << reply200 << "Reloaded" << MyMemoryCache::CachedContent() << int(QNetworkRequest::AlwaysNetwork) << false << true; + << reply200 << "Reloaded" << MyMemoryCache::CachedContent() << int(QNetworkRequest::AlwaysNetwork) << QStringList() << false << true; QTest::newRow("not-cached,prefer-network") - << reply200 << "Reloaded" << MyMemoryCache::CachedContent() << int(QNetworkRequest::PreferNetwork) << false << true; + << reply200 << "Reloaded" << MyMemoryCache::CachedContent() << int(QNetworkRequest::PreferNetwork) << QStringList() << false << true; QTest::newRow("not-cached,prefer-cache") - << reply200 << "Reloaded" << MyMemoryCache::CachedContent() << int(QNetworkRequest::PreferCache) << false << true; + << reply200 << "Reloaded" << MyMemoryCache::CachedContent() << int(QNetworkRequest::PreferCache) << QStringList() << false << true; QDateTime present = QDateTime::currentDateTime().toUTC(); QDateTime past = present.addSecs(-3600); @@ -2771,14 +3185,14 @@ void tst_QNetworkReply::ioGetFromHttpWithCache_data() content.first.setLastModified(past); QTest::newRow("expired,200,prefer-network") - << reply200 << "Reloaded" << content << int(QNetworkRequest::PreferNetwork) << false << true; + << reply200 << "Reloaded" << content << int(QNetworkRequest::PreferNetwork) << QStringList() << false << true; QTest::newRow("expired,200,prefer-cache") - << reply200 << "Reloaded" << content << int(QNetworkRequest::PreferCache) << false << true; + << reply200 << "Reloaded" << content << int(QNetworkRequest::PreferCache) << QStringList() << false << true; QTest::newRow("expired,304,prefer-network") - << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << true << true; + << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << QStringList() << true << true; QTest::newRow("expired,304,prefer-cache") - << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << true << true; + << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << QStringList() << true << true; // // Set to not-expired @@ -2790,20 +3204,20 @@ void tst_QNetworkReply::ioGetFromHttpWithCache_data() content.first.setExpirationDate(future); QTest::newRow("not-expired,200,always-network") - << reply200 << "Reloaded" << content << int(QNetworkRequest::AlwaysNetwork) << false << true; + << reply200 << "Reloaded" << content << int(QNetworkRequest::AlwaysNetwork) << QStringList() << false << true; QTest::newRow("not-expired,200,prefer-network") - << reply200 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << true << false; + << reply200 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << QStringList() << true << false; QTest::newRow("not-expired,200,prefer-cache") - << reply200 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << true << false; + << reply200 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << QStringList() << true << false; QTest::newRow("not-expired,200,always-cache") - << reply200 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << true << false; + << reply200 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << QStringList() << true << false; QTest::newRow("not-expired,304,prefer-network") - << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << true << false; + << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << QStringList() << true << false; QTest::newRow("not-expired,304,prefer-cache") - << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << true << false; + << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << QStringList() << true << false; QTest::newRow("not-expired,304,always-cache") - << reply304 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << true << false; + << reply304 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << QStringList() << true << false; // // Set must-revalidate now @@ -2814,20 +3228,42 @@ void tst_QNetworkReply::ioGetFromHttpWithCache_data() content.first.setRawHeaders(rawHeaders); QTest::newRow("must-revalidate,200,always-network") - << reply200 << "Reloaded" << content << int(QNetworkRequest::AlwaysNetwork) << false << true; + << reply200 << "Reloaded" << content << int(QNetworkRequest::AlwaysNetwork) << QStringList() << false << true; QTest::newRow("must-revalidate,200,prefer-network") - << reply200 << "Reloaded" << content << int(QNetworkRequest::PreferNetwork) << false << true; + << reply200 << "Reloaded" << content << int(QNetworkRequest::PreferNetwork) << QStringList() << false << true; QTest::newRow("must-revalidate,200,prefer-cache") - << reply200 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << true << false; + << reply200 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << QStringList() << true << false; QTest::newRow("must-revalidate,200,always-cache") - << reply200 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << true << false; + << reply200 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << QStringList() << true << false; QTest::newRow("must-revalidate,304,prefer-network") - << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << true << true; + << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << QStringList() << true << true; QTest::newRow("must-revalidate,304,prefer-cache") - << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << true << false; + << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << QStringList() << true << false; QTest::newRow("must-revalidate,304,always-cache") - << reply304 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << true << false; + << reply304 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << QStringList() << true << false; + + // + // Partial content + // + rawHeaders.clear(); + rawHeaders << QNetworkCacheMetaData::RawHeader("Date", QLocale::c().toString(past, dateFormat).toLatin1()) + << QNetworkCacheMetaData::RawHeader("Cache-control", "max-age=7200"); // isn't used in cache loading + content.first.setRawHeaders(rawHeaders); + content.first.setExpirationDate(future); + + QByteArray reply206 = + "HTTP/1.0 206\r\n" + "Connection: keep-alive\r\n" + "Content-Type: text/plain\r\n" + "Cache-control: no-cache\r\n" + "Content-Range: bytes 2-6/8\r\n" + "Content-length: 4\r\n" + "\r\n" + "load"; + + QTest::newRow("partial,dontuse-cache") + << reply206 << "load" << content << int(QNetworkRequest::PreferCache) << (QStringList() << "Range" << "bytes=2-6") << false << true; } void tst_QNetworkReply::ioGetFromHttpWithCache() @@ -2849,6 +3285,15 @@ void tst_QNetworkReply::ioGetFromHttpWithCache() QNetworkRequest request(url); request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, cacheMode); request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false); + + QFETCH(QStringList, extraHttpHeaders); + QStringListIterator it(extraHttpHeaders); + while (it.hasNext()) { + QString header = it.next(); + QString value = it.next(); + request.setRawHeader(header.toLatin1(), value.toLatin1()); // To latin1? Deal with it! + } + QNetworkReplyPtr reply = manager.get(request); connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); @@ -5500,6 +5945,25 @@ void tst_QNetworkReply::qtbug15311doubleContentLength() QCOMPARE(reply->readAll(), QByteArray("ABC")); } +void tst_QNetworkReply::qtbug18232gzipContentLengthZero() +{ + QByteArray response("HTTP/1.0 200 OK\r\nContent-Encoding: gzip\r\nContent-Length: 0\r\n\r\n"); + MiniHttpServer server(response); + server.doClose = true; + + QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); + QNetworkReplyPtr reply = manager.get(request); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(reply->isFinished()); + QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->size(), qint64(0)); + QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), qint64(0)); + QCOMPARE(reply->readAll(), QByteArray()); +} + void tst_QNetworkReply::synchronousRequest_data() { QTest::addColumn<QUrl>("url"); @@ -5631,6 +6095,39 @@ void tst_QNetworkReply::httpAbort() // It must not crash either. } +void tst_QNetworkReply::dontInsertPartialContentIntoTheCache() +{ + QByteArray reply206 = + "HTTP/1.0 206\r\n" + "Connection: keep-alive\r\n" + "Content-Type: text/plain\r\n" + "Cache-control: no-cache\r\n" + "Content-Range: bytes 2-6/8\r\n" + "Content-length: 4\r\n" + "\r\n" + "load"; + + MiniHttpServer server(reply206); + server.doClose = false; + + MySpyMemoryCache *memoryCache = new MySpyMemoryCache(&manager); + manager.setCache(memoryCache); + + QUrl url = "http://localhost:" + QString::number(server.serverPort()); + QNetworkRequest request(url); + request.setRawHeader("Range", "bytes=2-6"); + + QNetworkReplyPtr reply = manager.get(request); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QVERIFY(server.totalConnections > 0); + QCOMPARE(reply->readAll().constData(), "load"); + QCOMPARE(memoryCache->m_insertedUrls.count(), 0); +} + // NOTE: This test must be last testcase in tst_qnetworkreply! void tst_QNetworkReply::parentingRepliesToTheApp() { @@ -5640,4 +6137,5 @@ void tst_QNetworkReply::parentingRepliesToTheApp() } QTEST_MAIN(tst_QNetworkReply) + #include "tst_qnetworkreply.moc" diff --git a/tests/auto/qpainterpath/tst_qpainterpath.cpp b/tests/auto/qpainterpath/tst_qpainterpath.cpp index 8382edc..86adabb 100644 --- a/tests/auto/qpainterpath/tst_qpainterpath.cpp +++ b/tests/auto/qpainterpath/tst_qpainterpath.cpp @@ -305,6 +305,11 @@ void tst_QPainterPath::contains_QPointF_data() QTest::newRow("horizontal cubic, out left") << path << QPointF(0, 100) << false; QTest::newRow("horizontal cubic, out right") << path << QPointF(300, 100) <<false; QTest::newRow("horizontal cubic, in mid") << path << QPointF(150, 100) << true; + + path = QPainterPath(); + path.addEllipse(QRectF(-5000.0, -5000.0, 1500000.0, 1500000.0)); + QTest::newRow("huge ellipse, qreal=float crash") << path << QPointF(1100000.35, 1098000.2) << true; + } void tst_QPainterPath::contains_QPointF() diff --git a/tests/auto/qpixmap/qpixmap.pro b/tests/auto/qpixmap/qpixmap.pro index 185ec1a..e73c130 100644 --- a/tests/auto/qpixmap/qpixmap.pro +++ b/tests/auto/qpixmap/qpixmap.pro @@ -25,6 +25,7 @@ wince*: { LIBS += -lfbscli.dll -lbitgdi.dll -lgdi.dll contains(QT_CONFIG, openvg) { LIBS += $$QMAKE_LIBS_OPENVG + QT *= openvg } } else { DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp index a8f8b7b..480893a 100644 --- a/tests/auto/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/qpixmap/tst_qpixmap.cpp @@ -68,6 +68,10 @@ #include <fbs.h> #include <gdi.h> #include <bitdev.h> +#if !defined(QT_NO_OPENVG) +#include <QtOpenVG/qvg.h> +#include <QtOpenVG/private/qpixmapdata_vg_p.h> +#endif #endif #ifdef Q_WS_X11 @@ -187,6 +191,10 @@ private slots: void toImageDeepCopy(); void loadAsBitmapOrPixmap(); + +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) + void vgImageReadBack(); +#endif }; static bool lenientCompare(const QPixmap &actual, const QPixmap &expected) @@ -1783,6 +1791,104 @@ void tst_QPixmap::toImageDeepCopy() QVERIFY(first != second); } +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) +Q_OPENVG_EXPORT VGImage qPixmapToVGImage(const QPixmap& pixmap); +class FriendlyVGPixmapData : public QVGPixmapData +{ +public: + FriendlyVGPixmapData(PixelType type) : QVGPixmapData(type) { } + bool sourceIsNull() { return source.isNull(); } + friend QPixmap pixmapFromVGImage(VGImage image); +}; +QPixmap pixmapFromVGImage(VGImage image) +{ + if (image != VG_INVALID_HANDLE) { + int w = vgGetParameteri(image, VG_IMAGE_WIDTH); + int h = vgGetParameteri(image, VG_IMAGE_HEIGHT); + FriendlyVGPixmapData *pd = new FriendlyVGPixmapData(QPixmapData::PixmapType); + pd->resize(w, h); + pd->vgImage = image; + pd->recreate = false; + pd->prevSize = QSize(pd->w, pd->h); + return QPixmap(pd); + } + return QPixmap(); +} +class Content : public QWidget +{ +public: + void paintEvent(QPaintEvent *) { + QPainter painter(this); + QColor testPixel(qRgb(200, 150, 100)); + if (pm.isNull()) { // first phase: create a VGImage + painter.beginNativePainting(); + vgimage = vgCreateImage(VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER); + QImage img(20, 10, QImage::Format_ARGB32_Premultiplied); + img.fill(qRgb(0, 0, 0)); + QPainter p(&img); + p.fillRect(0, 0, img.width(), img.height(), testPixel); + p.end(); + vgImageSubData(vgimage, img.bits(), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height()); + // Now the area 0,0 20x10 (in OpenVG coords) is filled with some color. + painter.endNativePainting(); + } else { // second phase: check if readback works + painter.drawPixmap(0, 0, pm); + // Drawing should not cause readback, this is important for performance; + noreadback_ok = static_cast<FriendlyVGPixmapData *>(pm.pixmapData())->sourceIsNull(); + // However toImage() requires readback. + QImage img = pm.toImage(); + readback_ok = img.width() == pm.width(); + readback_ok &= img.height() == pm.height(); + readback_ok &= !static_cast<FriendlyVGPixmapData *>(pm.pixmapData())->sourceIsNull(); + uint pix = img.pixel(1, 1); + content_ok = qRed(pix) == testPixel.red(); + content_ok &= qGreen(pix) == testPixel.green(); + content_ok &= qBlue(pix) == testPixel.blue(); + pix = img.pixel(img.width() - 1, img.height() - 1); + content_ok &= qRed(pix) == 0; + content_ok &= qGreen(pix) == 0; + content_ok &= qBlue(pix) == 0; + } + } + int w; + int h; + VGImage vgimage; + QPixmap pm; + bool noreadback_ok; + bool readback_ok; + bool content_ok; +}; +void tst_QPixmap::vgImageReadBack() +{ + QPixmap tmp(10, 20); + if (tmp.pixmapData()->classId() == QPixmapData::OpenVGClass) { + Content c; + c.w = 50; + c.h = 60; + c.vgimage = VG_INVALID_HANDLE; + c.noreadback_ok = c.readback_ok = c.content_ok = false; + c.showFullScreen(); + QTest::qWaitForWindowShown(&c); + QVERIFY(c.vgimage != VG_INVALID_HANDLE); + QPixmap pm = pixmapFromVGImage(c.vgimage); + QVERIFY(!pm.isNull()); + QCOMPARE(pm.width(), c.w); + QCOMPARE(pm.height(), c.h); + QVERIFY(qPixmapToVGImage(pm) == c.vgimage); + QVERIFY(static_cast<FriendlyVGPixmapData *>(pm.pixmapData())->sourceIsNull()); + c.pm = pm; + // Make sure the second phase in paintEvent is executed too. + c.hide(); + c.showFullScreen(); + QTest::qWaitForWindowShown(&c); + QVERIFY(c.noreadback_ok); + QVERIFY(c.readback_ok); + QVERIFY(c.content_ok); + } else { + QSKIP("Not using openvg graphicssystem", SkipSingle); + } +} +#endif // Symbian & OpenVG QTEST_MAIN(tst_QPixmap) #include "tst_qpixmap.moc" diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index 9d7e896..457188c 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -725,10 +725,7 @@ void tst_QScriptContext::backtrace_data() expected << "<native>('hey') at -1" << "<eval>() at 3" - << QString::fromLatin1("foo(arg1 = 'hello', arg2 = 456) at testfile:%0") - // interpreter unfortunately doesn't provide line number for eval() - .arg(qt_script_isJITEnabled() ? 2 : -1); - expected + << "foo(arg1 = 'hello', arg2 = 456) at testfile:2" << "<global>() at testfile:4"; QTest::newRow("eval") << source << expected; @@ -787,10 +784,7 @@ void tst_QScriptContext::backtrace_data() expected << "<native>('hey') at -1" << "<eval>() at 3" - << QString::fromLatin1("plop('hello', 456) at testfile:%0") - // interpreter unfortunately doesn't provide line number for eval() - .arg(qt_script_isJITEnabled() ? 3 : -1); - expected + << "plop('hello', 456) at testfile:3" << "<global>() at testfile:5"; QTest::newRow("eval in member") << source << expected; @@ -987,6 +981,8 @@ void tst_QScriptContext::backtrace() QVERIFY(!eng.hasUncaughtException()); QVERIFY(ret.isArray()); QStringList slist = qscriptvalue_cast<QStringList>(ret); + QEXPECT_FAIL("eval", "QTBUG-17842: Missing line number in backtrace when function calls eval()", Continue); + QEXPECT_FAIL("eval in member", "QTBUG-17842: Missing line number in backtrace when function calls eval()", Continue); QCOMPARE(slist, expectedbacktrace); } diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index 2d7feee..bc4091d 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -157,6 +157,7 @@ private slots: void reportAdditionalMemoryCost(); void gcWithNestedDataStructure(); void processEventsWhileRunning(); + void throwErrorFromProcessEvents_data(); void throwErrorFromProcessEvents(); void disableProcessEventsInterval(); void stacktrace(); @@ -164,6 +165,7 @@ private slots: void numberParsing(); void automaticSemicolonInsertion(); void abortEvaluation_notEvaluating(); + void abortEvaluation_data(); void abortEvaluation(); void abortEvaluation_tryCatch(); void abortEvaluation_fromNative(); @@ -235,6 +237,7 @@ private slots: void evaluateProgram_multipleEngines(); void evaluateProgram_empty(); void collectGarbageAfterConnect(); + void collectGarbageAfterNativeArguments(); void promoteThisObjectToQObjectInConstructor(); void scriptValueFromQMetaObject(); @@ -2961,17 +2964,42 @@ public: QScriptEngine *engine; }; +void tst_QScriptEngine::throwErrorFromProcessEvents_data() +{ + QTest::addColumn<QString>("script"); + QTest::addColumn<QString>("error"); + + QTest::newRow("while (1)") + << QString::fromLatin1("while (1) { }") + << QString::fromLatin1("Error: Killed"); + QTest::newRow("while (1) i++") + << QString::fromLatin1("i = 0; while (1) { i++; }") + << QString::fromLatin1("Error: Killed"); + // Unlike abortEvaluation(), scripts should be able to catch the + // exception. + QTest::newRow("try catch") + << QString::fromLatin1("try {" + " while (1) { }" + "} catch(e) {" + " throw new Error('Caught');" + "}") + << QString::fromLatin1("Error: Caught"); +} + void tst_QScriptEngine::throwErrorFromProcessEvents() { + QFETCH(QString, script); + QFETCH(QString, error); + QScriptEngine eng; EventReceiver2 receiver(&eng); QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1))); eng.setProcessEventsInterval(100); - QScriptValue ret = eng.evaluate(QString::fromLatin1("while (1) { }")); + QScriptValue ret = eng.evaluate(script); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("Error: Killed")); + QCOMPARE(ret.toString(), error); } void tst_QScriptEngine::disableProcessEventsInterval() @@ -3386,8 +3414,26 @@ void tst_QScriptEngine::abortEvaluation_notEvaluating() } } +void tst_QScriptEngine::abortEvaluation_data() +{ + QTest::addColumn<QString>("script"); + + QTest::newRow("while (1)") + << QString::fromLatin1("while (1) { }"); + QTest::newRow("while (1) i++") + << QString::fromLatin1("i = 0; while (1) { i++; }"); + QTest::newRow("try catch") + << QString::fromLatin1("try {" + " while (1) { }" + "} catch(e) {" + " throw new Error('Caught');" + "}"); +} + void tst_QScriptEngine::abortEvaluation() { + QFETCH(QString, script); + QScriptEngine eng; EventReceiver3 receiver(&eng); @@ -3395,7 +3441,7 @@ void tst_QScriptEngine::abortEvaluation() for (int x = 0; x < 4; ++x) { QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1))); receiver.resultType = EventReceiver3::AbortionResult(x); - QScriptValue ret = eng.evaluate(QString::fromLatin1("while (1) { }")); + QScriptValue ret = eng.evaluate(script); switch (receiver.resultType) { case EventReceiver3::None: QVERIFY(!eng.hasUncaughtException()); @@ -5643,6 +5689,16 @@ void tst_QScriptEngine::collectGarbageAfterConnect() QVERIFY(widget == 0); } +void tst_QScriptEngine::collectGarbageAfterNativeArguments() +{ + // QTBUG-17788 + QScriptEngine eng; + QScriptContext *ctx = eng.pushContext(); + QScriptValue arguments = ctx->argumentsObject(); + // Shouldn't crash when marking the arguments object. + collectGarbage_helper(eng); +} + static QScriptValue constructQObjectFromThisObject(QScriptContext *ctx, QScriptEngine *eng) { Q_ASSERT(ctx->isCalledAsConstructor()); diff --git a/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.cpp b/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.cpp index 1679512..c4fb0e3 100644 --- a/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.cpp +++ b/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.cpp b/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.cpp index b13f723..e4b9e4e 100644 --- a/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.cpp +++ b/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qscriptextensionplugin/tst_qscriptextensionplugin.cpp b/tests/auto/qscriptextensionplugin/tst_qscriptextensionplugin.cpp index e8b5e0a..78e949c 100644 --- a/tests/auto/qscriptextensionplugin/tst_qscriptextensionplugin.cpp +++ b/tests/auto/qscriptextensionplugin/tst_qscriptextensionplugin.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qscriptjstestsuite/expect_fail.txt b/tests/auto/qscriptjstestsuite/expect_fail.txt new file mode 100644 index 0000000..7f93378 --- /dev/null +++ b/tests/auto/qscriptjstestsuite/expect_fail.txt @@ -0,0 +1,198 @@ +ecma/Array/15.4.3.1-2.js | var props = ''; for ( p in Array ) { props += p } props + +ecma/Boolean/15.6.3.1-1.js | var str='';for ( p in Boolean ) { str += p } str; + +ecma/Expressions/11.4.1.js | var abc; delete(abc) + +ecma/FunctionObjects/15.3.3.1-2.js | var str='';for (prop in Function ) str += prop; str; + +ecma/ObjectObjects/15.2.3.1-1.js | var str = '';for ( p in Object ) { str += p; }; str + +ecma/Statements/12.6.3-11.js | result = ""; for ( p in Number ) { result += String(p) }; +ecma/Statements/12.6.3-2.js | Boolean.prototype.foo = 34; for ( j in Boolean ) Boolean[j] + +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4256) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4257) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4258) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4259) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4260) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4261) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4262) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4263) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4264) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4265) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4266) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4267) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4268) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4269) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4270) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4271) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4272) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4273) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4274) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4275) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4276) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4277) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4278) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4279) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4280) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4281) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4282) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4283) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4284) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4285) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4286) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4287) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4288) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4289) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4290) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4291) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4292) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-2.js | var s = new String( String.fromCharCode(4293) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-5.js | var s = new String( String.fromCharCode(1024) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.11-5.js | var s = new String( String.fromCharCode(1037) ); s.toLowerCase().charCodeAt(0) +ecma/String/15.5.4.12-1.js | var s = new String( String.fromCharCode(181) ); s.toUpperCase().charCodeAt(0) +ecma/String/15.5.4.12-1.js | var s = new String( String.fromCharCode(329) ); s.toUpperCase().charCodeAt(0) +ecma/String/15.5.4.12-4.js | var s = new String( String.fromCharCode(1104) ); s.toUpperCase().charCodeAt(0) +ecma/String/15.5.4.12-4.js | var s = new String( String.fromCharCode(1117) ); s.toUpperCase().charCodeAt(0) +ecma/String/15.5.4.12-5.js | var s = new String( String.fromCharCode(1415) ); s.toUpperCase().charCodeAt(0) + +ecma/TypeConversion/9.3.1-3.js | -"\u20001234\u2001" +ecma/TypeConversion/9.3.1-3.js | - "-0x123456789abcde8" + +ecma/extensions/15.1.2.1-1.js | var PROPS = ''; for ( p in eval ) { PROPS += p }; PROPS + +ecma/GlobalObject/15.1.2.2-1.js | var PROPS=''; for ( var p in parseInt ) { PROPS += p; }; PROPS +ecma/GlobalObject/15.1.2.3-1.js | var MYPROPS=''; for ( var p in parseFloat ) { MYPROPS += p }; MYPROPS +ecma/GlobalObject/15.1.2.4.js | var MYPROPS=''; for ( var p in escape ) { MYPROPS+= p}; MYPROPS +ecma/GlobalObject/15.1.2.5-1.js | var MYPROPS=''; for ( var p in unescape ) { MYPROPS+= p }; MYPROPS +ecma/GlobalObject/15.1.2.6.js | var MYPROPS=''; for ( var p in isNaN ) { MYPROPS+= p }; MYPROPS +ecma/GlobalObject/15.1.2.7.js | var MYPROPS=''; for ( p in isFinite ) { MYPROPS+= p }; MYPROPS + +ecma_3/Array/15.4.5.1-01.js | 15.4.5.1 - array.length coverage + +ecma_3/extensions/regress-274152.js | Do not ignore unicode format-control characters: 0 +ecma_3/extensions/regress-274152.js | Do not ignore unicode format-control characters: 1 +ecma_3/extensions/regress-274152.js | Do not ignore unicode format-control characters: 2 +ecma_3/extensions/regress-274152.js | Do not ignore unicode format-control characters: 3 +ecma_3/extensions/regress-274152.js | Do not ignore unicode format-control characters: 4 +ecma_3/extensions/regress-274152.js | Do not ignore unicode format-control characters: 5 +ecma_3/extensions/regress-274152.js | Do not ignore unicode format-control characters: 6 +ecma_3/extensions/regress-274152.js | Do not ignore unicode format-control characters: 7 +ecma_3/extensions/regress-274152.js | Do not ignore unicode format-control characters: 8 +ecma_3/extensions/regress-368516.js | Treat unicode BOM characters as whitespace: 0 +ecma_3/extensions/regress-368516.js | Treat unicode BOM characters as whitespace: 1 + +ecma_3/Date/15.9.4.3.js | 15.9.4.3 - Date.UTC edge-case arguments.: date Infinity +ecma_3/Date/15.9.4.3.js | 15.9.4.3 - Date.UTC edge-case arguments.: hours Infinity +ecma_3/Date/15.9.4.3.js | 15.9.4.3 - Date.UTC edge-case arguments.: minutes Infinity +ecma_3/Date/15.9.4.3.js | 15.9.4.3 - Date.UTC edge-case arguments.: seconds Infinity +ecma_3/Function/regress-131964.js | Section 1 of test - +ecma_3/Function/regress-313570.js | length of objects whose prototype chain includes a function: immutable +ecma_3/FunExpr/fe-001.js | Both functions were defined. + +ecma_3/LexicalConventions/7.9.1.js | Automatic Semicolon insertion in postfix expressions: expr\n++ +ecma_3/LexicalConventions/7.9.1.js | Automatic Semicolon insertion in postfix expressions: expr\n-- +ecma_3/LexicalConventions/7.9.1.js | Automatic Semicolon insertion in postfix expressions: (x\n)-- y +ecma_3/LexicalConventions/7.9.1.js | Automatic Semicolon insertion in postfix expressions: (x)-- y + +ecma_3/Object/8.6.1-01.js | In strict mode, setting a read-only property should generate a warning: Throw if STRICT and WERROR is enabled + +ecma_3/Operators/order-01.js | operator evaluation order: 11.8.2 > +ecma_3/Operators/order-01.js | operator evaluation order: 11.8.4 >= + +ecma_3/RegExp/15.10.2-1.js | Section 7 of test - \nregexp = /(z)((a+)?(b+)?(c))*/\nstring = 'zaacbbbcac'\nERROR !!! regexp failed to give expected match array:\nExpect: ["zaacbbbcac", "z", "ac", "a", , "c"]\nActual: ["zaacbbbcac", "z", "ac", "a", "bbb", "c"]\n +ecma_3/RegExp/15.10.2-1.js | Section 8 of test - \nregexp = /(a*)*/\nstring = 'b'\nERROR !!! regexp failed to give expected match array:\nExpect: ["", , ]\nActual: ["", ""]\n +ecma_3/RegExp/15.10.2-1.js | Section 12 of test - \nregexp = /(.*?)a(?!(a+)b\2c)\2(.*)/\nstring = 'baaabaac'\nERROR !!! regexp failed to give expected match array:\nExpect: ["baaabaac", "ba", , "abaac"]\nActual: ["baaabaac", "ba", "aa", "abaac"]\n +ecma_3/RegExp/perlstress-001.js | Section 218 of test - \nregexp = /((foo)|(bar))*/\nstring = 'foobar'\nERROR !!! regexp failed to give expected match array:\nExpect: ["foobar", "bar", , "bar"]\nActual: ["foobar", "bar", "foo", "bar"]\n +ecma_3/RegExp/perlstress-001.js | Section 234 of test - \nregexp = /(?:(f)(o)(o)|(b)(a)(r))*/\nstring = 'foobar'\nERROR !!! regexp failed to give expected match array:\nExpect: ["foobar", , , , "b", "a", "r"]\nActual: ["foobar", "f", "o", "o", "b", "a", "r"]\n +ecma_3/RegExp/perlstress-001.js | Section 241 of test - \nregexp = /^(?:b|a(?=(.)))*\1/\nstring = 'abc'\nERROR !!! regexp failed to give expected match array:\nExpect: ["ab", , ]\nActual: ["ab", "b"]\n +ecma_3/RegExp/perlstress-001.js | Section 412 of test - \nregexp = /^(a(b)?)+$/\nstring = 'aba'\nERROR !!! regexp failed to give expected match array:\nExpect: ["aba", "a", , ]\nActual: ["aba", "a", "b"]\n +ecma_3/RegExp/perlstress-001.js | Section 413 of test - \nregexp = /^(aa(bb)?)+$/\nstring = 'aabbaa'\nERROR !!! regexp failed to give expected match array:\nExpect: ["aabbaa", "aa", , ]\nActual: ["aabbaa", "aa", "bb"]\n + +ecma_3/RegExp/regress-209919.js | Section 1 of test - \nregexp = /(a|b*)*/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: ["a", "a"]\nActual: ["a", ""]\n +ecma_3/RegExp/regress-209919.js | Section 3 of test - \nregexp = /(b*)*/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: ["", , ]\nActual: ["", ""]\n +ecma_3/RegExp/regress-209919.js | Section 5 of test - \nregexp = /^\-?(\d{1,}|\.{0,})*(\,\d{1,})?$/\nstring = '100.00'\nERROR !!! regexp failed to give expected match array:\nExpect: ["100.00", "00", , ]\nActual: ["100.00", "", , ]\n +ecma_3/RegExp/regress-209919.js | Section 6 of test - \nregexp = /^\-?(\d{1,}|\.{0,})*(\,\d{1,})?$/\nstring = '100,00'\nERROR !!! regexp failed to give expected match array:\nExpect: ["100,00", "100", ",00"]\nActual: ["100,00", "", ",00"]\n +ecma_3/RegExp/regress-209919.js | Section 7 of test - \nregexp = /^\-?(\d{1,}|\.{0,})*(\,\d{1,})?$/\nstring = '1.000,00'\nERROR !!! regexp failed to give expected match array:\nExpect: ["1.000,00", "000", ",00"]\nActual: ["1.000,00", "", ",00"]\n + +ecma_3/String/15.5.4.11.js | Section 7 +ecma_3/String/15.5.4.11.js | Section 24 +ecma_3/String/15.5.4.11.js | Section 26 +ecma_3/String/15.5.4.11.js | Section 28 +ecma_3/String/15.5.4.11.js | Section 30 +ecma_3/String/15.5.4.14.js | 15.5.4.14 - String.prototype.split(/()/) + +ecma_3/Unicode/regress-352044-01.js | issues with Unicode escape sequences in JavaScript source code +ecma_3/Unicode/uc-001.js | Unicode format-control character test (Category Cf.) + +ecma_2/RegExp/exec-001.js | NO TESTS EXIST +ecma_2/String/replace-001.js | NO TESTS EXIST + +[Q_CC_MSVC] +ecma_3/Expressions/11.7.3-01.js | 11.7.3 - >>> should evaluate operands in order: order | QTBUG-8056 +ecma_3/Operators/order-01.js | operator evaluation order: 11.7.3 >>> | QTBUG-8056 +ecma_3/Operators/order-01.js | operator evaluation order: 11.13.2 >>>= | QTBUG-8056 + +[Q_CC_MINGW] +ecma/Math/15.8.2.13.js | Math.pow(NaN,0) +ecma/Math/15.8.2.13.js | Math.pow(NaN,-0) +ecma/Math/15.8.2.5.js | Math.atan2(Infinity, Infinity) +ecma/Math/15.8.2.5.js | Math.atan2(Infinity, -Infinity) +ecma/Math/15.8.2.5.js | Math.atan2(-Infinity, Infinity) +ecma/Math/15.8.2.5.js | Math.atan2(-Infinity, -Infinity) + +[Q_OS_SOLARIS] +ecma/Expressions/11.13.2-2.js | VAR1 = -0; VAR2= Infinity; VAR2 /= VAR1 +ecma/Expressions/11.13.2-2.js | VAR1 = -0; VAR2= -Infinity; VAR2 /= VAR1 +ecma/Expressions/11.13.2-2.js | VAR1 = 1; VAR2= -0; VAR1 /= VAR2 +ecma/Expressions/11.13.2-2.js | VAR1 = -1; VAR2= -0; VAR1 /= VAR2 +ecma/Expressions/11.5.2.js | Number.POSITIVE_INFINITY / -0 +ecma/Expressions/11.5.2.js | Number.NEGATIVE_INFINITY / -0 +ecma/Expressions/11.5.2.js | 1 / -0 +ecma/Expressions/11.5.2.js | -1 / -0 +ecma/Math/15.8.2.10.js | Math.log(-0.0000001) +ecma/Math/15.8.2.10.js | Math.log(-1) +ecma/Math/15.8.2.11.js | Infinity/Math.max(-0,-0) +ecma/Math/15.8.2.12.js | Infinity/Math.min(0,-0) +ecma/Math/15.8.2.12.js | Infinity/Math.min(-0,-0) +ecma/Math/15.8.2.13.js | Math.pow(NaN,0) +ecma/Math/15.8.2.13.js | Math.pow(NaN,-0) +ecma/Math/15.8.2.13.js | Infinity/Math.pow(-Infinity, -1) +ecma/Math/15.8.2.13.js | Math.pow(0, -1) +ecma/Math/15.8.2.13.js | Math.pow(0, -0.5) +ecma/Math/15.8.2.13.js | Math.pow(0, -1000) +ecma/Math/15.8.2.13.js | Infinity/Math.pow(-0, 1) +ecma/Math/15.8.2.13.js | Infinity/Math.pow(-0, 3) +ecma/Math/15.8.2.13.js | Math.pow(-0, -2) +ecma/Math/15.8.2.15.js | Infinity/Math.round(-0) +ecma/Math/15.8.2.15.js | Infinity/Math.round(-0.49) +ecma/Math/15.8.2.15.js | Infinity/Math.round(-0.5) +ecma/Math/15.8.2.17.js | Infinity/Math.sqrt(-0) +ecma/Math/15.8.2.18.js | Infinity/Math.tan(-0) +ecma/Math/15.8.2.2.js | Math.acos(1.00000001) +ecma/Math/15.8.2.2.js | Math.acos(11.00000001) +ecma/Math/15.8.2.3.js | Math.asin(1.000001) +ecma/Math/15.8.2.3.js | Math.asin(-1.000001) +ecma/Math/15.8.2.3.js | Infinity/Math.asin(-0) +ecma/Math/15.8.2.4.js | Infinity/Math.atan(-0) +ecma/Math/15.8.2.5.js | Math.atan2(0, -0) +ecma/Math/15.8.2.5.js | Infinity/Math.atan2(-0, 1) +ecma/Math/15.8.2.5.js | Math.atan2(-0,\t-0) +ecma/Math/15.8.2.5.js | Math.atan2(-0,\t-1) +ecma/Math/15.8.2.6.js | Infinity/Math.ceil('-0') +ecma/Math/15.8.2.6.js | Infinity/Math.ceil(-0) +ecma/Math/15.8.2.6.js | Infinity/Math.ceil(-Number.MIN_VALUE) +ecma/Math/15.8.2.6.js | Infinity/Math.ceil(-0.9) +ecma/Math/15.8.2.9.js | Infinity/Math.floor(-0) +ecma/TypeConversion/9.3.1-3.js | var z = 0; print(1/-z) +ecma/TypeConversion/9.3.1-3.js | 1/-1e-2000 + +[Q_OS_SYMBIAN] +ecma/Math/15.8.2.13.js | Math.pow(-1, 0.5) +ecma/Math/15.8.2.13.js | Math.pow(-1, -0.5) +ecma_3/Operators/order-01.js | operator evaluation order: 11.5.1 * +ecma_3/Operators/order-01.js | operator evaluation order: 11.5.2 / +ecma_3/Operators/order-01.js | operator evaluation order: 11.6.2 - +ecma_3/Operators/order-01.js | operator evaluation order: 11.13.2 *= +ecma_3/Operators/order-01.js | operator evaluation order: 11.13.2 /= diff --git a/tests/auto/qscriptjstestsuite/qscriptjstestsuite.pro b/tests/auto/qscriptjstestsuite/qscriptjstestsuite.pro index b1ddd64..471aa02 100644 --- a/tests/auto/qscriptjstestsuite/qscriptjstestsuite.pro +++ b/tests/auto/qscriptjstestsuite/qscriptjstestsuite.pro @@ -1,6 +1,8 @@ load(qttest_p4) QT = core script SOURCES += tst_qscriptjstestsuite.cpp +RESOURCES += qscriptjstestsuite.qrc +include(../qscriptv8testsuite/abstracttestsuite.pri) !symbian: DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/auto/qscriptjstestsuite/qscriptjstestsuite.qrc b/tests/auto/qscriptjstestsuite/qscriptjstestsuite.qrc new file mode 100644 index 0000000..4a4eb60 --- /dev/null +++ b/tests/auto/qscriptjstestsuite/qscriptjstestsuite.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>expect_fail.txt</file> + <file>skip.txt</file> +</qresource> +</RCC> diff --git a/tests/auto/qscriptjstestsuite/skip.txt b/tests/auto/qscriptjstestsuite/skip.txt new file mode 100644 index 0000000..2dc0ccb --- /dev/null +++ b/tests/auto/qscriptjstestsuite/skip.txt @@ -0,0 +1,9 @@ +.+/15\.9\.2\..+ | unstable on slow machines +.+/15\.9\.5\..+ | too slooow +regress-130451.js | asserts +regress-322135-01.js | asserts +regress-322135-02.js | asserts +regress-322135-03.js | takes forever +regress-322135-04.js | takes forever +ecma_3/RegExp/regress-375715-04.js | bug +ecma_3/RegExp/regress-289669.js | Can fail due to relying on wall-clock time diff --git a/tests/auto/qscriptjstestsuite/tst_qscriptjstestsuite.cpp b/tests/auto/qscriptjstestsuite/tst_qscriptjstestsuite.cpp index 43a6dba..e042dfe 100644 --- a/tests/auto/qscriptjstestsuite/tst_qscriptjstestsuite.cpp +++ b/tests/auto/qscriptjstestsuite/tst_qscriptjstestsuite.cpp @@ -40,44 +40,18 @@ ****************************************************************************/ +#include "abstracttestsuite.h" #include <QtTest/QtTest> #include <QtScript> #if defined(Q_OS_SYMBIAN) -# define SRCDIR "" +# define SRCDIR "." #endif //TESTED_CLASS= //TESTED_FILES= -// Uncomment the following define to have the autotest generate -// addExpectedFailure() code for all the tests that fail. -// This is useful when a whole new test (sub)suite is added. -// The code is stored in addexpectedfailures.cpp. -// Paste the contents into this file after the existing -// addExpectedFailure() calls. - -//#define GENERATE_ADDEXPECTEDFAILURE_CODE - -static QString readFile(const QString &filename) -{ - QFile file(filename); - if (!file.open(QFile::ReadOnly)) - return QString(); - QTextStream stream(&file); - return stream.readAll(); -} - -static void appendCString(QVector<char> *v, const char *s) -{ - char c; - do { - c = *(s++); - *v << c; - } while (c != '\0'); -} - struct TestRecord { TestRecord() : lineNumber(-1) { } @@ -120,17 +94,18 @@ struct FailureItem QString message; }; -class tst_Suite : public QObject +class tst_QScriptJSTestSuite : public AbstractTestSuite { public: - tst_Suite(); - virtual ~tst_Suite(); + tst_QScriptJSTestSuite(); + virtual ~tst_QScriptJSTestSuite(); - static QMetaObject staticMetaObject; - virtual const QMetaObject *metaObject() const; - virtual void *qt_metacast(const char *); - virtual int qt_metacall(QMetaObject::Call, int, void **argv); +protected: + virtual void configData(TestConfig::Mode mode, const QStringList &parts); + virtual void writeSkipConfigFile(QTextStream &); + virtual void writeExpectFailConfigFile(QTextStream &); + virtual void runTestFunction(int testIndex); private: void addExpectedFailure(const QString &fileName, const QString &description, const QString &message); @@ -143,33 +118,11 @@ private: void addFileExclusion(const QRegExp &rx, const QString &message); bool isExcludedFile(const QString &fileName, QString *message) const; - QDir testsDir; QList<QString> subSuitePaths; QList<FailureItem> expectedFailures; QList<QPair<QRegExp, QString> > fileExclusions; -#ifdef GENERATE_ADDEXPECTEDFAILURE_CODE - QString generatedAddExpectedFailureCode; -#endif }; -QMetaObject tst_Suite::staticMetaObject; - -Q_GLOBAL_STATIC(QVector<uint>, qt_meta_data_tst_Suite) -Q_GLOBAL_STATIC(QVector<char>, qt_meta_stringdata_tst_Suite) - -const QMetaObject *tst_Suite::metaObject() const -{ - return &staticMetaObject; -} - -void *tst_Suite::qt_metacast(const char *_clname) -{ - if (!_clname) return 0; - if (!strcmp(_clname, qt_meta_stringdata_tst_Suite()->constData())) - return static_cast<void*>(const_cast<tst_Suite*>(this)); - return QObject::qt_metacast(_clname); -} - static QScriptValue qscript_void(QScriptContext *, QScriptEngine *eng) { return eng->undefinedValue(); @@ -222,625 +175,245 @@ static QScriptValue qscript_TestCase(QScriptContext *ctx, QScriptEngine *eng) return ret; } -int tst_Suite::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +void tst_QScriptJSTestSuite::runTestFunction(int testIndex) { - _id = QObject::qt_metacall(_c, _id, _a); - if (_id < 0) - return _id; - if (_c == QMetaObject::InvokeMetaMethod) { - if (!(_id & 1)) { - // data - QTest::addColumn<TestRecord>("record"); - bool hasData = false; - - QString testsShellPath = testsDir.absoluteFilePath("shell.js"); - QString testsShellContents = readFile(testsShellPath); - - QDir subSuiteDir(subSuitePaths.at(_id / 2)); - QString subSuiteShellPath = subSuiteDir.absoluteFilePath("shell.js"); - QString subSuiteShellContents = readFile(subSuiteShellPath); - - QDir testSuiteDir(subSuiteDir); - testSuiteDir.cdUp(); - QString suiteJsrefPath = testSuiteDir.absoluteFilePath("jsref.js"); - QString suiteJsrefContents = readFile(suiteJsrefPath); - QString suiteShellPath = testSuiteDir.absoluteFilePath("shell.js"); - QString suiteShellContents = readFile(suiteShellPath); - - QFileInfoList testFileInfos = subSuiteDir.entryInfoList(QStringList() << "*.js", QDir::Files); - foreach (QFileInfo tfi, testFileInfos) { - if ((tfi.fileName() == "shell.js") || (tfi.fileName() == "browser.js")) - continue; - - QString abspath = tfi.absoluteFilePath(); - QString relpath = testsDir.relativeFilePath(abspath); - QString excludeMessage; - if (isExcludedFile(relpath, &excludeMessage)) { - QTest::newRow(relpath.toLatin1()) << TestRecord(excludeMessage, relpath); - continue; - } + if (!(testIndex & 1)) { + // data + QTest::addColumn<TestRecord>("record"); + bool hasData = false; + + QString testsShellPath = testsDir.absoluteFilePath("shell.js"); + QString testsShellContents = readFile(testsShellPath); + + QDir subSuiteDir(subSuitePaths.at(testIndex / 2)); + QString subSuiteShellPath = subSuiteDir.absoluteFilePath("shell.js"); + QString subSuiteShellContents = readFile(subSuiteShellPath); + + QDir testSuiteDir(subSuiteDir); + testSuiteDir.cdUp(); + QString suiteJsrefPath = testSuiteDir.absoluteFilePath("jsref.js"); + QString suiteJsrefContents = readFile(suiteJsrefPath); + QString suiteShellPath = testSuiteDir.absoluteFilePath("shell.js"); + QString suiteShellContents = readFile(suiteShellPath); + + QFileInfoList testFileInfos = subSuiteDir.entryInfoList(QStringList() << "*.js", QDir::Files); + foreach (QFileInfo tfi, testFileInfos) { + if ((tfi.fileName() == "shell.js") || (tfi.fileName() == "browser.js")) + continue; + + QString abspath = tfi.absoluteFilePath(); + QString relpath = testsDir.relativeFilePath(abspath); + QString excludeMessage; + if (isExcludedFile(relpath, &excludeMessage)) { + QTest::newRow(relpath.toLatin1()) << TestRecord(excludeMessage, relpath); + continue; + } - QScriptEngine eng; - QScriptValue global = eng.globalObject(); - global.setProperty("print", eng.newFunction(qscript_void)); - global.setProperty("quit", eng.newFunction(qscript_quit)); - global.setProperty("options", eng.newFunction(qscript_options)); - - eng.evaluate(testsShellContents, testsShellPath); - if (eng.hasUncaughtException()) { - QStringList bt = eng.uncaughtExceptionBacktrace(); - QString err = eng.uncaughtException().toString(); - qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n"))); - break; - } + QScriptEngine eng; + QScriptValue global = eng.globalObject(); + global.setProperty("print", eng.newFunction(qscript_void)); + global.setProperty("quit", eng.newFunction(qscript_quit)); + global.setProperty("options", eng.newFunction(qscript_options)); + + eng.evaluate(testsShellContents, testsShellPath); + if (eng.hasUncaughtException()) { + QStringList bt = eng.uncaughtExceptionBacktrace(); + QString err = eng.uncaughtException().toString(); + qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n"))); + break; + } - eng.evaluate(suiteJsrefContents, suiteJsrefPath); - if (eng.hasUncaughtException()) { - QStringList bt = eng.uncaughtExceptionBacktrace(); - QString err = eng.uncaughtException().toString(); - qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n"))); - break; - } + eng.evaluate(suiteJsrefContents, suiteJsrefPath); + if (eng.hasUncaughtException()) { + QStringList bt = eng.uncaughtExceptionBacktrace(); + QString err = eng.uncaughtException().toString(); + qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n"))); + break; + } - eng.evaluate(suiteShellContents, suiteShellPath); - if (eng.hasUncaughtException()) { - QStringList bt = eng.uncaughtExceptionBacktrace(); - QString err = eng.uncaughtException().toString(); - qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n"))); - break; - } + eng.evaluate(suiteShellContents, suiteShellPath); + if (eng.hasUncaughtException()) { + QStringList bt = eng.uncaughtExceptionBacktrace(); + QString err = eng.uncaughtException().toString(); + qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n"))); + break; + } - eng.evaluate(subSuiteShellContents, subSuiteShellPath); - if (eng.hasUncaughtException()) { - QStringList bt = eng.uncaughtExceptionBacktrace(); - QString err = eng.uncaughtException().toString(); - qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n"))); - break; - } + eng.evaluate(subSuiteShellContents, subSuiteShellPath); + if (eng.hasUncaughtException()) { + QStringList bt = eng.uncaughtExceptionBacktrace(); + QString err = eng.uncaughtException().toString(); + qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n"))); + break; + } - QScriptValue origTestCaseCtor = global.property("TestCase"); - QScriptValue myTestCaseCtor = eng.newFunction(qscript_TestCase); - myTestCaseCtor.setData(origTestCaseCtor); - global.setProperty("TestCase", myTestCaseCtor); + QScriptValue origTestCaseCtor = global.property("TestCase"); + QScriptValue myTestCaseCtor = eng.newFunction(qscript_TestCase); + myTestCaseCtor.setData(origTestCaseCtor); + global.setProperty("TestCase", myTestCaseCtor); - global.setProperty("gTestfile", tfi.fileName()); - global.setProperty("gTestsuite", testSuiteDir.dirName()); - global.setProperty("gTestsubsuite", subSuiteDir.dirName()); - QString testFileContents = readFile(abspath); + global.setProperty("gTestfile", tfi.fileName()); + global.setProperty("gTestsuite", testSuiteDir.dirName()); + global.setProperty("gTestsubsuite", subSuiteDir.dirName()); + QString testFileContents = readFile(abspath); // qDebug() << relpath; - eng.evaluate(testFileContents, abspath); - if (eng.hasUncaughtException() && !relpath.endsWith("-n.js")) { - QStringList bt = eng.uncaughtExceptionBacktrace(); - QString err = eng.uncaughtException().toString(); - qWarning("%s\n%s\n", qPrintable(err), qPrintable(bt.join("\n"))); - continue; - } + eng.evaluate(testFileContents, abspath); + if (eng.hasUncaughtException() && !relpath.endsWith("-n.js")) { + QStringList bt = eng.uncaughtExceptionBacktrace(); + QString err = eng.uncaughtException().toString(); + qWarning("%s\n%s\n", qPrintable(err), qPrintable(bt.join("\n"))); + continue; + } - QScriptValue testcases = global.property("testcases"); - if (!testcases.isArray()) - testcases = global.property("gTestcases"); - int count = testcases.property("length").toInt32(); - if (count == 0) - continue; - - hasData = true; - QString title = global.property("TITLE").toString(); - for (int i = 0; i < count; ++i) { - QScriptValue kase = testcases.property(i); - QString description = kase.property("description").toString(); - QScriptValue expect = kase.property("expect"); - QScriptValue actual = kase.property("actual"); - bool passed = kase.property("passed").toBoolean(); - int lineNumber = kase.property("__lineNumber__").toInt32(); - - TestRecord rec(description, passed, - actual.toString(), expect.toString(), - relpath, lineNumber); - - QTest::newRow(description.toLatin1()) << rec; - } + QScriptValue testcases = global.property("testcases"); + if (!testcases.isArray()) + testcases = global.property("gTestcases"); + int count = testcases.property("length").toInt32(); + if (count == 0) + continue; + + hasData = true; + QString title = global.property("TITLE").toString(); + for (int i = 0; i < count; ++i) { + QScriptValue kase = testcases.property(i); + QString description = kase.property("description").toString(); + QScriptValue expect = kase.property("expect"); + QScriptValue actual = kase.property("actual"); + bool passed = kase.property("passed").toBoolean(); + int lineNumber = kase.property("__lineNumber__").toInt32(); + + TestRecord rec(description, passed, + actual.toString(), expect.toString(), + relpath, lineNumber); + + QTest::newRow(description.toLatin1()) << rec; } - if (!hasData) - QTest::newRow("") << TestRecord(); // dummy + } + if (!hasData) + QTest::newRow("") << TestRecord(); // dummy + } else { + QFETCH(TestRecord, record); + if ((record.lineNumber == -1) && (record.actual == "QSKIP")) { + QTest::qSkip(record.description.toLatin1(), QTest::SkipAll, record.fileName.toLatin1(), -1); } else { - QFETCH(TestRecord, record); - if ((record.lineNumber == -1) && (record.actual == "QSKIP")) { - QTest::qSkip(record.description.toLatin1(), QTest::SkipAll, record.fileName.toLatin1(), -1); - } else { - QString msg; - FailureItem::Action failAct; - bool expectFail = isExpectedFailure(record.fileName, record.description, &msg, &failAct); - if (expectFail) { - switch (failAct) { - case FailureItem::ExpectFail: - QTest::qExpectFail("", msg.toLatin1(), - QTest::Continue, record.fileName.toLatin1(), - record.lineNumber); - break; - case FailureItem::Skip: - QTest::qSkip(msg.toLatin1(), QTest::SkipSingle, - record.fileName.toLatin1(), record.lineNumber); - break; - } + QString msg; + FailureItem::Action failAct; + bool expectFail = isExpectedFailure(record.fileName, record.description, &msg, &failAct); + if (expectFail) { + switch (failAct) { + case FailureItem::ExpectFail: + QTest::qExpectFail("", msg.toLatin1(), + QTest::Continue, record.fileName.toLatin1(), + record.lineNumber); + break; + case FailureItem::Skip: + QTest::qSkip(msg.toLatin1(), QTest::SkipSingle, + record.fileName.toLatin1(), record.lineNumber); + break; } - if (!expectFail || (failAct == FailureItem::ExpectFail)) { - if (!record.passed) { -#ifdef GENERATE_ADDEXPECTEDFAILURE_CODE - if (!expectFail) { - QString escapedDescription = record.description; - escapedDescription.replace("\\", "\\\\"); - escapedDescription.replace("\n", "\\n"); - escapedDescription.replace("\"", "\\\""); - generatedAddExpectedFailureCode.append( - " addExpectedFailure(\"" + record.fileName - + "\", \"" + escapedDescription + - "\", willFixInNextReleaseMessage);\n"); - } -#endif - QTest::qCompare(record.actual, record.expected, "actual", "expect", - record.fileName.toLatin1(), record.lineNumber); - } else { - QTest::qCompare(record.actual, record.actual, "actual", "expect", - record.fileName.toLatin1(), record.lineNumber); + } + if (!expectFail || (failAct == FailureItem::ExpectFail)) { + if (!record.passed) { + if (!expectFail && shouldGenerateExpectedFailures) { + addExpectedFailure(record.fileName, + record.description, + QString()); } + QTest::qCompare(record.actual, record.expected, "actual", "expect", + record.fileName.toLatin1(), record.lineNumber); + } else { + QTest::qCompare(record.actual, record.actual, "actual", "expect", + record.fileName.toLatin1(), record.lineNumber); } } } - _id -= subSuitePaths.size()*2; } - return _id; } -tst_Suite::tst_Suite() +tst_QScriptJSTestSuite::tst_QScriptJSTestSuite() + : AbstractTestSuite("tst_QScriptJsTestSuite", + QString::fromLatin1("%0/tests").arg(SRCDIR), + ":/") { - testsDir = QDir(SRCDIR); - bool testsFound = testsDir.cd("tests"); - if (!testsFound) { - qWarning("*** no tests/ dir!"); - } - - QString willFixInNextReleaseMessage = QString::fromLatin1("Will fix in next release"); - QString fromCharCodeMessage = QString::fromLatin1("Test is wrong?"); - for (int i = 4256; i < 4294; ++i) { - addExpectedFailure("ecma/String/15.5.4.11-2.js", QString::fromLatin1("var s = new String( String.fromCharCode(%0) ); s.toLowerCase().charCodeAt(0)").arg(i), fromCharCodeMessage); - } - addExpectedFailure("ecma/String/15.5.4.11-5.js", "var s = new String( String.fromCharCode(1024) ); s.toLowerCase().charCodeAt(0)", fromCharCodeMessage); - addExpectedFailure("ecma/String/15.5.4.11-5.js", "var s = new String( String.fromCharCode(1037) ); s.toLowerCase().charCodeAt(0)", fromCharCodeMessage); - addExpectedFailure("ecma/String/15.5.4.12-1.js", "var s = new String( String.fromCharCode(181) ); s.toUpperCase().charCodeAt(0)", fromCharCodeMessage); - addExpectedFailure("ecma/String/15.5.4.12-1.js", "var s = new String( String.fromCharCode(329) ); s.toUpperCase().charCodeAt(0)", fromCharCodeMessage); - addExpectedFailure("ecma/String/15.5.4.12-4.js", "var s = new String( String.fromCharCode(1104) ); s.toUpperCase().charCodeAt(0)", fromCharCodeMessage); - addExpectedFailure("ecma/String/15.5.4.12-4.js", "var s = new String( String.fromCharCode(1117) ); s.toUpperCase().charCodeAt(0)", fromCharCodeMessage); - addExpectedFailure("ecma/String/15.5.4.12-5.js", "var s = new String( String.fromCharCode(1415) ); s.toUpperCase().charCodeAt(0)", fromCharCodeMessage); - - addExpectedFailure("ecma/TypeConversion/9.3.1-3.js", "- \"-0x123456789abcde8\"", willFixInNextReleaseMessage); - - addExpectedFailure("ecma/extensions/15.1.2.1-1.js", "var PROPS = ''; for ( p in eval ) { PROPS += p }; PROPS", willFixInNextReleaseMessage); - addExpectedFailure("ecma/GlobalObject/15.1.2.2-1.js", "var PROPS=''; for ( var p in parseInt ) { PROPS += p; }; PROPS", willFixInNextReleaseMessage); - - addExpectedFailure("ecma/GlobalObject/15.1.2.3-1.js", "var MYPROPS=''; for ( var p in parseFloat ) { MYPROPS += p }; MYPROPS", willFixInNextReleaseMessage); - addExpectedFailure("ecma/GlobalObject/15.1.2.4.js", "var MYPROPS=''; for ( var p in escape ) { MYPROPS+= p}; MYPROPS", willFixInNextReleaseMessage); - addExpectedFailure("ecma/GlobalObject/15.1.2.5-1.js", "var MYPROPS=''; for ( var p in unescape ) { MYPROPS+= p }; MYPROPS", willFixInNextReleaseMessage); - addExpectedFailure("ecma/GlobalObject/15.1.2.6.js", "var MYPROPS=''; for ( var p in isNaN ) { MYPROPS+= p }; MYPROPS", willFixInNextReleaseMessage); - addExpectedFailure("ecma/GlobalObject/15.1.2.7.js", "var MYPROPS=''; for ( p in isFinite ) { MYPROPS+= p }; MYPROPS", willFixInNextReleaseMessage); - - addExpectedFailure(QRegExp(), "NO TESTS EXIST", willFixInNextReleaseMessage); - - addExpectedFailure("ecma_3/Array/15.4.5.1-01.js", "15.4.5.1 - array.length coverage", willFixInNextReleaseMessage); - - addExpectedFailure("ecma_3/extensions/regress-228087-002.js", - "Section 1 of test - \nregexp = /{1.*}/g\n" - "string = 'foo {1} foo {2} foo'\n" - "ERROR !!! match arrays have different lengths:\n" - "Expect: [\"{1} foo {2}\"]\n" - "Actual: []", willFixInNextReleaseMessage); - - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", - "Section 1 of test - \n" - "regexp = /a|ab/\n" - "string = 'abc'\n" - "ERROR !!! regexp failed to give expected match array:\n" - "Expect: [\"a\"]\n" - "Actual: [\"ab\"]\n", willFixInNextReleaseMessage); - - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", - "Section 2 of test - \n" - "regexp = /((a)|(ab))((c)|(bc))/\n" - "string = 'abc'\n" - "ERROR !!! regexp failed to give expected match array:\n" - "Expect: [\"abc\", \"a\", \"a\", , \"bc\", , \"bc\"]\n" - "Actual: [\"abc\", \"ab\", \"\", \"ab\", \"c\", \"c\", \"\"]\n", willFixInNextReleaseMessage); - - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", - "Section 4 of test - \n" - "regexp = /a[a-z]{2,4}?/\n" - "string = 'abcdefghi'\n" - "ERROR !!! regexp FAILED to match anything !!!\n" - "Expect: abc\n" - "Actual: null\n", willFixInNextReleaseMessage); - - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js(317)", - "Section 5 of test - \n" - "regexp = /(aa|aabaac|ba|b|c)*/\n" - "string = 'aabaac'\n" - "ERROR !!! regexp failed to give expected match array:\n" - "Expect: [\"aaba\", \"ba\"]\n" - "Actual: [\"aabaac\", \"aabaac\"]\n", willFixInNextReleaseMessage); - - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 1 of test - \nregexp = /{1.*}/g\nstring = 'foo {1} foo {2} foo'\nERROR !!! match arrays have different lengths:\nExpect: [\"{1} foo {2}\"]\nActual: []\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 2 of test - \nregexp = /{1.*}/g\nstring = 'foo {1} foo {2} foo'\nERROR !!! match arrays have different lengths:\nExpect: [\"{1} foo {2}\"]\nActual: []\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 3 of test - \nregexp = /{1[.!}]*}/g\nstring = 'foo {1} foo {2} foo'\nERROR !!! match arrays have different lengths:\nExpect: [\"{1}\"]\nActual: []\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 4 of test - \nregexp = /{1[.!}]*}/g\nstring = 'foo {1} foo {2} foo'\nERROR !!! match arrays have different lengths:\nExpect: [\"{1}\"]\nActual: []\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 6 of test - \nregexp = /c{3 }/\nstring = 'abccccc{3 }c{ 3}c{3, }c{3 ,}c{3 ,4}c{3, 4}c{3,4 }de'\nERROR !!! regexp FAILED to match anything !!!\nExpect: c{3 }\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 7 of test - \nregexp = /c{3.}/\nstring = 'abccccc{3 }c{ 3}c{3, }c{3 ,}c{3 ,4}c{3, 4}c{3,4 }de'\nERROR !!! regexp FAILED to match anything !!!\nExpect: c{3 }\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 8 of test - \nregexp = /c{3\\s}/\nstring = 'abccccc{3 }c{ 3}c{3, }c{3 ,}c{3 ,4}c{3, 4}c{3,4 }de'\nERROR !!! regexp FAILED to match anything !!!\nExpect: c{3 }\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 9 of test - \nregexp = /c{3[ ]}/\nstring = 'abccccc{3 }c{ 3}c{3, }c{3 ,}c{3 ,4}c{3, 4}c{3,4 }de'\nERROR !!! regexp FAILED to match anything !!!\nExpect: c{3 }\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 10 of test - \nregexp = /c{ 3}/\nstring = 'abccccc{3 }c{ 3}c{3, }c{3 ,}c{3 ,4}c{3, 4}c{3,4 }de'\nERROR !!! regexp FAILED to match anything !!!\nExpect: c{ 3}\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 12 of test - \nregexp = /c{3, }/\nstring = 'abccccc{3 }c{ 3}c{3, }c{3 ,}c{3 ,4}c{3, 4}c{3,4 }de'\nERROR !!! regexp FAILED to match anything !!!\nExpect: c{3, }\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 13 of test - \nregexp = /c{3 ,}/\nstring = 'abccccc{3 }c{ 3}c{3, }c{3 ,}c{3 ,4}c{3, 4}c{3,4 }de'\nERROR !!! regexp FAILED to match anything !!!\nExpect: c{3 ,}\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 15 of test - \nregexp = /c{3 ,4}/\nstring = 'abccccc{3 }c{ 3}c{3, }c{3 ,}c{3 ,4}c{3, 4}c{3,4 }de'\nERROR !!! regexp FAILED to match anything !!!\nExpect: c{3 ,4}\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 16 of test - \nregexp = /c{3, 4}/\nstring = 'abccccc{3 }c{ 3}c{3, }c{3 ,}c{3 ,4}c{3, 4}c{3,4 }de'\nERROR !!! regexp FAILED to match anything !!!\nExpect: c{3, 4}\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-228087.js", "Section 17 of test - \nregexp = /c{3,4 }/\nstring = 'abccccc{3 }c{ 3}c{3, }c{3 ,}c{3 ,4}c{3, 4}c{3,4 }de'\nERROR !!! regexp FAILED to match anything !!!\nExpect: c{3,4 }\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-274152.js", "Do not ignore unicode format-control characters: 0", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-274152.js", "Do not ignore unicode format-control characters: 1", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-274152.js", "Do not ignore unicode format-control characters: 2", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-274152.js", "Do not ignore unicode format-control characters: 3", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-274152.js", "Do not ignore unicode format-control characters: 4", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-274152.js", "Do not ignore unicode format-control characters: 5", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-274152.js", "Do not ignore unicode format-control characters: 6", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-274152.js", "Do not ignore unicode format-control characters: 7", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-274152.js", "Do not ignore unicode format-control characters: 8", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-368516.js", "Treat unicode BOM characters as whitespace: 0", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/extensions/regress-368516.js", "Treat unicode BOM characters as whitespace: 1", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/FunExpr/fe-001-n.js", "Previous statement should have thrown a ReferenceError", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/LexicalConventions/7.9.1.js", "Automatic Semicolon insertion in postfix expressions: expr\n++", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/LexicalConventions/7.9.1.js", "Automatic Semicolon insertion in postfix expressions: expr\n--", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/LexicalConventions/7.9.1.js", "Automatic Semicolon insertion in postfix expressions: (x\n)-- y", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/LexicalConventions/7.9.1.js", "Automatic Semicolon insertion in postfix expressions: (x)-- y", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Object/8.6.1-01.js", "In strict mode, setting a read-only property should generate a warning: Throw if STRICT and WERROR is enabled", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Operators/order-01.js", "operator evaluation order: 11.8.2 >", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Operators/order-01.js", "operator evaluation order: 11.8.4 >=", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", "Section 5 of test - \nregexp = /(aa|aabaac|ba|b|c)*/\nstring = 'aabaac'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"aaba\", \"ba\"]\nActual: [\"aabaac\", \"aabaac\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", "Section 6 of test - \nregexp = /^(a+)\\1*,\\1+$/\nstring = 'aaaaaaaaaa,aaaaaaaaaaaaaaa'\nERROR !!! regexp FAILED to match anything !!!\nExpect: aaaaaaaaaa,aaaaaaaaaaaaaaa,aaaaa\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", "Section 7 of test - \nregexp = /(z)((a+)?(b+)?(c))*/\nstring = 'zaacbbbcac'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"zaacbbbcac\", \"z\", \"ac\", \"a\", , \"c\"]\nActual: [\"zaacbbbcac\", \"z\", \"ac\", \"a\", \"\", \"c\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", "Section 8 of test - \nregexp = /(a*)*/\nstring = 'b'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"\", , ]\nActual: [\"\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", "Section 10 of test - \nregexp = /(?=(a+))/\nstring = 'baaabac'\nERROR !!! match arrays have different lengths:\nExpect: [\"\", \"aaa\"]\nActual: [\"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", "Section 11 of test - \nregexp = /(?=(a+))a*b\\1/\nstring = 'baaabac'\nERROR !!! match arrays have different lengths:\nExpect: [\"aba\", \"a\"]\nActual: [\"aaab\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", "Section 12 of test - \nregexp = /(.*?)a(?!(a+)b\\2c)\\2(.*)/\nstring = 'baaabaac'\nERROR !!! regexp FAILED to match anything !!!\nExpect: baaabaac,ba,,abaac\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", "Section 13 of test - \nregexp = /(?=(a+))/\nstring = 'baaabac'\nERROR !!! match arrays have different lengths:\nExpect: [\"\", \"aaa\"]\nActual: [\"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 34 of test - \nregexp = /a]/\nstring = 'a]'\nERROR !!! regexp FAILED to match anything !!!\nExpect: a]\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 66 of test - \nregexp = /a.+?c/\nstring = 'abcabc'\nERROR !!! regexp FAILED to match anything !!!\nExpect: abc\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 94 of test - \nregexp = /^a(bc+|b[eh])g|.h$/\nstring = 'abh'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"bh\", , ]\nActual: [\"bh\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 95 of test - \nregexp = /(bc+d$|ef*g.|h?i(j|k))/\nstring = 'effgz'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"effgz\", \"effgz\", , ]\nActual: [\"effgz\", \"effgz\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 97 of test - \nregexp = /(bc+d$|ef*g.|h?i(j|k))/\nstring = 'reffgz'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"effgz\", \"effgz\", , ]\nActual: [\"effgz\", \"effgz\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 109 of test - \nregexp = /(([a-c])b*?\\2)*/\nstring = 'ababbbcbc'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ababb,bb,b\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 110 of test - \nregexp = /(([a-c])b*?\\2){3}/\nstring = 'ababbbcbc'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ababbbcbc,cbc,c\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 119 of test - \nregexp = /ab*?bc/i\nstring = 'ABBBBC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABBBBC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 120 of test - \nregexp = /ab{0,}?bc/i\nstring = 'ABBBBC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABBBBC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 121 of test - \nregexp = /ab+?bc/i\nstring = 'ABBC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABBC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 123 of test - \nregexp = /ab{1,}?bc/i\nstring = 'ABBBBC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABBBBC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 124 of test - \nregexp = /ab{1,3}?bc/i\nstring = 'ABBBBC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABBBBC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 125 of test - \nregexp = /ab{3,4}?bc/i\nstring = 'ABBBBC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABBBBC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 126 of test - \nregexp = /ab??bc/i\nstring = 'ABBC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABBC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 127 of test - \nregexp = /ab??bc/i\nstring = 'ABC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 128 of test - \nregexp = /ab{0,1}?bc/i\nstring = 'ABC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 129 of test - \nregexp = /ab??c/i\nstring = 'ABC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 130 of test - \nregexp = /ab{0,1}?c/i\nstring = 'ABC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 138 of test - \nregexp = /a.*?c/i\nstring = 'AXYZC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: AXYZC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 144 of test - \nregexp = /a]/i\nstring = 'A]'\nERROR !!! regexp FAILED to match anything !!!\nExpect: A]\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 160 of test - \nregexp = /a.+?c/i\nstring = 'ABCABC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 161 of test - \nregexp = /a.*?c/i\nstring = 'ABCABC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 162 of test - \nregexp = /a.{0,5}?c/i\nstring = 'ABCABC'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ABC\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 169 of test - \nregexp = /(a+|b){0,1}?/i\nstring = 'AB'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ,\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 191 of test - \nregexp = /^a(bc+|b[eh])g|.h$/i\nstring = 'ABH'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"BH\", , ]\nActual: [\"BH\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 192 of test - \nregexp = /(bc+d$|ef*g.|h?i(j|k))/i\nstring = 'EFFGZ'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"EFFGZ\", \"EFFGZ\", , ]\nActual: [\"EFFGZ\", \"EFFGZ\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 194 of test - \nregexp = /(bc+d$|ef*g.|h?i(j|k))/i\nstring = 'REFFGZ'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"EFFGZ\", \"EFFGZ\", , ]\nActual: [\"EFFGZ\", \"EFFGZ\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 212 of test - \nregexp = /a(?:b|c|d)+?(.)/\nstring = 'ace'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ace,e\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 213 of test - \nregexp = /a(?:b|c|d)+?(.)/\nstring = 'acdbcdbe'\nERROR !!! regexp FAILED to match anything !!!\nExpect: acd,d\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 217 of test - \nregexp = /a(?:b|c|d){4,5}?(.)/\nstring = 'acdbcdbe'\nERROR !!! regexp FAILED to match anything !!!\nExpect: acdbcd,d\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 218 of test - \nregexp = /((foo)|(bar))*/\nstring = 'foobar'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"foobar\", \"bar\", , \"bar\"]\nActual: [\"foobar\", \"bar\", \"\", \"bar\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 220 of test - \nregexp = /a(?:b|c|d){6,7}?(.)/\nstring = 'acdbcdbe'\nERROR !!! regexp FAILED to match anything !!!\nExpect: acdbcdbe,e\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 222 of test - \nregexp = /a(?:b|c|d){5,6}?(.)/\nstring = 'acdbcdbe'\nERROR !!! regexp FAILED to match anything !!!\nExpect: acdbcdb,b\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 224 of test - \nregexp = /a(?:b|c|d){5,7}?(.)/\nstring = 'acdbcdbe'\nERROR !!! regexp FAILED to match anything !!!\nExpect: acdbcdb,b\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 225 of test - \nregexp = /a(?:b|(c|e){1,2}?|d)+?(.)/\nstring = 'ace'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ace,c,e\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 227 of test - \nregexp = /^([^a-z])|(\\^)$/\nstring = '.'\nERROR !!! regexp failed to give expected match array:\nExpect: [\".\", \".\", , ]\nActual: [\".\", \".\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 234 of test - \nregexp = /(?:(f)(o)(o)|(b)(a)(r))*/\nstring = 'foobar'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"foobar\", , , , \"b\", \"a\", \"r\"]\nActual: [\"foobar\", \"\", \"\", \"\", \"b\", \"a\", \"r\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 240 of test - \nregexp = /(?:..)*?a/\nstring = 'aba'\nERROR !!! regexp FAILED to match anything !!!\nExpect: a\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 241 of test - \nregexp = /^(?:b|a(?=(.)))*\\1/\nstring = 'abc'\nERROR !!! match arrays have different lengths:\nExpect: [\"ab\", , ]\nActual: [\"ab\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 246 of test - \nregexp = /(a|x)*ab/\nstring = 'cab'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"ab\", , ]\nActual: [\"ab\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 247 of test - \nregexp = /(a)*ab/\nstring = 'cab'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"ab\", , ]\nActual: [\"ab\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 300 of test - \nregexp = /(?=(a+?))(\\1ab)/\nstring = 'aaab'\nERROR !!! regexp FAILED to match anything !!!\nExpect: aab,a,aab\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 303 of test - \nregexp = /(?=(a+?))(\\1ab)/\nstring = 'aaab'\nERROR !!! regexp FAILED to match anything !!!\nExpect: aab,a,aab\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 304 of test - \nregexp = /([\\w:]+::)?(\\w+)$/\nstring = 'abcd'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"abcd\", , \"abcd\"]\nActual: [\"abcd\", \"\", \"abcd\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 308 of test - \nregexp = /([\\w:]+::)?(\\w+)$/\nstring = 'abcd'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"abcd\", , \"abcd\"]\nActual: [\"abcd\", \"\", \"abcd\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 342 of test - \nregexp = /a$/m\nstring = 'a\\nb\\n'\nERROR !!! regexp FAILED to match anything !!!\nExpect: a\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 344 of test - \nregexp = /a$/m\nstring = 'b\\na\\n'\nERROR !!! regexp FAILED to match anything !!!\nExpect: a\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 353 of test - \nregexp = /aa$/m\nstring = 'aa\\nb\\n'\nERROR !!! regexp FAILED to match anything !!!\nExpect: aa\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 355 of test - \nregexp = /aa$/m\nstring = 'b\\naa\\n'\nERROR !!! regexp FAILED to match anything !!!\nExpect: aa\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 364 of test - \nregexp = /ab$/m\nstring = 'ab\\nb\\n'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ab\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 366 of test - \nregexp = /ab$/m\nstring = 'b\\nab\\n'\nERROR !!! regexp FAILED to match anything !!!\nExpect: ab\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 375 of test - \nregexp = /abb$/m\nstring = 'abb\\nb\\n'\nERROR !!! regexp FAILED to match anything !!!\nExpect: abb\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 377 of test - \nregexp = /abb$/m\nstring = 'b\\nabb\\n'\nERROR !!! regexp FAILED to match anything !!!\nExpect: abb\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 383 of test - \nregexp = /^d[x][x][x]/m\nstring = 'abcd\\ndxxx'\nERROR !!! regexp FAILED to match anything !!!\nExpect: dxxx\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 391 of test - \nregexp = /\\.c(pp|xx|c)?$/i\nstring = 'IO.c'\nERROR !!! regexp failed to give expected match array:\nExpect: [\".c\", , ]\nActual: [\".c\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 392 of test - \nregexp = /(\\.c(pp|xx|c)?$)/i\nstring = 'IO.c'\nERROR !!! regexp failed to give expected match array:\nExpect: [\".c\", \".c\", , ]\nActual: [\".c\", \".c\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 394 of test - \nregexp = /^([ab]*?)(b)?(c)$/\nstring = 'abac'\nERROR !!! regexp FAILED to match anything !!!\nExpect: abac,aba,,c\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 412 of test - \nregexp = /^(a(b)?)+$/\nstring = 'aba'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"aba\", \"a\", , ]\nActual: [\"aba\", \"a\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 413 of test - \nregexp = /^(aa(bb)?)+$/\nstring = 'aabbaa'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"aabbaa\", \"aa\", , ]\nActual: [\"aabbaa\", \"aa\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 414 of test - \nregexp = /^.{9}abc.*\\n/m\nstring = '123\\nabcabcabcabc\\n'\nERROR !!! regexp FAILED to match anything !!!\nExpect: abcabcabcabc\n\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 415 of test - \nregexp = /^(a)?a$/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"a\", , ]\nActual: [\"a\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 416 of test - \nregexp = /^(a\\1?)(a\\1?)(a\\2?)(a\\3?)$/\nstring = 'aaaaaa'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"aaaaaa\", \"a\", \"aa\", \"a\", \"aa\"]\nActual: [\"aaaaaa\", \"aa\", \"a\", \"aa\", \"a\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 418 of test - \nregexp = /^(0+)?(?:x(1))?/\nstring = 'x1'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"x1\", , \"1\"]\nActual: [\"x1\", \"\", \"1\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 419 of test - \nregexp = /^([0-9a-fA-F]+)(?:x([0-9a-fA-F]+)?)(?:x([0-9a-fA-F]+))?/\nstring = '012cxx0190'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"012cxx0190\", \"012c\", , \"0190\"]\nActual: [\"012cxx0190\", \"012c\", \"\", \"0190\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 420 of test - \nregexp = /^(b+?|a){1,2}c/\nstring = 'bbbac'\nERROR !!! regexp FAILED to match anything !!!\nExpect: bbbac,a\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 421 of test - \nregexp = /^(b+?|a){1,2}c/\nstring = 'bbbbac'\nERROR !!! regexp FAILED to match anything !!!\nExpect: bbbbac,a\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-002.js", "Section 40 of test - \nregexp = /(a)|\\1/\nstring = 'x'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"\", , ]\nActual: [\"\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-105972.js", "Section 1 of test - \nregexp = /^.*?$/\nstring = 'Hello World'\nERROR !!! regexp FAILED to match anything !!!\nExpect: Hello World\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-105972.js", "Section 2 of test - \nregexp = /^.*?/\nstring = 'Hello World'\nERROR !!! regexp FAILED to match anything !!!\nExpect: \nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-105972.js", "Section 3 of test - \nregexp = /^.*?(:|$)/\nstring = 'Hello: World'\nERROR !!! regexp FAILED to match anything !!!\nExpect: Hello:,:\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-123437.js", "Section 1 of test - \nregexp = /(a)?a/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"a\", , ]\nActual: [\"a\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-123437.js", "Section 2 of test - \nregexp = /a|(b)/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"a\", , ]\nActual: [\"a\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-123437.js", "Section 3 of test - \nregexp = /(a)?(a)/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"a\", , \"a\"]\nActual: [\"a\", \"\", \"a\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-165353.js", "Section 1 of test - \nregexp = /^([a-z]+)*[a-z]$/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"a\", , ]\nActual: [\"a\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-169497.js", "Section 1 of test - \nregexp = /<body.*>((.*\\n?)*?)<\\/body>/i\nstring = '<html>\\n<body onXXX=\"alert(event.type);\">\\n<p>Kibology for all</p>\\n<p>All for Kibology</p>\\n</body>\\n</html>'\nERROR !!! regexp FAILED to match anything !!!\nExpect: <body onXXX=\"alert(event.type);\">\n<p>Kibology for all</p>\n<p>All for Kibology</p>\n</body>,\n<p>Kibology for all</p>\n<p>All for Kibology</p>\n,<p>All for Kibology</p>\n\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-187133.js", "Section 5 of test - \nregexp = /(?!a|b)|c/\nstring = 'bc'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"\"]\nActual: [\"c\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-191479.js", "Section 1 of test - \nregexp = /(\\d|\\d\\s){2,}/\nstring = '12 3 45'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"12\", \"2\"]\nActual: [\"12 3 45\", \"5\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-191479.js", "Section 3 of test - \nregexp = /(\\d|\\d\\s)+/\nstring = '12 3 45'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"12\", \"2\"]\nActual: [\"12 3 45\", \"5\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-191479.js", "Section 8 of test - \nregexp = /(\\d|\\d\\s){2,}?/\nstring = '12 3 45'\nERROR !!! regexp FAILED to match anything !!!\nExpect: 12,2\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-191479.js", "Section 9 of test - \nregexp = /(\\d|\\d\\s){4,}?/\nstring = '12 3 45'\nERROR !!! regexp FAILED to match anything !!!\nExpect: 12 3 4,4\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-191479.js", "Section 10 of test - \nregexp = /(\\d|\\d\\s)+?/\nstring = '12 3 45'\nERROR !!! regexp FAILED to match anything !!!\nExpect: 1,1\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-191479.js", "Section 11 of test - \nregexp = /(\\d\\s?){4,}?/\nstring = '12 3 45'\nERROR !!! regexp FAILED to match anything !!!\nExpect: 12 3 4,4\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-191479.js", "Section 12 of test - \nregexp = /(\\d\\s|\\d){2,}?/\nstring = '12 3 45'\nERROR !!! regexp FAILED to match anything !!!\nExpect: 12 ,2 \nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-191479.js", "Section 13 of test - \nregexp = /(\\d\\s|\\d){4,}?/\nstring = '12 3 45'\nERROR !!! regexp FAILED to match anything !!!\nExpect: 12 3 4,4\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-191479.js", "Section 14 of test - \nregexp = /(\\d\\s|\\d)+?/\nstring = '12 3 45'\nERROR !!! regexp FAILED to match anything !!!\nExpect: 1,1\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-202564.js", "Section 1 of test - \nregexp = /(?:(.+), )?(.+), (..) to (?:(.+), )?(.+), (..)/\nstring = 'Seattle, WA to Buckley, WA'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"Seattle, WA to Buckley, WA\", , \"Seattle\", \"WA\", , \"Buckley\", \"WA\"]\nActual: [\"Seattle, WA to Buckley, WA\", \"\", \"Seattle\", \"WA\", \"\", \"Buckley\", \"WA\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-209919.js", "Section 2 of test - \nregexp = /(a|b*){5,}/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"a\", \"\"]\nActual: [\"a\", \"a\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-209919.js", "Section 3 of test - \nregexp = /(b*)*/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"\", , ]\nActual: [\"\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-209919.js", "Section 5 of test - \nregexp = /^\\-?(\\d{1,}|\\.{0,})*(\\,\\d{1,})?$/\nstring = '100.00'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"100.00\", \"00\", , ]\nActual: [\"100.00\", \"00\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-216591.js", "Section 1 of test - \nregexp = /\\{(([a-z0-9\\-_]+?\\.)+?)([a-z0-9\\-_]+?)\\}/i\nstring = 'a {result.data.DATA} b'\nERROR !!! regexp FAILED to match anything !!!\nExpect: {result.data.DATA},result.data.,data.,DATA\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-216591.js", "Section 2 of test - \nregexp = /\\{(([a-z0-9\\-_]+?\\.)+?)([a-z0-9\\-_]+?)\\}/gi\nstring = 'a {result.data.DATA} b'\nERROR !!! match arrays have different lengths:\nExpect: [\"{result.data.DATA}\"]\nActual: []\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-220367-001.js", "Section 1 of test - \nregexp = /(a)|(b)/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"a\", \"a\", , ]\nActual: [\"a\", \"a\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-220367-001.js", "Section 2 of test - \nregexp = /(a)|(b)/\nstring = 'b'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"b\", , \"b\"]\nActual: [\"b\", \"\", \"b\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-223535.js", "Section 2 of test - \nregexp = /|a/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"\"]\nActual: [\"a\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-223535.js", "Section 6 of test - \nregexp = /(|a)/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"\", \"\"]\nActual: [\"a\", \"a\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-223535.js", "Section 7 of test - \nregexp = /(|a|)/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"\", \"\"]\nActual: [\"a\", \"a\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-224676.js", "Section 17 of test - \nregexp = /[x]b|(a)/\nstring = 'ZZZxbZZZ'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"xb\", , ]\nActual: [\"xb\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-224676.js", "Section 18 of test - \nregexp = /[x]b|()a/\nstring = 'ZZZxbZZZ'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"xb\", , ]\nActual: [\"xb\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-225289.js", "Section 7 of test - \nregexp = /(a)|([^a])/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"a\", \"a\", , ]\nActual: [\"a\", \"a\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-225289.js", "Section 9 of test - \nregexp = /(a)|([^a])/\nstring = '()'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"(\", , \"(\"]\nActual: [\"(\", \"\", \"(\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-225289.js", "Section 10 of test - \nregexp = /((?:a|[^a])*)/g\nstring = 'a'\nERROR !!! match arrays have different lengths:\nExpect: [\"a\", \"\"]\nActual: [\"a\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-225289.js", "Section 11 of test - \nregexp = /((?:a|[^a])*)/g\nstring = ''\nERROR !!! match arrays have different lengths:\nExpect: [\"\"]\nActual: []\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-225289.js", "Section 12 of test - \nregexp = /((?:a|[^a])*)/g\nstring = '()'\nERROR !!! match arrays have different lengths:\nExpect: [\"()\", \"\"]\nActual: [\"()\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-31316.js", "Section 1 of test - \nregexp = /<([^\\/<>][^<>]*[^\\/])>|<([^\\/<>])>/\nstring = '<p>Some<br />test</p>'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"<p>\", , \"p\"]\nActual: [\"<p>\", \"\", \"p\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-330684.js", "Do not hang on RegExp", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-375711.js", "Do not assert with /[Q-b]/i.exec(\"\"): /[q-b]/.exec(\"\")", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-375711.js", "Do not assert with /[Q-b]/i.exec(\"\"): /[q-b]/i.exec(\"\")", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '(?)'and flag 'i'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '(?)'and flag 'g'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '(?)'and flag 'm'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '(?)'and flag 'undefined'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '(a'and flag 'i'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '(a'and flag 'g'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '(a'and flag 'm'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '(a'and flag 'undefined'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '( ]'and flag 'i'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '( ]'and flag 'g'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '( ]'and flag 'm'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-57631.js", "Testing for error creating illegal RegExp object on pattern '( ]'and flag 'undefined'", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-78156.js", "Section 1 of test - \nregexp = /^\\d/gm\nstring = 'aaa\\n789\\r\\nccc\\r\\n345'\nERROR !!! match arrays have different lengths:\nExpect: [\"7\", \"3\"]\nActual: []\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-78156.js", "Section 2 of test - \nregexp = /\\d$/gm\nstring = 'aaa\\n789\\r\\nccc\\r\\n345'\nERROR !!! match arrays have different lengths:\nExpect: [\"9\", \"5\"]\nActual: [\"5\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-78156.js", "Section 3 of test - \nregexp = /^\\d/gm\nstring = 'aaa\\n789\\r\\nccc\\r\\nddd'\nERROR !!! match arrays have different lengths:\nExpect: [\"7\"]\nActual: []\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-78156.js", "Section 4 of test - \nregexp = /\\d$/gm\nstring = 'aaa\\n789\\r\\nccc\\r\\nddd'\nERROR !!! match arrays have different lengths:\nExpect: [\"9\"]\nActual: []\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-85721.js", "Section 2 of test - \nregexp = /<sql:connection id=\"([^\\r\\n]*?)\">\\s*<sql:url>\\s*([^\\r\\n]*?)\\s*<\\/sql:url>\\s*<sql:driver>\\s*([^\\r\\n]*?)\\s*<\\/sql:driver>\\s*(\\s*<sql:userId>\\s*([^\\r\\n]*?)\\s*<\\/sql:userId>\\s*)?\\s*(\\s*<sql:password>\\s*([^\\r\\n]*?)\\s*<\\/sql:password>\\s*)?\\s*<\\/sql:connection>/\nstring = '<sql:connection id=\"conn1\"> <sql:url>www.m.com</sql:url> <sql:driver>drive.class</sql:driver>\\n<sql:userId>foo</sql:userId> <sql:password>goo</sql:password> </sql:connection>'\nERROR !!! regexp FAILED to match anything !!!\nExpect: <sql:connection id=\"conn1\"> <sql:url>www.m.com</sql:url> <sql:driver>drive.class</sql:driver>\n<sql:userId>foo</sql:userId> <sql:password>goo</sql:password> </sql:connection>,conn1,www.m.com,drive.class,<sql:userId>foo</sql:userId> ,foo,<sql:password>goo</sql:password> ,goo\nActual: null\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-87231.js", "Section 3 of test - \nregexp = /^(A)?(A.*)$/\nstring = 'A'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"A\", , \"A\"]\nActual: [\"A\", \"\", \"A\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-87231.js", "Section 6 of test - \nregexp = /(A)?(A.*)/\nstring = 'zxcasd;fl\\ ^AaaAAaaaf;lrlrzs'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"AaaAAaaaf;lrlrzs\", , \"AaaAAaaaf;lrlrzs\"]\nActual: [\"AaaAAaaaf;lrlrzs\", \"\", \"AaaAAaaaf;lrlrzs\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/String/15.5.4.11.js", "Section 24", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/String/15.5.4.11.js", "Section 28", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/String/15.5.4.11.js", "Section 30", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/String/15.5.4.14.js", "15.5.4.14 - String.prototype.split(/()/)", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Unicode/regress-352044-01.js", "issues with Unicode escape sequences in JavaScript source code", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Unicode/uc-001.js", "Unicode format-control character test (Category Cf.)", willFixInNextReleaseMessage); - - addFileExclusion(".+/15\\.9\\.2\\..+", "unstable on slow machines"); - addFileExclusion(".+/15\\.9\\.5\\..+", "too slooow"); - addFileExclusion("regress-130451.js", "asserts"); - addFileExclusion("regress-322135-01.js", "asserts"); - addFileExclusion("regress-322135-02.js", "asserts"); - addFileExclusion("regress-322135-03.js", "takes forever"); - addFileExclusion("regress-322135-04.js", "takes forever"); - addFileExclusion("ecma_3/RegExp/regress-375715-04.js", "bug"); - - addFileExclusion("ecma_3/RegExp/regress-289669.js", "Can fail due to relying on wall-clock time"); - - // Failures due to switch to JSC as back-end - addExpectedFailure("ecma/Array/15.4.3.1-2.js", "var props = ''; for ( p in Array ) { props += p } props", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Boolean/15.6.3.1-1.js", "var str='';for ( p in Boolean ) { str += p } str;", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Expressions/11.4.1.js", "var abc; delete(abc)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/FunctionObjects/15.3.3.1-2.js", "var str='';for (prop in Function ) str += prop; str;", willFixInNextReleaseMessage); - addExpectedFailure("ecma/ObjectObjects/15.2.3.1-1.js", "var str = '';for ( p in Object ) { str += p; }; str", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Statements/12.6.3-11.js", "result = \"\"; for ( p in Number ) { result += String(p) };", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Statements/12.6.3-2.js", "Boolean.prototype.foo = 34; for ( j in Boolean ) Boolean[j]", willFixInNextReleaseMessage); - addExpectedFailure("ecma/TypeConversion/9.3.1-3.js", "-\"\\u20001234\\u2001\"", willFixInNextReleaseMessage); - addExpectedFailure("ecma_2/RegExp/properties-001.js", "//.toString()", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Date/15.9.4.3.js", "15.9.4.3 - Date.UTC edge-case arguments.: date Infinity", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Date/15.9.4.3.js", "15.9.4.3 - Date.UTC edge-case arguments.: hours Infinity", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Date/15.9.4.3.js", "15.9.4.3 - Date.UTC edge-case arguments.: minutes Infinity", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Date/15.9.4.3.js", "15.9.4.3 - Date.UTC edge-case arguments.: seconds Infinity", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Function/regress-131964.js", "Section 1 of test - ", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Function/regress-313570.js", "length of objects whose prototype chain includes a function: immutable", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/FunExpr/fe-001.js", "Both functions were defined.", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", "Section 7 of test - \nregexp = /(z)((a+)?(b+)?(c))*/\nstring = 'zaacbbbcac'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"zaacbbbcac\", \"z\", \"ac\", \"a\", , \"c\"]\nActual: [\"zaacbbbcac\", \"z\", \"ac\", \"a\", \"bbb\", \"c\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/15.10.2-1.js", "Section 12 of test - \nregexp = /(.*?)a(?!(a+)b\\2c)\\2(.*)/\nstring = 'baaabaac'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"baaabaac\", \"ba\", , \"abaac\"]\nActual: [\"baaabaac\", \"ba\", \"aa\", \"abaac\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 218 of test - \nregexp = /((foo)|(bar))*/\nstring = 'foobar'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"foobar\", \"bar\", , \"bar\"]\nActual: [\"foobar\", \"bar\", \"foo\", \"bar\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 234 of test - \nregexp = /(?:(f)(o)(o)|(b)(a)(r))*/\nstring = 'foobar'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"foobar\", , , , \"b\", \"a\", \"r\"]\nActual: [\"foobar\", \"f\", \"o\", \"o\", \"b\", \"a\", \"r\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 241 of test - \nregexp = /^(?:b|a(?=(.)))*\\1/\nstring = 'abc'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"ab\", , ]\nActual: [\"ab\", \"b\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 412 of test - \nregexp = /^(a(b)?)+$/\nstring = 'aba'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"aba\", \"a\", , ]\nActual: [\"aba\", \"a\", \"b\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/perlstress-001.js", "Section 413 of test - \nregexp = /^(aa(bb)?)+$/\nstring = 'aabbaa'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"aabbaa\", \"aa\", , ]\nActual: [\"aabbaa\", \"aa\", \"bb\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-209919.js", "Section 1 of test - \nregexp = /(a|b*)*/\nstring = 'a'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"a\", \"a\"]\nActual: [\"a\", \"\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-209919.js", "Section 5 of test - \nregexp = /^\\-?(\\d{1,}|\\.{0,})*(\\,\\d{1,})?$/\nstring = '100.00'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"100.00\", \"00\", , ]\nActual: [\"100.00\", \"\", , ]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-209919.js", "Section 6 of test - \nregexp = /^\\-?(\\d{1,}|\\.{0,})*(\\,\\d{1,})?$/\nstring = '100,00'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"100,00\", \"100\", \",00\"]\nActual: [\"100,00\", \"\", \",00\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-209919.js", "Section 7 of test - \nregexp = /^\\-?(\\d{1,}|\\.{0,})*(\\,\\d{1,})?$/\nstring = '1.000,00'\nERROR !!! regexp failed to give expected match array:\nExpect: [\"1.000,00\", \"000\", \",00\"]\nActual: [\"1.000,00\", \"\", \",00\"]\n", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/RegExp/regress-311414.js", "RegExp captured tail match should be O(N) BigO 2 < 2", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/String/15.5.4.11.js", "Section 7", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/String/15.5.4.11.js", "Section 26", willFixInNextReleaseMessage); - -#ifdef Q_CC_MSVC - addExpectedFailure("ecma_3/Expressions/11.7.3-01.js", "11.7.3 - >>> should evaluate operands in order: order", "QTBUG-8056"); - addExpectedFailure("ecma_3/Operators/order-01.js", "operator evaluation order: 11.7.3 >>>", "QTBUG-8056"); - addExpectedFailure("ecma_3/Operators/order-01.js", "operator evaluation order: 11.13.2 >>>=", "QTBUG-8056"); -#endif - -#ifdef Q_CC_MINGW - addExpectedFailure("ecma/Math/15.8.2.13.js", "Math.pow(NaN,0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.13.js", "Math.pow(NaN,-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.5.js", "Math.atan2(Infinity, Infinity)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.5.js", "Math.atan2(Infinity, -Infinity)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.5.js", "Math.atan2(-Infinity, Infinity)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.5.js", "Math.atan2(-Infinity, -Infinity)", willFixInNextReleaseMessage); -#endif - -#ifdef Q_OS_SOLARIS - addExpectedFailure("ecma/Expressions/11.13.2-2.js", "VAR1 = -0; VAR2= Infinity; VAR2 /= VAR1", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Expressions/11.13.2-2.js", "VAR1 = -0; VAR2= -Infinity; VAR2 /= VAR1", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Expressions/11.13.2-2.js", "VAR1 = 1; VAR2= -0; VAR1 /= VAR2", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Expressions/11.13.2-2.js", "VAR1 = -1; VAR2= -0; VAR1 /= VAR2", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Expressions/11.5.2.js", "Number.POSITIVE_INFINITY / -0", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Expressions/11.5.2.js", "Number.NEGATIVE_INFINITY / -0", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Expressions/11.5.2.js", "1 / -0", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Expressions/11.5.2.js", "-1 / -0", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.10.js", "Math.log(-0.0000001)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.10.js", "Math.log(-1)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.11.js", "Infinity/Math.max(-0,-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.12.js", "Infinity/Math.min(0,-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.12.js", "Infinity/Math.min(-0,-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.13.js", "Math.pow(NaN,0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.13.js", "Math.pow(NaN,-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.13.js", "Infinity/Math.pow(-Infinity, -1)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.13.js", "Math.pow(0, -1)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.13.js", "Math.pow(0, -0.5)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.13.js", "Math.pow(0, -1000)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.13.js", "Infinity/Math.pow(-0, 1)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.13.js", "Infinity/Math.pow(-0, 3)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.13.js", "Math.pow(-0, -2)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.15.js", "Infinity/Math.round(-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.15.js", "Infinity/Math.round(-0.49)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.15.js", "Infinity/Math.round(-0.5)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.17.js", "Infinity/Math.sqrt(-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.18.js", "Infinity/Math.tan(-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.2.js", "Math.acos(1.00000001)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.2.js", "Math.acos(11.00000001)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.3.js", "Math.asin(1.000001)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.3.js", "Math.asin(-1.000001)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.3.js", "Infinity/Math.asin(-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.4.js", "Infinity/Math.atan(-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.5.js", "Math.atan2(0, -0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.5.js", "Infinity/Math.atan2(-0, 1)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.5.js", "Math.atan2(-0,\t-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.5.js", "Math.atan2(-0,\t-1)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.6.js", "Infinity/Math.ceil('-0')", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.6.js", "Infinity/Math.ceil(-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.6.js", "Infinity/Math.ceil(-Number.MIN_VALUE)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.6.js", "Infinity/Math.ceil(-0.9)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.9.js", "Infinity/Math.floor(-0)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/TypeConversion/9.3.1-3.js", "var z = 0; print(1/-z)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/TypeConversion/9.3.1-3.js", "1/-1e-2000", willFixInNextReleaseMessage); -#endif - -#ifdef Q_OS_SYMBIAN - addExpectedFailure("ecma/Math/15.8.2.13.js", "Math.pow(-1, 0.5)", willFixInNextReleaseMessage); - addExpectedFailure("ecma/Math/15.8.2.13.js", "Math.pow(-1, -0.5)", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Operators/order-01.js", "operator evaluation order: 11.5.1 *", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Operators/order-01.js", "operator evaluation order: 11.5.2 /", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Operators/order-01.js", "operator evaluation order: 11.6.2 -", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Operators/order-01.js", "operator evaluation order: 11.13.2 *=", willFixInNextReleaseMessage); - addExpectedFailure("ecma_3/Operators/order-01.js", "operator evaluation order: 11.13.2 /=", willFixInNextReleaseMessage); -#endif - - static const char klass[] = "tst_QScriptJsTestSuite"; - - QVector<uint> *data = qt_meta_data_tst_Suite(); - // content: - *data << 1 // revision - << 0 // classname - << 0 << 0 // classinfo - << 0 << 10 // methods (backpatched later) - << 0 << 0 // properties - << 0 << 0 // enums/sets - ; - - QVector<char> *stringdata = qt_meta_stringdata_tst_Suite(); - appendCString(stringdata, klass); - appendCString(stringdata, ""); - // don't execute any tests on slow machines #if !defined(Q_OS_IRIX) // do all the test suites - QFileInfoList testSuiteDirInfos; - if (testsFound) - testSuiteDirInfos = testsDir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot); + QFileInfoList testSuiteDirInfos = testsDir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot); foreach (QFileInfo tsdi, testSuiteDirInfos) { QDir testSuiteDir(tsdi.absoluteFilePath()); // do all the dirs in the test suite QFileInfoList subSuiteDirInfos = testSuiteDir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot); foreach (QFileInfo ssdi, subSuiteDirInfos) { subSuitePaths.append(ssdi.absoluteFilePath()); - // slot: signature, parameters, type, tag, flags - QString data_slot = QString::fromLatin1("%0/%1_data()") - .arg(testSuiteDir.dirName()).arg(ssdi.fileName()); - static const int nullbyte = sizeof(klass); - *data << stringdata->size() << nullbyte << nullbyte << nullbyte << 0x08; - appendCString(stringdata, data_slot.toLatin1()); - QString slot = QString::fromLatin1("%0/%1()") - .arg(testSuiteDir.dirName()).arg(ssdi.fileName()); - *data << stringdata->size() << nullbyte << nullbyte << nullbyte << 0x08; - appendCString(stringdata, slot.toLatin1()); + QString function = QString::fromLatin1("%0/%1") + .arg(testSuiteDir.dirName()).arg(ssdi.fileName()); + addTestFunction(function, CreateDataFunction); } } #endif - (*data)[4] = subSuitePaths.size() * 2; + finalizeMetaObject(); +} + +tst_QScriptJSTestSuite::~tst_QScriptJSTestSuite() +{ +} - *data << 0; // eod +void tst_QScriptJSTestSuite::configData(TestConfig::Mode mode, const QStringList &parts) +{ + switch (mode) { + case TestConfig::Skip: + addFileExclusion(parts.at(0), parts.value(1)); + break; + + case TestConfig::ExpectFail: + addExpectedFailure(parts.at(0), parts.value(1), parts.value(2)); + break; + } +} - // initialize staticMetaObject - staticMetaObject.d.superdata = &QObject::staticMetaObject; - staticMetaObject.d.stringdata = stringdata->constData(); - staticMetaObject.d.data = data->constData(); - staticMetaObject.d.extradata = 0; +void tst_QScriptJSTestSuite::writeSkipConfigFile(QTextStream &stream) +{ + stream << QString::fromLatin1("# testcase | message") << endl; } -tst_Suite::~tst_Suite() +void tst_QScriptJSTestSuite::writeExpectFailConfigFile(QTextStream &stream) { -#ifdef GENERATE_ADDEXPECTEDFAILURE_CODE - if (!generatedAddExpectedFailureCode.isEmpty()) { - QFile file("addexpectedfailures.cpp"); - file.open(QFile::WriteOnly); - QTextStream ts(&file); - ts << generatedAddExpectedFailureCode; + stream << QString::fromLatin1("# testcase | description | message") << endl; + for (int i = 0; i < expectedFailures.size(); ++i) { + const FailureItem &fail = expectedFailures.at(i); + if (fail.pathRegExp.pattern().isEmpty()) + continue; + stream << QString::fromLatin1("%0 | %1") + .arg(fail.pathRegExp.pattern()) + .arg(escape(fail.description)); + if (!fail.message.isEmpty()) + stream << QString::fromLatin1(" | %0").arg(escape(fail.message)); + stream << endl; } -#endif } -void tst_Suite::addExpectedFailure(const QRegExp &path, const QString &description, const QString &message) +void tst_QScriptJSTestSuite::addExpectedFailure(const QRegExp &path, const QString &description, const QString &message) { expectedFailures.append(FailureItem(FailureItem::ExpectFail, path, description, message)); } -void tst_Suite::addExpectedFailure(const QString &fileName, const QString &description, const QString &message) +void tst_QScriptJSTestSuite::addExpectedFailure(const QString &fileName, const QString &description, const QString &message) { expectedFailures.append(FailureItem(FailureItem::ExpectFail, QRegExp(fileName), description, message)); } -void tst_Suite::addSkip(const QRegExp &path, const QString &description, const QString &message) +void tst_QScriptJSTestSuite::addSkip(const QRegExp &path, const QString &description, const QString &message) { expectedFailures.append(FailureItem(FailureItem::Skip, path, description, message)); } -void tst_Suite::addSkip(const QString &fileName, const QString &description, const QString &message) +void tst_QScriptJSTestSuite::addSkip(const QString &fileName, const QString &description, const QString &message) { expectedFailures.append(FailureItem(FailureItem::Skip, QRegExp(fileName), description, message)); } -bool tst_Suite::isExpectedFailure(const QString &fileName, const QString &description, +bool tst_QScriptJSTestSuite::isExpectedFailure(const QString &fileName, const QString &description, QString *message, FailureItem::Action *action) const { for (int i = 0; i < expectedFailures.size(); ++i) { @@ -857,17 +430,17 @@ bool tst_Suite::isExpectedFailure(const QString &fileName, const QString &descri return false; } -void tst_Suite::addFileExclusion(const QString &fileName, const QString &message) +void tst_QScriptJSTestSuite::addFileExclusion(const QString &fileName, const QString &message) { fileExclusions.append(qMakePair(QRegExp(fileName), message)); } -void tst_Suite::addFileExclusion(const QRegExp &rx, const QString &message) +void tst_QScriptJSTestSuite::addFileExclusion(const QRegExp &rx, const QString &message) { fileExclusions.append(qMakePair(rx, message)); } -bool tst_Suite::isExcludedFile(const QString &fileName, QString *message) const +bool tst_QScriptJSTestSuite::isExcludedFile(const QString &fileName, QString *message) const { for (int i = 0; i < fileExclusions.size(); ++i) { if (fileExclusions.at(i).first.indexIn(fileName) != -1) { @@ -879,4 +452,4 @@ bool tst_Suite::isExcludedFile(const QString &fileName, QString *message) const return false; } -QTEST_MAIN(tst_Suite) +QTEST_MAIN(tst_QScriptJSTestSuite) diff --git a/tests/auto/qscriptv8testsuite/abstracttestsuite.cpp b/tests/auto/qscriptv8testsuite/abstracttestsuite.cpp new file mode 100644 index 0000000..d47eb24 --- /dev/null +++ b/tests/auto/qscriptv8testsuite/abstracttestsuite.cpp @@ -0,0 +1,481 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "abstracttestsuite.h" +#include <QtTest/QtTest> +#include <QtCore/qset.h> +#include <QtCore/qtextstream.h> + +/*! + AbstractTestSuite provides a way of building QtTest test objects + dynamically. The use case is integration of JavaScript test suites + into QtTest autotests. + + Subclasses add their tests functions with addTestFunction() in the + constructor, and must reimplement runTestFunction(). Additionally, + subclasses can reimplement initTestCase() and cleanupTestCase() + (but make sure to call the base implementation). + + AbstractTestSuite uses configuration files for getting information + about skipped tests (skip.txt) and expected test failures + (expect_fail.txt). Subclasses must reimplement + createSkipConfigFile() and createExpectFailConfigFile() for + creating these files, and configData() for processing an entry of + such a file. + + The config file format is as follows: + - Lines starting with '#' are skipped. + - Lines of the form [SYMBOL] means that the upcoming data + should only be processed if the given SYMBOL is defined on + this platform. + - Any other line is split on ' | ' and handed off to the client. + + Subclasses must provide a default tests directory (where the + subclass expects to find the script files to run as tests), and a + default config file directory. Some environment variables can be + used to affect where AbstractTestSuite will look for files: + + - QTSCRIPT_TEST_CONFIG_DIR: Overrides the default test config path. + + - QTSCRIPT_TEST_CONFIG_SUFFIX: Is appended to "skip" and + "expect_fail" to create the test config name. This makes it easy to + maintain skip- and expect_fail-files corresponding to different + revisions of a test suite, and switch between them. + + - QTSCRIPT_TEST_DIR: Overrides the default test dir. + + AbstractTestSuite does _not_ define how the test dir itself is + processed or how tests are run; this is left up to the subclass. + + If no config files are found, AbstractTestSuite will ask the + subclass to create a default skip file. Also, the + shouldGenerateExpectedFailures variable will be set to true. The + subclass should check for this when a test fails, and add an entry + to its set of expected failures. When all tests have been run, + AbstractTestSuite will ask the subclass to create the expect_fail + file based on the tests that failed. The next time the autotest is + run, the created config files will be used. + + The reason for skipping a test is usually that it takes a very long + time to complete (or even hangs completely), or it crashes. It's + not possible for the test runner to know in advance which tests are + problematic, which is why the entries to the skip file are + typically added manually. When running tests for the first time, it + can be useful to run the autotest with the -v1 command line option, + so you can see the name of each test before it's run, and can add a + skip entry if appropriate. +*/ + +// Helper class for constructing the test class's QMetaObject contents +// at runtime. +class TestMetaObjectBuilder +{ +public: + TestMetaObjectBuilder(const QByteArray &className, + const QMetaObject *superClass); + + void appendPrivateVoidSlot(const char *signature); + void appendPrivateVoidSlot(const QString &signature) + { appendPrivateVoidSlot(signature.toLatin1().constData()); } + + void assignContents(QMetaObject &); + +private: + void appendString(const char *); + void finalize(); + + const QByteArray m_className; + const QMetaObject *m_superClass; + QVector<uint> m_data; + QVector<char> m_stringdata; + int m_emptyStringOffset; + bool m_finalized; +}; + +TestMetaObjectBuilder::TestMetaObjectBuilder( + const QByteArray &className, + const QMetaObject *superClass) + : m_className(className), m_superClass(superClass), + m_finalized(false) +{ + // header + m_data << 1 // revision + << 0 // classname + << 0 << 0 // classinfo + << 0 << 10 // methods (backpatched later) + << 0 << 0 // properties + << 0 << 0 // enums/sets + ; + + appendString(className.constData()); + m_emptyStringOffset = m_stringdata.size(); + appendString(""); +} + +void TestMetaObjectBuilder::appendString(const char *s) +{ + char c; + do { + c = *(s++); + m_stringdata << c; + } while (c != '\0'); +} + +void TestMetaObjectBuilder::appendPrivateVoidSlot(const char *signature) +{ + static const int methodCountOffset = 4; + // signature, parameters, type, tag, flags + m_data << m_stringdata.size() + << m_emptyStringOffset + << m_emptyStringOffset + << m_emptyStringOffset + << 0x08; + appendString(signature); + ++m_data[methodCountOffset]; +} + +void TestMetaObjectBuilder::finalize() +{ + if (m_finalized) + return; + m_data << 0; // eod + m_finalized = true; +} + +/** + Assigns this builder's contents to the meta-object \a mo. It's up + to the caller to ensure that this builder (and hence, its data) + stays alive as long as needed. +*/ +void TestMetaObjectBuilder::assignContents(QMetaObject &mo) +{ + finalize(); + mo.d.superdata = m_superClass; + mo.d.stringdata = m_stringdata.constData(); + mo.d.data = m_data.constData(); + mo.d.extradata = 0; +} + + +class TestConfigClientInterface; +// For parsing information about skipped tests and expected failures. +class TestConfigParser +{ +public: + static void parse(const QString &path, + TestConfig::Mode mode, + TestConfigClientInterface *client); + +private: + static QString unescape(const QString &); + static bool isKnownSymbol(const QString &); + static bool isDefined(const QString &); + + static QSet<QString> knownSymbols; + static QSet<QString> definedSymbols; +}; + +QSet<QString> TestConfigParser::knownSymbols; +QSet<QString> TestConfigParser::definedSymbols; + +/** + Parses the config file at the given \a path in the given \a mode. + Handling of errors and data is delegated to the given \a client. +*/ +void TestConfigParser::parse(const QString &path, + TestConfig::Mode mode, + TestConfigClientInterface *client) +{ + QFile file(path); + if (!file.open(QIODevice::ReadOnly)) + return; + QTextStream stream(&file); + int lineNumber = 0; + QString predicate; + const QString separator = QString::fromLatin1(" | "); + while (!stream.atEnd()) { + ++lineNumber; + QString line = stream.readLine(); + if (line.isEmpty()) + continue; + if (line.startsWith('#')) // Comment + continue; + if (line.startsWith('[')) { // Predicate + if (!line.endsWith(']')) { + client->configError(path, "malformed predicate", lineNumber); + return; + } + QString symbol = line.mid(1, line.size()-2); + if (isKnownSymbol(symbol)) { + predicate = symbol; + } else { + qWarning("symbol %s is not known -- add it to TestConfigParser!", qPrintable(symbol)); + predicate = QString(); + } + } else { + if (predicate.isEmpty() || isDefined(predicate)) { + QStringList parts = line.split(separator, QString::KeepEmptyParts); + for (int i = 0; i < parts.size(); ++i) + parts[i] = unescape(parts[i]); + client->configData(mode, parts); + } + } + } +} + +QString TestConfigParser::unescape(const QString &str) +{ + return QString(str).replace("\\n", "\n"); +} + +bool TestConfigParser::isKnownSymbol(const QString &symbol) +{ + if (knownSymbols.isEmpty()) { + knownSymbols + // If you add a symbol here, add a case for it in + // isDefined() as well. + << "Q_OS_LINUX" + << "Q_OS_SOLARIS" + << "Q_OS_WINCE" + << "Q_OS_SYMBIAN" + << "Q_CC_MSVC" + << "Q_CC_MINGW" + ; + } + return knownSymbols.contains(symbol); +} + +bool TestConfigParser::isDefined(const QString &symbol) +{ + if (definedSymbols.isEmpty()) { + definedSymbols +#ifdef Q_OS_LINUX + << "Q_OS_LINUX" +#endif +#ifdef Q_OS_SOLARIS + << "Q_OS_SOLARIS" +#endif +#ifdef Q_OS_WINCE + << "Q_OS_WINCE" +#endif +#ifdef Q_OS_SYMBIAN + << "Q_OS_SYMBIAN" +#endif +#ifdef Q_CC_MSVC + << "Q_CC_MSVC" +#endif +#ifdef Q_CC_MINGW + << "Q_CC_MINGW" +#endif + ; + } + return definedSymbols.contains(symbol); +} + + +QMetaObject AbstractTestSuite::staticMetaObject; + +const QMetaObject *AbstractTestSuite::metaObject() const +{ + return &staticMetaObject; +} + +void *AbstractTestSuite::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, staticMetaObject.d.stringdata)) + return static_cast<void*>(const_cast<AbstractTestSuite*>(this)); + return QObject::qt_metacast(_clname); +} + +int AbstractTestSuite::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: + initTestCase(); + break; + case 1: + cleanupTestCase(); + break; + default: + // If another method is added above, this offset must be adjusted. + runTestFunction(_id - 2); + } + _id -= staticMetaObject.methodCount() - staticMetaObject.methodOffset(); + } + return _id; +} + +AbstractTestSuite::AbstractTestSuite(const QByteArray &className, + const QString &defaultTestsPath, + const QString &defaultConfigPath) + : shouldGenerateExpectedFailures(false), + metaBuilder(new TestMetaObjectBuilder(className, &QObject::staticMetaObject)) +{ + QString testConfigPath = qgetenv("QTSCRIPT_TEST_CONFIG_DIR"); + if (testConfigPath.isEmpty()) + testConfigPath = defaultConfigPath; + QString configSuffix = qgetenv("QTSCRIPT_TEST_CONFIG_SUFFIX"); + skipConfigPath = QString::fromLatin1("%0/skip%1.txt") + .arg(testConfigPath).arg(configSuffix); + expectFailConfigPath = QString::fromLatin1("%0/expect_fail%1.txt") + .arg(testConfigPath).arg(configSuffix); + + QString testsPath = qgetenv("QTSCRIPT_TEST_DIR"); + if (testsPath.isEmpty()) + testsPath = defaultTestsPath; + testsDir = QDir(testsPath); + + addTestFunction("initTestCase"); + addTestFunction("cleanupTestCase"); + + // Subclass constructors should add their custom test functions to + // the meta-object and call finalizeMetaObject(). +} + +AbstractTestSuite::~AbstractTestSuite() +{ + delete metaBuilder; +} + +void AbstractTestSuite::addTestFunction(const QString &name, + DataFunctionCreation dfc) +{ + if (dfc == CreateDataFunction) { + QString dataSignature = QString::fromLatin1("%0_data()").arg(name); + metaBuilder->appendPrivateVoidSlot(dataSignature); + } + QString signature = QString::fromLatin1("%0()").arg(name); + metaBuilder->appendPrivateVoidSlot(signature); +} + +void AbstractTestSuite::finalizeMetaObject() +{ + metaBuilder->assignContents(staticMetaObject); +} + +void AbstractTestSuite::initTestCase() +{ + if (!testsDir.exists()) { + QString message = QString::fromLatin1("tests directory (%0) doesn't exist.") + .arg(testsDir.path()); + QFAIL(qPrintable(message)); + return; + } + + if (QFileInfo(skipConfigPath).exists()) + TestConfigParser::parse(skipConfigPath, TestConfig::Skip, this); + else + createSkipConfigFile(); + + if (QFileInfo(expectFailConfigPath).exists()) + TestConfigParser::parse(expectFailConfigPath, TestConfig::ExpectFail, this); + else + shouldGenerateExpectedFailures = true; +} + +void AbstractTestSuite::cleanupTestCase() +{ + if (shouldGenerateExpectedFailures) + createExpectFailConfigFile(); +} + +void AbstractTestSuite::configError(const QString &path, const QString &message, int lineNumber) +{ + QString output; + output.append(path); + if (lineNumber != -1) + output.append(":").append(QString::number(lineNumber)); + output.append(": ").append(message); + QFAIL(qPrintable(output)); +} + +void AbstractTestSuite::createSkipConfigFile() +{ + QFile file(skipConfigPath); + if (!file.open(QIODevice::WriteOnly)) + return; + QWARN(qPrintable(QString::fromLatin1("creating %0").arg(skipConfigPath))); + QTextStream stream(&file); + + writeSkipConfigFile(stream); + + file.close(); +} + +void AbstractTestSuite::createExpectFailConfigFile() +{ + QFile file(expectFailConfigPath); + if (!file.open(QFile::WriteOnly)) + return; + QWARN(qPrintable(QString::fromLatin1("creating %0").arg(expectFailConfigPath))); + QTextStream stream(&file); + + writeExpectFailConfigFile(stream); + + file.close(); +} + +/*! + Convenience function for reading all contents of a file. + */ +QString AbstractTestSuite::readFile(const QString &filename) +{ + QFile file(filename); + if (!file.open(QFile::ReadOnly)) + return QString(); + QTextStream stream(&file); + stream.setCodec("UTF-8"); + return stream.readAll(); +} + +/*! + Escapes characters in the string \a str so it's suitable for writing + to a config file. + */ +QString AbstractTestSuite::escape(const QString &str) +{ + return QString(str).replace("\n", "\\n"); +} diff --git a/tests/auto/qscriptv8testsuite/abstracttestsuite.h b/tests/auto/qscriptv8testsuite/abstracttestsuite.h new file mode 100644 index 0000000..b13c61a --- /dev/null +++ b/tests/auto/qscriptv8testsuite/abstracttestsuite.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ABSTRACTTESTSUITE_H +#define ABSTRACTTESTSUITE_H + +#include <QtCore/qobject.h> + +#include <QtCore/qbytearray.h> +#include <QtCore/qdir.h> +#include <QtCore/qstring.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qvector.h> +#include <QtCore/qtextstream.h> + +class TestMetaObjectBuilder; + +namespace TestConfig { +enum Mode { + Skip, + ExpectFail +}; +} + +// For receiving callbacks from the config parser. +class TestConfigClientInterface +{ +public: + virtual ~TestConfigClientInterface() {} + virtual void configData(TestConfig::Mode mode, + const QStringList &parts) = 0; + virtual void configError(const QString &path, + const QString &message, + int lineNumber) = 0; +}; + +class AbstractTestSuite : public QObject, + public TestConfigClientInterface +{ +// No Q_OBJECT macro, we implement the meta-object ourselves. +public: + AbstractTestSuite(const QByteArray &className, + const QString &defaultTestsPath, + const QString &defaultConfigPath); + virtual ~AbstractTestSuite(); + + static QMetaObject staticMetaObject; + virtual const QMetaObject *metaObject() const; + virtual void *qt_metacast(const char *); + virtual int qt_metacall(QMetaObject::Call, int, void **argv); + + static QString readFile(const QString &); + static QString escape(const QString &); + +protected: + enum DataFunctionCreation { + DontCreateDataFunction, + CreateDataFunction + }; + + void addTestFunction(const QString &, + DataFunctionCreation = DontCreateDataFunction); + void finalizeMetaObject(); + + virtual void initTestCase(); + virtual void cleanupTestCase(); + + virtual void writeSkipConfigFile(QTextStream &) = 0; + virtual void writeExpectFailConfigFile(QTextStream &) = 0; + + virtual void runTestFunction(int index) = 0; + + virtual void configError(const QString &path, const QString &message, int lineNumber); + + QDir testsDir; + bool shouldGenerateExpectedFailures; + +private: + TestMetaObjectBuilder *metaBuilder; + QString skipConfigPath, expectFailConfigPath; + +private: + void createSkipConfigFile(); + void createExpectFailConfigFile(); +}; + +#endif diff --git a/tests/auto/qscriptv8testsuite/abstracttestsuite.pri b/tests/auto/qscriptv8testsuite/abstracttestsuite.pri new file mode 100644 index 0000000..1de5b93 --- /dev/null +++ b/tests/auto/qscriptv8testsuite/abstracttestsuite.pri @@ -0,0 +1,4 @@ +SOURCES += $$PWD/abstracttestsuite.cpp +HEADERS += $$PWD/abstracttestsuite.h +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD diff --git a/tests/auto/qscriptv8testsuite/expect_fail.txt b/tests/auto/qscriptv8testsuite/expect_fail.txt new file mode 100644 index 0000000..a4eee73 --- /dev/null +++ b/tests/auto/qscriptv8testsuite/expect_fail.txt @@ -0,0 +1,16 @@ +# testcase | actual | expected | message +arguments-enum | 2 | 0 +const-redecl | undefined | TypeError | local:'const x; var x' +date-parse | NaN | 946713600000 | Sat, 01-Jan-2000 08:00:00 GMT+00:00 +delete-global-properties | true | false +delete | false | true | delete 100 +function-arguments-null | false | true +function-caller | null | function eval() {\n [native code]\n} +function-prototype | prototype | disconnectconnect +global-const-var-conflicts | false | true +number-tostring | 0 | 0.0000a7c5ac471b4788 +parse-int-float | 1e+21 | 1 +regexp | false | true +string-lastindexof | 0 | -1 +string-split | 4 | 3 | 19 - array length +substr | abcdefghijklmn | diff --git a/tests/auto/qscriptv8testsuite/qscriptv8testsuite.pro b/tests/auto/qscriptv8testsuite/qscriptv8testsuite.pro index 00e2e01..e1c6234 100644 --- a/tests/auto/qscriptv8testsuite/qscriptv8testsuite.pro +++ b/tests/auto/qscriptv8testsuite/qscriptv8testsuite.pro @@ -2,3 +2,4 @@ load(qttest_p4) QT = core script SOURCES += tst_qscriptv8testsuite.cpp RESOURCES += qscriptv8testsuite.qrc +include(abstracttestsuite.pri) diff --git a/tests/auto/qscriptv8testsuite/qscriptv8testsuite.qrc b/tests/auto/qscriptv8testsuite/qscriptv8testsuite.qrc index a894ee5..150ccf0 100644 --- a/tests/auto/qscriptv8testsuite/qscriptv8testsuite.qrc +++ b/tests/auto/qscriptv8testsuite/qscriptv8testsuite.qrc @@ -1,5 +1,7 @@ <!DOCTYPE RCC><RCC version="1.0"> <qresource> <file>tests</file> + <file>expect_fail.txt</file> + <file>skip.txt</file> </qresource> </RCC> diff --git a/tests/auto/qscriptv8testsuite/skip.txt b/tests/auto/qscriptv8testsuite/skip.txt new file mode 100644 index 0000000..3c2cc53 --- /dev/null +++ b/tests/auto/qscriptv8testsuite/skip.txt @@ -0,0 +1,17 @@ +# testcase | message +debug-* | not applicable +mirror-* | not applicable +array-concat | Hangs on JSC backend +array-splice | Hangs on JSC backend +sparse-array-reverse | Hangs on JSC backend +string-case | V8-specific behavior? (Doesn't pass on SpiderMonkey either) + +[Q_OS_WINCE] +deep-recursion | Demands too much memory on WinCE +nested-repetition-count-overflow | Demands too much memory on WinCE +unicode-test | Demands too much memory on WinCE +mul-exhaustive | Demands too much memory on WinCE + +[Q_OS_SYMBIAN] +nested-repetition-count-overflow | Demands too much memory on Symbian +unicode-test | Demands too much memory on Symbian diff --git a/tests/auto/qscriptv8testsuite/tst_qscriptv8testsuite.cpp b/tests/auto/qscriptv8testsuite/tst_qscriptv8testsuite.cpp index 7d0858e..b35fd06 100644 --- a/tests/auto/qscriptv8testsuite/tst_qscriptv8testsuite.cpp +++ b/tests/auto/qscriptv8testsuite/tst_qscriptv8testsuite.cpp @@ -40,68 +40,33 @@ ****************************************************************************/ +#include "abstracttestsuite.h" #include <QtTest/QtTest> -#include <QByteArray> - #include <QtScript> //TESTED_CLASS= //TESTED_FILES= -// Uncomment the following define to have the autotest generate -// addExpectedFailure() code for all the tests that fail. -// This is useful when a whole new test (sub)suite is added. -// The code is stored in addexpectedfailures.cpp. -// Paste the contents into this file after the existing -// addExpectedFailure() calls. - -//#define GENERATE_ADDEXPECTEDFAILURE_CODE - -static QString readFile(const QString &filename) -{ - QFile file(filename); - if (!file.open(QFile::ReadOnly)) - return QString(); - QTextStream stream(&file); - stream.setCodec("UTF-8"); - return stream.readAll(); -} - -static void appendCString(QVector<char> *v, const char *s) -{ - char c; - do { - c = *(s++); - *v << c; - } while (c != '\0'); -} - -struct ExpectedFailure +class tst_QScriptV8TestSuite : public AbstractTestSuite { - ExpectedFailure(const QString &name, const QString &act, - const QString &exp, const QString &msg) - : testName(name), actual(act), expected(exp), message(msg) - { } - - QString testName; - QString actual; - QString expected; - QString message; -}; - -class tst_Suite : public QObject -{ - public: - tst_Suite(); - virtual ~tst_Suite(); + tst_QScriptV8TestSuite(); + virtual ~tst_QScriptV8TestSuite(); + +protected: + struct ExpectedFailure + { + ExpectedFailure(const QString &name, const QString &act, + const QString &exp, const QString &msg) + : testName(name), actual(act), expected(exp), message(msg) + { } + + QString testName; + QString actual; + QString expected; + QString message; + }; - static QMetaObject staticMetaObject; - virtual const QMetaObject *metaObject() const; - virtual void *qt_metacast(const char *); - virtual int qt_metacall(QMetaObject::Call, int, void **argv); - -private: void addExpectedFailure(const QString &testName, const QString &actual, const QString &expected, const QString &message); bool isExpectedFailure(const QString &testName, const QString &actual, @@ -110,34 +75,23 @@ private: void addTestExclusion(const QRegExp &rx, const QString &message); bool isExcludedTest(const QString &testName, QString *message) const; - QDir testsDir; + virtual void initTestCase(); + virtual void configData(TestConfig::Mode mode, const QStringList &parts); + virtual void writeSkipConfigFile(QTextStream &); + virtual void writeExpectFailConfigFile(QTextStream &); + virtual void runTestFunction(int testIndex); + QStringList testNames; QList<ExpectedFailure> expectedFailures; QList<QPair<QRegExp, QString> > testExclusions; QString mjsunitContents; -#ifdef GENERATE_ADDEXPECTEDFAILURE_CODE - QString generatedAddExpectedFailureCode; -#endif }; -QMetaObject tst_Suite::staticMetaObject; - -Q_GLOBAL_STATIC(QVector<uint>, qt_meta_data_tst_Suite) -Q_GLOBAL_STATIC(QVector<char>, qt_meta_stringdata_tst_Suite) - -const QMetaObject *tst_Suite::metaObject() const -{ - return &staticMetaObject; -} - -void *tst_Suite::qt_metacast(const char *_clname) -{ - if (!_clname) return 0; - if (!strcmp(_clname, qt_meta_stringdata_tst_Suite()->constData())) - return static_cast<void*>(const_cast<tst_Suite*>(this)); - return QObject::qt_metacast(_clname); -} - +// We expect failing tests to call the fail() function (defined in +// mjsunit.js) with arguments expected, actual, message_opt. This +// function intercepts the call, calls the real fail() function (which +// will throw an exception), and sets the original arguments on the +// exception object so that we can process them later. static QScriptValue qscript_fail(QScriptContext *ctx, QScriptEngine *eng) { QScriptValue realFail = ctx->callee().data(); @@ -146,193 +100,141 @@ static QScriptValue qscript_fail(QScriptContext *ctx, QScriptEngine *eng) Q_ASSERT(eng->hasUncaughtException()); ret.setProperty("expected", ctx->argument(0)); ret.setProperty("actual", ctx->argument(1)); + ret.setProperty("message", ctx->argument(2)); QScriptContextInfo info(ctx->parentContext()->parentContext()); ret.setProperty("lineNumber", info.lineNumber()); return ret; } -int tst_Suite::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +void tst_QScriptV8TestSuite::writeSkipConfigFile(QTextStream &stream) { - _id = QObject::qt_metacall(_c, _id, _a); - if (_id < 0) - return _id; - if (_c == QMetaObject::InvokeMetaMethod) { - QString name = testNames.at(_id); - QString path = testsDir.absoluteFilePath(name + ".js"); - QString excludeMessage; - if (isExcludedTest(name, &excludeMessage)) { - QTest::qSkip(excludeMessage.toLatin1(), QTest::SkipAll, path.toLatin1(), -1); - } else { - QScriptEngine engine; - engine.evaluate(mjsunitContents).toString(); - if (engine.hasUncaughtException()) { - QStringList bt = engine.uncaughtExceptionBacktrace(); - QString err = engine.uncaughtException().toString(); - qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n"))); - } else { - QScriptValue fakeFail = engine.newFunction(qscript_fail); - fakeFail.setData(engine.globalObject().property("fail")); - engine.globalObject().setProperty("fail", fakeFail); - QString contents = readFile(path); - QScriptValue ret = engine.evaluate(contents); - if (engine.hasUncaughtException()) { - if (!ret.isError()) { - Q_ASSERT(ret.instanceOf(engine.globalObject().property("MjsUnitAssertionError"))); - QString actual = ret.property("actual").toString(); - QString expected = ret.property("expected").toString(); - int lineNumber = ret.property("lineNumber").toInt32(); - QString failMessage; - if (isExpectedFailure(name, actual, expected, &failMessage)) { - QTest::qExpectFail("", failMessage.toLatin1(), - QTest::Continue, path.toLatin1(), - lineNumber); - } -#ifdef GENERATE_ADDEXPECTEDFAILURE_CODE - else { - generatedAddExpectedFailureCode.append( - " addExpectedFailure(\"" + name - + "\", \"" + actual + "\", \"" + expected - + "\", willFixInNextReleaseMessage);\n"); - } -#endif - QTest::qCompare(actual, expected, "actual", "expect", - path.toLatin1(), lineNumber); - } else { - int lineNumber = ret.property("lineNumber").toInt32(); - QTest::qExpectFail("", ret.toString().toLatin1(), - QTest::Continue, path.toLatin1(), lineNumber); - QTest::qVerify(false, ret.toString().toLatin1(), "", path.toLatin1(), lineNumber); - } - } - } - } - _id -= testNames.size(); - } - return _id; + stream << QString::fromLatin1("# testcase | message") << endl; } -tst_Suite::tst_Suite() +void tst_QScriptV8TestSuite::writeExpectFailConfigFile(QTextStream &stream) { - testsDir = QDir(":/tests"); - if (!testsDir.exists()) { - qWarning("*** no tests/ dir!"); - } else { - if (!testsDir.exists("mjsunit.js")) - qWarning("*** no tests/mjsunit.js file!"); - else { - mjsunitContents = readFile(testsDir.absoluteFilePath("mjsunit.js")); - if (mjsunitContents.isEmpty()) - qWarning("*** tests/mjsunit.js is empty!"); - } + stream << QString::fromLatin1("# testcase | actual | expected | message") << endl; + for (int i = 0; i < expectedFailures.size(); ++i) { + const ExpectedFailure &fail = expectedFailures.at(i); + stream << QString::fromLatin1("%0 | %1 | %2") + .arg(fail.testName) + .arg(escape(fail.actual)) + .arg(escape(fail.expected)); + if (!fail.message.isEmpty()) + stream << QString::fromLatin1(" | %0").arg(escape(fail.message)); + stream << endl; } - QString willFixInNextReleaseMessage = QString::fromLatin1("Will fix in next release"); - addExpectedFailure("arguments-enum", "2", "0", willFixInNextReleaseMessage); - addExpectedFailure("const-redecl", "undefined", "TypeError", willFixInNextReleaseMessage); - addExpectedFailure("global-const-var-conflicts", "false", "true", willFixInNextReleaseMessage); - addExpectedFailure("string-lastindexof", "0", "-1", "test is wrong?"); - -#ifndef Q_OS_LINUX - addExpectedFailure("to-precision", "1.235e+27", "1.234e+27", "QTBUG-8053: toPrecision(4) gives wrong result on Mac"); -#endif - -#ifdef Q_OS_SOLARIS - addExpectedFailure("math-min-max", "Infinity", "-Infinity", willFixInNextReleaseMessage); - addExpectedFailure("negate-zero", "false", "true", willFixInNextReleaseMessage); - addExpectedFailure("str-to-num", "Infinity", "-Infinity", willFixInNextReleaseMessage); -#endif - - addTestExclusion("debug-*", "not applicable"); - addTestExclusion("mirror-*", "not applicable"); - - addTestExclusion("array-concat", "Hangs on JSC backend"); - addTestExclusion("array-splice", "Hangs on JSC backend"); - addTestExclusion("sparse-array-reverse", "Hangs on JSC backend"); - - addTestExclusion("string-case", "V8-specific behavior? (Doesn't pass on SpiderMonkey either)"); - -#ifdef Q_OS_WINCE - addTestExclusion("deep-recursion", "Demands too much memory on WinCE"); - addTestExclusion("nested-repetition-count-overflow", "Demands too much memory on WinCE"); - addTestExclusion("unicode-test", "Demands too much memory on WinCE"); - addTestExclusion("mul-exhaustive", "Demands too much memory on WinCE"); -#endif - -#ifdef Q_OS_SYMBIAN - addTestExclusion("nested-repetition-count-overflow", "Demands too much memory on Symbian"); - addTestExclusion("unicode-test", "Demands too much memory on Symbian"); -#endif - // Failures due to switch to JSC as back-end - addExpectedFailure("date-parse", "NaN", "946713600000", willFixInNextReleaseMessage); - addExpectedFailure("delete-global-properties", "true", "false", willFixInNextReleaseMessage); - addExpectedFailure("delete", "false", "true", willFixInNextReleaseMessage); - addExpectedFailure("function-arguments-null", "false", "true", willFixInNextReleaseMessage); - addExpectedFailure("function-caller", "null", "function eval() {\n [native code]\n}", willFixInNextReleaseMessage); - addExpectedFailure("function-prototype", "prototype", "disconnectconnect", willFixInNextReleaseMessage); - addExpectedFailure("number-tostring", "0", "0.0000a7c5ac471b4788", willFixInNextReleaseMessage); - addExpectedFailure("parse-int-float", "1e+21", "1", willFixInNextReleaseMessage); - addExpectedFailure("regexp", "false", "true", willFixInNextReleaseMessage); - addExpectedFailure("smi-negative-zero", "-Infinity", "Infinity", willFixInNextReleaseMessage); - addExpectedFailure("string-split", "4", "3", willFixInNextReleaseMessage); - addExpectedFailure("substr", "abcdefghijklmn", "", willFixInNextReleaseMessage); +} - static const char klass[] = "tst_QScriptV8TestSuite"; +void tst_QScriptV8TestSuite::runTestFunction(int testIndex) +{ + QString name = testNames.at(testIndex); + QString path = testsDir.absoluteFilePath(name + ".js"); - QVector<uint> *data = qt_meta_data_tst_Suite(); - // content: - *data << 1 // revision - << 0 // classname - << 0 << 0 // classinfo - << 0 << 10 // methods (backpatched later) - << 0 << 0 // properties - << 0 << 0 // enums/sets - ; + QString excludeMessage; + if (isExcludedTest(name, &excludeMessage)) { + QTest::qSkip(excludeMessage.toLatin1(), QTest::SkipAll, path.toLatin1(), -1); + return; + } - QVector<char> *stringdata = qt_meta_stringdata_tst_Suite(); - appendCString(stringdata, klass); - appendCString(stringdata, ""); + QScriptEngine engine; + engine.evaluate(mjsunitContents); + if (engine.hasUncaughtException()) { + QStringList bt = engine.uncaughtExceptionBacktrace(); + QString err = engine.uncaughtException().toString(); + qWarning("%s\n%s", qPrintable(err), qPrintable(bt.join("\n"))); + } else { + // Prepare to intercept calls to mjsunit's fail() function. + QScriptValue fakeFail = engine.newFunction(qscript_fail); + fakeFail.setData(engine.globalObject().property("fail")); + engine.globalObject().setProperty("fail", fakeFail); + + QString contents = readFile(path); + QScriptValue ret = engine.evaluate(contents); + if (engine.hasUncaughtException()) { + if (!ret.isError()) { + Q_ASSERT(ret.instanceOf(engine.globalObject().property("MjsUnitAssertionError"))); + QString actual = ret.property("actual").toString(); + QString expected = ret.property("expected").toString(); + int lineNumber = ret.property("lineNumber").toInt32(); + QString failMessage; + if (shouldGenerateExpectedFailures) { + if (ret.property("message").isString()) + failMessage = ret.property("message").toString(); + addExpectedFailure(name, actual, expected, failMessage); + } else if (isExpectedFailure(name, actual, expected, &failMessage)) { + QTest::qExpectFail("", failMessage.toLatin1(), + QTest::Continue, path.toLatin1(), + lineNumber); + } + QTest::qCompare(actual, expected, "actual", "expect", + path.toLatin1(), lineNumber); + } else { + int lineNumber = ret.property("lineNumber").toInt32(); + QTest::qExpectFail("", ret.toString().toLatin1(), + QTest::Continue, path.toLatin1(), lineNumber); + QTest::qVerify(false, ret.toString().toLatin1(), "", path.toLatin1(), lineNumber); + } + } + } +} +tst_QScriptV8TestSuite::tst_QScriptV8TestSuite() + : AbstractTestSuite("tst_QScriptV8TestSuite", + ":/tests", ":/") +{ + // One test function per test file. QFileInfoList testFileInfos; testFileInfos = testsDir.entryInfoList(QStringList() << "*.js", QDir::Files); foreach (QFileInfo tfi, testFileInfos) { QString name = tfi.baseName(); - // slot: signature, parameters, type, tag, flags - QString slot = QString::fromLatin1("%0()").arg(name); - static const int nullbyte = sizeof(klass); - *data << stringdata->size() << nullbyte << nullbyte << nullbyte << 0x08; - appendCString(stringdata, slot.toLatin1()); + addTestFunction(name); testNames.append(name); } - (*data)[4] = testFileInfos.size(); + finalizeMetaObject(); +} - *data << 0; // eod +tst_QScriptV8TestSuite::~tst_QScriptV8TestSuite() +{ +} - // initialize staticMetaObject - staticMetaObject.d.superdata = &QObject::staticMetaObject; - staticMetaObject.d.stringdata = stringdata->constData(); - staticMetaObject.d.data = data->constData(); - staticMetaObject.d.extradata = 0; +void tst_QScriptV8TestSuite::initTestCase() +{ + AbstractTestSuite::initTestCase(); + + // FIXME: These warnings should be QFAIL, but that would make the + // test fail right now. + if (!testsDir.exists("mjsunit.js")) + qWarning("*** no tests/mjsunit.js file!"); + else { + mjsunitContents = readFile(testsDir.absoluteFilePath("mjsunit.js")); + if (mjsunitContents.isEmpty()) + qWarning("*** tests/mjsunit.js is empty!"); + } } -tst_Suite::~tst_Suite() +void tst_QScriptV8TestSuite::configData(TestConfig::Mode mode, const QStringList &parts) { -#ifdef GENERATE_ADDEXPECTEDFAILURE_CODE - if (!generatedAddExpectedFailureCode.isEmpty()) { - QFile file("addexpectedfailures.cpp"); - file.open(QFile::WriteOnly); - QTextStream ts(&file); - ts << generatedAddExpectedFailureCode; + switch (mode) { + case TestConfig::Skip: + addTestExclusion(parts.at(0), parts.value(1)); + break; + + case TestConfig::ExpectFail: + addExpectedFailure(parts.at(0), parts.value(1), + parts.value(2), parts.value(3)); + break; } -#endif } -void tst_Suite::addExpectedFailure(const QString &testName, const QString &actual, +void tst_QScriptV8TestSuite::addExpectedFailure(const QString &testName, const QString &actual, const QString &expected, const QString &message) { expectedFailures.append(ExpectedFailure(testName, actual, expected, message)); } -bool tst_Suite::isExpectedFailure(const QString &testName, const QString &actual, +bool tst_QScriptV8TestSuite::isExpectedFailure(const QString &testName, const QString &actual, const QString &expected, QString *message) const { for (int i = 0; i < expectedFailures.size(); ++i) { @@ -346,17 +248,17 @@ bool tst_Suite::isExpectedFailure(const QString &testName, const QString &actual return false; } -void tst_Suite::addTestExclusion(const QString &testName, const QString &message) +void tst_QScriptV8TestSuite::addTestExclusion(const QString &testName, const QString &message) { testExclusions.append(qMakePair(QRegExp(testName), message)); } -void tst_Suite::addTestExclusion(const QRegExp &rx, const QString &message) +void tst_QScriptV8TestSuite::addTestExclusion(const QRegExp &rx, const QString &message) { testExclusions.append(qMakePair(rx, message)); } -bool tst_Suite::isExcludedTest(const QString &testName, QString *message) const +bool tst_QScriptV8TestSuite::isExcludedTest(const QString &testName, QString *message) const { for (int i = 0; i < testExclusions.size(); ++i) { if (testExclusions.at(i).first.indexIn(testName) != -1) { @@ -368,4 +270,4 @@ bool tst_Suite::isExcludedTest(const QString &testName, QString *message) const return false; } -QTEST_MAIN(tst_Suite) +QTEST_MAIN(tst_QScriptV8TestSuite) diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp index 9014241..6686e2d 100644 --- a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp +++ b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp @@ -2328,8 +2328,7 @@ void tst_QScriptValue::getSetPrototype_invalidPrototype() inv.setPrototype(object); QCOMPARE(inv.prototype().isValid(), false); object.setPrototype(inv); - // FIXME should it be invalid or proto? - QVERIFY(object.prototype().strictlyEquals(inv)); + QVERIFY(object.prototype().strictlyEquals(proto)); } void tst_QScriptValue::getSetPrototype_twoEngines() @@ -2367,8 +2366,6 @@ void tst_QScriptValue::getSetPrototype_notObjectOrNull() QScriptValue object = eng.newObject(); QScriptValue originalProto = object.prototype(); - QEXPECT_FAIL("", "QTBUG-15154: QScriptValue::setPrototype() allows a non-Object value to be set as prototype", Abort); - // bool object.setPrototype(true); QVERIFY(object.prototype().equals(originalProto)); diff --git a/tests/auto/qscriptvaluegenerated/testgen/testgenerator.h b/tests/auto/qscriptvaluegenerated/testgen/testgenerator.h index 1c61fc5..be4f79f 100644 --- a/tests/auto/qscriptvaluegenerated/testgen/testgenerator.h +++ b/tests/auto/qscriptvaluegenerated/testgen/testgenerator.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qscriptvaluegenerated/tst_qscriptvalue.cpp b/tests/auto/qscriptvaluegenerated/tst_qscriptvalue.cpp index 962a2af..529558f 100644 --- a/tests/auto/qscriptvaluegenerated/tst_qscriptvalue.cpp +++ b/tests/auto/qscriptvaluegenerated/tst_qscriptvalue.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qscriptvaluegenerated/tst_qscriptvalue.h b/tests/auto/qscriptvaluegenerated/tst_qscriptvalue.h index 8248ef3..f625399 100644 --- a/tests/auto/qscriptvaluegenerated/tst_qscriptvalue.h +++ b/tests/auto/qscriptvaluegenerated/tst_qscriptvalue.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qscroller/tst_qscroller.cpp b/tests/auto/qscroller/tst_qscroller.cpp index b4e4ddf..a9b3d9f 100644 --- a/tests/auto/qscroller/tst_qscroller.cpp +++ b/tests/auto/qscroller/tst_qscroller.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index 6bb971d..d26f0cd 100644 --- a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp @@ -144,6 +144,8 @@ private slots: void taskQTBUG_7537_appearsAndSort(); void taskQTBUG_7716_unnecessaryDynamicSorting(); void taskQTBUG_10287_unnecessaryMapCreation(); + void taskQTBUG_17812_resetInvalidate_data(); + void taskQTBUG_17812_resetInvalidate(); void testMultipleProxiesWithSelection(); void mapSelectionFromSource(); @@ -3351,5 +3353,60 @@ void tst_QSortFilterProxyModel::filteredColumns() insertCommand->doCommand(); } +void tst_QSortFilterProxyModel::taskQTBUG_17812_resetInvalidate_data() +{ + QTest::addColumn<int>("test"); + QTest::addColumn<bool>("works"); + + QTest::newRow("nothing") << 0 << false; + QTest::newRow("reset") << 1 << true; + QTest::newRow("invalidate") << 2 << true; + QTest::newRow("invalidate_filter") << 3 << true; +} + +void tst_QSortFilterProxyModel::taskQTBUG_17812_resetInvalidate() +{ + QFETCH(int, test); + QFETCH(bool, works); + + struct Proxy : QSortFilterProxyModel { + QString pattern; + virtual bool filterAcceptsRow(int source_row, const QModelIndex&) const { + return sourceModel()->data(sourceModel()->index(source_row, 0)).toString().contains(pattern); + } + void notifyChange(int test) { + switch (test) { + case 0: break; + case 1: reset(); break; + case 2: invalidate(); break; + case 3: invalidateFilter(); break; + } + } + }; + + QStringListModel sourceModel(QStringList() << "Poisson" << "Vache" << "Brebis" + << "Elephant" << "Cochon" << "Serpent" + << "Mouton" << "Ecureuil" << "Mouche"); + Proxy proxy; + proxy.pattern = QString::fromLatin1("n"); + proxy.setSourceModel(&sourceModel); + + QCOMPARE(proxy.rowCount(), 5); + for (int i = 0; i < proxy.rowCount(); i++) { + QVERIFY(proxy.data(proxy.index(i,0)).toString().contains('n')); + } + + proxy.pattern = QString::fromLatin1("o"); + proxy.notifyChange(test); + + QCOMPARE(proxy.rowCount(), works ? 4 : 5); + bool ok = true; + for (int i = 0; i < proxy.rowCount(); i++) { + if (!proxy.data(proxy.index(i,0)).toString().contains('o')) + ok = false; + } + QCOMPARE(ok, works); +} + QTEST_MAIN(tst_QSortFilterProxyModel) #include "tst_qsortfilterproxymodel.moc" diff --git a/tests/auto/qsslsocket/tst_qsslsocket.cpp b/tests/auto/qsslsocket/tst_qsslsocket.cpp index a5b5b23..023fbb3 100644 --- a/tests/auto/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/qsslsocket/tst_qsslsocket.cpp @@ -66,6 +66,7 @@ Q_DECLARE_METATYPE(QSslSocket::SslMode) typedef QList<QSslError::SslError> SslErrorList; Q_DECLARE_METATYPE(SslErrorList) Q_DECLARE_METATYPE(QSslError) +Q_DECLARE_METATYPE(QSsl::SslProtocol) #endif #if defined Q_OS_HPUX && defined Q_CC_GNU @@ -145,10 +146,11 @@ private slots: void peerCertificateChain(); void privateKey(); void protocol(); + void protocolServerSide_data(); + void protocolServerSide(); void setCaCertificates(); void setLocalCertificate(); void setPrivateKey(); - void setProtocol(); void setSocketDescriptor(); void waitForEncrypted(); void waitForConnectedEncryptedReadyRead(); @@ -385,7 +387,7 @@ void tst_QSslSocket::constructing() QVERIFY(!socket.waitForConnected(10)); QTest::ignoreMessage(QtWarningMsg, "QSslSocket::waitForDisconnected() is not allowed in UnconnectedState"); QVERIFY(!socket.waitForDisconnected(10)); - QCOMPARE(socket.protocol(), QSsl::TlsV1); + QCOMPARE(socket.protocol(), QSsl::SecureProtocols); QSslConfiguration savedDefault = QSslConfiguration::defaultConfiguration(); @@ -765,15 +767,13 @@ void tst_QSslSocket::protocol() this->socket = socket; QList<QSslCertificate> certs = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); -// qDebug() << "certs:" << certs.at(0).issuerInfo(QSslCertificate::CommonName); socket->setCaCertificates(certs); #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(untrustedWorkaroundSlot(QList<QSslError>))); #endif -// qDebug() << "socket cert:" << socket->caCertificates().at(0).issuerInfo(QSslCertificate::CommonName); - QCOMPARE(socket->protocol(), QSsl::TlsV1); + QCOMPARE(socket->protocol(), QSsl::SecureProtocols); { // Fluke allows SSLv3. socket->setProtocol(QSsl::SslV3); @@ -837,44 +837,36 @@ void tst_QSslSocket::protocol() QCOMPARE(socket->protocol(), QSsl::AnyProtocol); socket->abort(); } -} - -void tst_QSslSocket::setCaCertificates() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocket socket; - QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); - socket.setCaCertificates(QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem")); - QCOMPARE(socket.caCertificates().size(), 1); - socket.setCaCertificates(socket.defaultCaCertificates()); - QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); -} - -void tst_QSslSocket::setLocalCertificate() -{ -} - -void tst_QSslSocket::setPrivateKey() -{ -} - -void tst_QSslSocket::setProtocol() -{ + { + // Fluke allows SSLV3, so it allows NoSslV2 + socket->setProtocol(QSsl::TlsV1SslV3); + QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3); + socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); + QVERIFY(socket->waitForEncrypted()); + QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3); + socket->abort(); + QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3); + socket->connectToHost(QtNetworkSettings::serverName(), 443); + QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString())); + socket->startClientEncryption(); + QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString())); + QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3); + socket->abort(); + } } class SslServer : public QTcpServer { Q_OBJECT public: - SslServer() : socket(0) { } + SslServer() : socket(0), protocol(QSsl::TlsV1) { } QSslSocket *socket; - + QSsl::SslProtocol protocol; protected: void incomingConnection(int socketDescriptor) { socket = new QSslSocket(this); + socket->setProtocol(protocol); connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); QFile file(SRCDIR "certs/fluke.key"); @@ -904,6 +896,118 @@ protected slots: } }; +void tst_QSslSocket::protocolServerSide_data() +{ + + QTest::addColumn<QSsl::SslProtocol>("serverProtocol"); + QTest::addColumn<QSsl::SslProtocol>("clientProtocol"); + QTest::addColumn<bool>("works"); + + QTest::newRow("ssl2-ssl2") << QSsl::SslV2 << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2 + QTest::newRow("ssl3-ssl3") << QSsl::SslV3 << QSsl::SslV3 << true; + QTest::newRow("tls1-tls1") << QSsl::TlsV1 << QSsl::TlsV1 << true; + QTest::newRow("tls1ssl3-tls1ssl3") << QSsl::TlsV1SslV3 << QSsl::TlsV1SslV3 << true; + QTest::newRow("any-any") << QSsl::AnyProtocol << QSsl::AnyProtocol << true; + QTest::newRow("secure-secure") << QSsl::SecureProtocols << QSsl::SecureProtocols << true; + + QTest::newRow("ssl2-ssl3") << QSsl::SslV2 << QSsl::SslV3 << false; + QTest::newRow("ssl2-tls1") << QSsl::SslV2 << QSsl::TlsV1 << false; + QTest::newRow("ssl2-tls1ssl3") << QSsl::SslV2 << QSsl::TlsV1SslV3 << false; + QTest::newRow("ssl2-secure") << QSsl::SslV2 << QSsl::SecureProtocols << false; + QTest::newRow("ssl2-any") << QSsl::SslV2 << QSsl::AnyProtocol << false; // no idea why it does not work, but we don't care about SSL 2 + + QTest::newRow("ssl3-ssl2") << QSsl::SslV3 << QSsl::SslV2 << false; + QTest::newRow("ssl3-tls1") << QSsl::SslV3 << QSsl::TlsV1 << false; + QTest::newRow("ssl3-tls1ssl3") << QSsl::SslV3 << QSsl::TlsV1SslV3 << true; + QTest::newRow("ssl3-secure") << QSsl::SslV3 << QSsl::SecureProtocols << true; + QTest::newRow("ssl3-any") << QSsl::SslV3 << QSsl::AnyProtocol << false; // we wont set a SNI header here because we connect to a + // numerical IP, so OpenSSL will send a SSL 2 handshake + + QTest::newRow("tls1-ssl2") << QSsl::TlsV1 << QSsl::SslV2 << false; + QTest::newRow("tls1-ssl3") << QSsl::TlsV1 << QSsl::SslV3 << false; + QTest::newRow("tls1-tls1ssl3") << QSsl::TlsV1 << QSsl::TlsV1SslV3 << true; + QTest::newRow("tls1-secure") << QSsl::TlsV1 << QSsl::SecureProtocols << true; + QTest::newRow("tls1-any") << QSsl::TlsV1 << QSsl::AnyProtocol << false; // we wont set a SNI header here because we connect to a + // numerical IP, so OpenSSL will send a SSL 2 handshake + + QTest::newRow("tls1ssl3-ssl2") << QSsl::TlsV1SslV3 << QSsl::SslV2 << false; + QTest::newRow("tls1ssl3-ssl3") << QSsl::TlsV1SslV3 << QSsl::SslV3 << true; + QTest::newRow("tls1ssl3-tls1") << QSsl::TlsV1SslV3 << QSsl::TlsV1 << true; + QTest::newRow("tls1ssl3-secure") << QSsl::TlsV1SslV3 << QSsl::SecureProtocols << true; + QTest::newRow("tls1ssl3-any") << QSsl::TlsV1SslV3 << QSsl::AnyProtocol << true; + + QTest::newRow("secure-ssl2") << QSsl::SecureProtocols << QSsl::SslV2 << false; + QTest::newRow("secure-ssl3") << QSsl::SecureProtocols << QSsl::SslV3 << true; + QTest::newRow("secure-tls1") << QSsl::SecureProtocols << QSsl::TlsV1 << true; + QTest::newRow("secure-tls1ssl3") << QSsl::SecureProtocols << QSsl::TlsV1SslV3 << true; + QTest::newRow("secure-any") << QSsl::SecureProtocols << QSsl::AnyProtocol << true; + + QTest::newRow("any-ssl2") << QSsl::AnyProtocol << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2 + QTest::newRow("any-ssl3") << QSsl::AnyProtocol << QSsl::SslV3 << true; + QTest::newRow("any-tls1") << QSsl::AnyProtocol << QSsl::TlsV1 << true; + QTest::newRow("any-tls1ssl3") << QSsl::AnyProtocol << QSsl::TlsV1SslV3 << true; + QTest::newRow("any-secure") << QSsl::AnyProtocol << QSsl::SecureProtocols << true; +} + +void tst_QSslSocket::protocolServerSide() +{ + if (!QSslSocket::supportsSsl()) { + qWarning("SSL not supported, skipping test"); + return; + } + + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + QFETCH(QSsl::SslProtocol, serverProtocol); + SslServer server; + server.protocol = serverProtocol; + QVERIFY(server.listen()); + + QEventLoop loop; + QTimer::singleShot(5000, &loop, SLOT(quit())); + + QSslSocketPtr client = new QSslSocket; + socket = client; + QFETCH(QSsl::SslProtocol, clientProtocol); + socket->setProtocol(clientProtocol); + // upon SSL wrong version error, error will be triggered, not sslErrors + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit())); + connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); + connect(client, SIGNAL(encrypted()), &loop, SLOT(quit())); + + client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); + + loop.exec(); + + QFETCH(bool, works); + QAbstractSocket::SocketState expectedState = (works) ? QAbstractSocket::ConnectedState : QAbstractSocket::UnconnectedState; + QCOMPARE(client->state(), expectedState); + QCOMPARE(client->isEncrypted(), works); +} + +void tst_QSslSocket::setCaCertificates() +{ + if (!QSslSocket::supportsSsl()) + return; + + QSslSocket socket; + QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); + socket.setCaCertificates(QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem")); + QCOMPARE(socket.caCertificates().size(), 1); + socket.setCaCertificates(socket.defaultCaCertificates()); + QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); +} + +void tst_QSslSocket::setLocalCertificate() +{ +} + +void tst_QSslSocket::setPrivateKey() +{ +} + void tst_QSslSocket::setSocketDescriptor() { if (!QSslSocket::supportsSsl()) diff --git a/tests/auto/qstringref/tst_qstringref.cpp b/tests/auto/qstringref/tst_qstringref.cpp index 585e14e..301559e 100644 --- a/tests/auto/qstringref/tst_qstringref.cpp +++ b/tests/auto/qstringref/tst_qstringref.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/auto/qtextblock/tst_qtextblock.cpp b/tests/auto/qtextblock/tst_qtextblock.cpp index 7b41874..cec3a6a 100644 --- a/tests/auto/qtextblock/tst_qtextblock.cpp +++ b/tests/auto/qtextblock/tst_qtextblock.cpp @@ -75,6 +75,7 @@ private slots: void fragmentOverBlockBoundaries(); void excludeParagraphSeparatorFragment(); void backwardsBlockIterator(); + void previousBlock_qtbug18026(); private: QTextDocument *doc; @@ -174,5 +175,11 @@ void tst_QTextBlock::backwardsBlockIterator() QCOMPARE(it.fragment().position(), 0); } +void tst_QTextBlock::previousBlock_qtbug18026() +{ + QTextBlock last = doc->end().previous(); + QVERIFY(last.isValid()); +} + QTEST_MAIN(tst_QTextBlock) #include "tst_qtextblock.moc" diff --git a/tests/auto/qtextlayout/tst_qtextlayout.cpp b/tests/auto/qtextlayout/tst_qtextlayout.cpp index d1b615e..83c7094 100644 --- a/tests/auto/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/qtextlayout/tst_qtextlayout.cpp @@ -124,8 +124,9 @@ private slots: void testLineBreakingAllSpaces(); void lineWidthFromBOM(); void textWidthVsWIdth(); - void textWithSurrogates_qtbug15679(); + void textWidthWithStackedTextEngine(); + void textWidthWithLineSeparator(); private: QFont testFont; @@ -1432,5 +1433,32 @@ void tst_QTextLayout::textWithSurrogates_qtbug15679() QCOMPARE(x[2] - x[0], x[5] - x[3]); } +void tst_QTextLayout::textWidthWithStackedTextEngine() +{ + QString text = QString::fromUtf8("คลิก ถัดไป เพื่อดำเนินการต่อ"); + QTextLayout layout(text); + layout.beginLayout(); + QTextLine line = layout.createLine(); + layout.endLayout(); + QFontMetricsF fm(layout.font()); + QCOMPARE(line.naturalTextWidth(), fm.width(text)); +} + +void tst_QTextLayout::textWidthWithLineSeparator() +{ + QString s1("Save Project"), s2("Save Project\ntest"); + s2.replace('\n', QChar::LineSeparator); + + QTextLayout layout1(s1), layout2(s2); + layout1.beginLayout(); + layout2.beginLayout(); + + QTextLine line1 = layout1.createLine(); + QTextLine line2 = layout2.createLine(); + line1.setLineWidth(0x1000); + line2.setLineWidth(0x1000); + QCOMPARE(line1.naturalTextWidth(), line2.naturalTextWidth()); +} + QTEST_MAIN(tst_QTextLayout) #include "tst_qtextlayout.moc" diff --git a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp index 91d0f3f..4f4e706a 100644 --- a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp +++ b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp @@ -56,7 +56,7 @@ -#if defined(Q_WS_X11) +#if defined(Q_WS_X11) || defined(Q_WS_MAC) #define private public #include <private/qtextengine_p.h> #include <qtextlayout.h> @@ -104,6 +104,7 @@ private slots: void khmer(); void linearB(); void controlInSyllable_qtbug14204(); + void combiningMarks_qtbug15675(); }; tst_QTextScriptEngine::tst_QTextScriptEngine() @@ -1133,5 +1134,27 @@ void tst_QTextScriptEngine::controlInSyllable_qtbug14204() #endif } +void tst_QTextScriptEngine::combiningMarks_qtbug15675() +{ +#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA) + QString s; + s.append(QChar(0x0061)); + s.append(QChar(0x0062)); + s.append(QChar(0x0300)); + s.append(QChar(0x0063)); + + QFont font("Monaco"); + QTextLayout layout(s, font); + QTextEngine *e = layout.d; + e->itemize(); + e->shape(0); + + QVERIFY(e->layoutData->items[0].num_glyphs == 4); + QVERIFY(e->layoutData->glyphLayout.advances_y[2] > 0); +#else + QSKIP("Mac specific test", SkipAll); +#endif +} + QTEST_MAIN(tst_QTextScriptEngine) #include "tst_qtextscriptengine.moc" diff --git a/tests/auto/qvariant/tst_qvariant.cpp b/tests/auto/qvariant/tst_qvariant.cpp index 62babdb..2e57264 100644 --- a/tests/auto/qvariant/tst_qvariant.cpp +++ b/tests/auto/qvariant/tst_qvariant.cpp @@ -2660,7 +2660,10 @@ void tst_QVariant::qvariant_cast_QObject_data() { QTest::addColumn<QVariant>("data"); QTest::addColumn<bool>("success"); - QTest::newRow("from QObject") << QVariant(QMetaType::QObjectStar, new QObject(this)) << true; + QObject *obj = new QObject(this); + obj->setObjectName(QString::fromLatin1("Hello")); + QTest::newRow("from QObject") << QVariant(QMetaType::QObjectStar, &obj) << true; + QTest::newRow("from QObject2") << QVariant::fromValue(obj) << true; QTest::newRow("from String") << QVariant(QLatin1String("1, 2, 3")) << false; QTest::newRow("from int") << QVariant((int) 123) << false; } @@ -2672,6 +2675,9 @@ void tst_QVariant::qvariant_cast_QObject() { QObject *o = qvariant_cast<QObject *>(data); QCOMPARE(o != 0, success); + if (success) { + QCOMPARE(o->objectName(), QString::fromLatin1("Hello")); + } } Q_DECLARE_METATYPE(qint8); diff --git a/tests/auto/qvolatileimage/qvolatileimage.pro b/tests/auto/qvolatileimage/qvolatileimage.pro new file mode 100644 index 0000000..5a0a613 --- /dev/null +++ b/tests/auto/qvolatileimage/qvolatileimage.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +SOURCES += tst_qvolatileimage.cpp + +symbian { + TARGET.EPOCHEAPSIZE = 0x200000 0x800000 + LIBS += -lfbscli +} diff --git a/tests/auto/qvolatileimage/tst_qvolatileimage.cpp b/tests/auto/qvolatileimage/tst_qvolatileimage.cpp new file mode 100644 index 0000000..b91a150 --- /dev/null +++ b/tests/auto/qvolatileimage/tst_qvolatileimage.cpp @@ -0,0 +1,403 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <QtGui/qpainter.h> +#include <QtGui/qpaintengine.h> +#include <QtGui/private/qvolatileimage_p.h> +#ifdef Q_OS_SYMBIAN +#include <fbs.h> +#endif + +class tst_QVolatileImage : public QObject +{ + Q_OBJECT + +public: + tst_QVolatileImage() { } + +private slots: + void create(); + void ensureFormat(); + void dataAccess(); + void sharing(); + void paint(); + void fill(); + void copy(); + void bitmap(); +}; + +void tst_QVolatileImage::create() +{ + QVolatileImage nullImg; + QVERIFY(nullImg.isNull()); + + QVolatileImage img(100, 200, QImage::Format_ARGB32); + QVERIFY(!img.isNull()); + QCOMPARE(img.width(), 100); + QCOMPARE(img.height(), 200); + QCOMPARE(img.format(), QImage::Format_ARGB32); + QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height()); + QCOMPARE(img.hasAlphaChannel(), true); + QCOMPARE(img.depth(), 32); + + QImage source(12, 23, QImage::Format_ARGB32_Premultiplied); + img = QVolatileImage(source); + QVERIFY(!img.isNull()); + QCOMPARE(img.width(), 12); + QCOMPARE(img.height(), 23); + QCOMPARE(img.format(), source.format()); + QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height()); + QVERIFY(img.imageRef() == source); + QVERIFY(img.toImage() == source); + QCOMPARE(img.hasAlphaChannel(), true); + QCOMPARE(img.hasAlphaChannel(), img.imageRef().hasAlphaChannel()); + QCOMPARE(img.hasAlphaChannel(), img.toImage().hasAlphaChannel()); + QCOMPARE(img.depth(), 32); + +#ifdef Q_OS_SYMBIAN + CFbsBitmap *bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(100, 50), EColor16MAP) == KErrNone); + QVolatileImage bmpimg(bmp); + QVERIFY(!bmpimg.isNull()); + QCOMPARE(bmpimg.width(), 100); + QCOMPARE(bmpimg.height(), 50); + // Verify that we only did handle duplication, not pixel data copying. + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + delete bmp; + // Check if content is still valid. + QImage copyimg = bmpimg.toImage(); + QCOMPARE(copyimg.format(), QImage::Format_ARGB32_Premultiplied); +#endif +} + +void tst_QVolatileImage::ensureFormat() +{ + QImage source(12, 23, QImage::Format_ARGB32_Premultiplied); + QVolatileImage img(source); + QVERIFY(!img.isNull()); + QVERIFY(img.imageRef() == source); + QVERIFY(img.toImage() == source); + + QVERIFY(img.ensureFormat(QImage::Format_ARGB32_Premultiplied)); // no-op + QVERIFY(img.imageRef() == source); + QVERIFY(img.toImage() == source); + QVERIFY(img.format() == QImage::Format_ARGB32_Premultiplied); + + QVERIFY(img.ensureFormat(QImage::Format_RGB32)); // new data under-the-hood + QVERIFY(img.imageRef() != source); + QVERIFY(img.toImage() != source); + QVERIFY(img.format() == QImage::Format_RGB32); + +#ifdef Q_OS_SYMBIAN + CFbsBitmap *bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(100, 50), EColor16MAP) == KErrNone); + QVolatileImage bmpimg(bmp); + QVERIFY(bmpimg.ensureFormat(QImage::Format_ARGB32_Premultiplied)); // no-op + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + + // A different format should cause data copying. + QVERIFY(bmpimg.ensureFormat(QImage::Format_RGB32)); + QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress()); + const uchar *prevBits = bmpimg.constBits(); + + QVERIFY(bmpimg.ensureFormat(QImage::Format_RGB16)); + QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress()); + QVERIFY(bmpimg.constBits() != prevBits); + prevBits = bmpimg.constBits(); + + QVERIFY(bmpimg.ensureFormat(QImage::Format_MonoLSB)); + QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress()); + QVERIFY(bmpimg.constBits() != prevBits); + + delete bmp; +#endif +} + +void tst_QVolatileImage::dataAccess() +{ + QImage source(12, 23, QImage::Format_ARGB32_Premultiplied); + QVolatileImage img(source); + QVERIFY(!img.isNull()); + img.beginDataAccess(); + QVERIFY(img.constBits()); + QVERIFY(img.imageRef().constBits()); + QVERIFY(img.bits()); + QVERIFY(img.imageRef().bits()); + img.endDataAccess(); + + img = QVolatileImage(12, 23, QImage::Format_ARGB32); + img.beginDataAccess(); + QVERIFY(img.constBits() && img.bits()); + img.endDataAccess(); +} + +void tst_QVolatileImage::sharing() +{ + QVolatileImage img1(100, 100, QImage::Format_ARGB32); + QVolatileImage img2 = img1; + img1.beginDataAccess(); + img2.beginDataAccess(); + QVERIFY(img1.constBits() == img2.constBits()); + img2.endDataAccess(); + img1.endDataAccess(); + img1.imageRef(); // non-const call, should detach + img1.beginDataAccess(); + img2.beginDataAccess(); + QVERIFY(img1.constBits() != img2.constBits()); + img2.endDataAccess(); + img1.endDataAccess(); + + // toImage() should return a copy of the internal QImage. + // imageRef() is a reference to the internal QImage. + QVERIFY(img1.imageRef().constBits() != img1.toImage().constBits()); + +#ifdef Q_OS_SYMBIAN + CFbsBitmap *bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(100, 50), EColor16MAP) == KErrNone); + QVolatileImage bmpimg(bmp); + QVolatileImage bmpimg2; + bmpimg2 = bmpimg; + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + QCOMPARE(bmpimg2.constBits(), (const uchar *) bmp->DataAddress()); + // Now force a detach, which should copy the pixel data under-the-hood. + bmpimg.imageRef(); + QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress()); + QCOMPARE(bmpimg2.constBits(), (const uchar *) bmp->DataAddress()); + delete bmp; +#endif +} + +bool fuzzyCompareImages(const QImage &image1, const QImage &image2, int tolerance) +{ + if (image1.bytesPerLine() != image2.bytesPerLine() + || image1.width() != image2.width() + || image1.height() != image2.height()) { + return false; + } + for (int i = 0; i < image1.height(); i++) { + const uchar *line1 = image1.scanLine(i); + const uchar *line2 = image2.scanLine(i); + int bytes = image1.bytesPerLine(); + for (int j = 0; j < bytes; j++) { + int delta = line1[j] - line2[j]; + if (qAbs(delta) > tolerance) + return false; + } + } + return true; +} + +void tst_QVolatileImage::paint() +{ +#ifdef Q_OS_SYMBIAN + QVolatileImage img(100, 100, QImage::Format_ARGB32); + img.beginDataAccess(); + img.imageRef().fill(QColor(Qt::green).rgba()); + QPainter p(&img.imageRef()); + p.drawRect(10, 10, 50, 50); + p.end(); + img.endDataAccess(); + QImage imgA = img.toImage(); + + // The following assumes that on openvg the pixmapdata is backed by QVolatileImage) + // (and that openvg is in use) + // It should pass with any engine nonetheless. + // See if painting into the underlying QImage succeeds. + QPixmap pm(100, 100); + if (pm.paintEngine()->type() == QPaintEngine::Raster) { + pm.fill(Qt::green); + QPainter pmp(&pm); + pmp.drawRect(10, 10, 50, 50); + pmp.end(); + QImage imgB = pm.toImage(); + QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); + // Exercise the accelerated QVolatileImagePaintEngine::drawPixmap() a bit. + QPixmap targetPm(pm.size()); + targetPm.fill(Qt::black); + pmp.begin(&targetPm); + pmp.drawPixmap(QPointF(0, 0), pm); + pmp.end(); + imgB = targetPm.toImage(); + QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); + // Now the overload taking rects. + targetPm.fill(Qt::black); + pmp.begin(&targetPm); + QRectF rect(QPointF(0, 0), pm.size()); + pmp.drawPixmap(rect, pm, rect); + pmp.end(); + imgB = targetPm.toImage(); + QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); + } else { + QSKIP("Pixmaps not painted via raster, skipping paint test", SkipSingle); + } +#endif +} + +void tst_QVolatileImage::fill() +{ + QVolatileImage img(100, 100, QImage::Format_ARGB32_Premultiplied); + QColor col = QColor(10, 20, 30); + img.fill(col.rgba()); + QVERIFY(img.imageRef().pixel(1, 1) == col.rgba()); + QVERIFY(img.toImage().pixel(1, 1) == col.rgba()); + +#ifdef Q_OS_SYMBIAN + CFbsBitmap *bmp = static_cast<CFbsBitmap *>(img.duplicateNativeImage()); + QVERIFY(bmp); + TRgb pix; + bmp->GetPixel(pix, TPoint(1, 1)); + QCOMPARE(pix.Red(), col.red()); + QCOMPARE(pix.Green(), col.green()); + QCOMPARE(pix.Blue(), col.blue()); + delete bmp; +#endif +} + +void tst_QVolatileImage::copy() +{ + QVolatileImage img(100, 100, QImage::Format_RGB32); + img.beginDataAccess(); + img.imageRef().fill(QColor(Qt::green).rgba()); + QPainter p(&img.imageRef()); + p.drawRect(10, 10, 50, 50); + p.end(); + img.endDataAccess(); + + QVolatileImage img2(100, 100, QImage::Format_RGB32); + img2.copyFrom(&img, QRect()); + QImage imgA = img.toImage(); + QImage imgB = img2.toImage(); + QCOMPARE(imgA.size(), imgB.size()); + QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); + + img2 = QVolatileImage(20, 20, QImage::Format_RGB32); + img2.copyFrom(&img, QRect(5, 5, 20, 20)); + imgA = img.toImage().copy(5, 5, 20, 20); + imgB = img2.toImage(); + QCOMPARE(imgA.size(), imgB.size()); + QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); +} + +void tst_QVolatileImage::bitmap() +{ +#ifdef Q_OS_SYMBIAN + CFbsBitmap *bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(100, 50), EColor64K) == KErrNone); + QVolatileImage bmpimg(bmp); + CFbsBitmap *dupbmp = static_cast<CFbsBitmap *>(bmpimg.duplicateNativeImage()); + QVERIFY(dupbmp); + QVERIFY(dupbmp != bmp); + QCOMPARE(dupbmp->DataAddress(), bmp->DataAddress()); + delete dupbmp; + delete bmp; + bmpimg.beginDataAccess(); + qMemSet(bmpimg.bits(), 0, bmpimg.byteCount()); + qMemSet(bmpimg.bits(), 1, bmpimg.bytesPerLine() * bmpimg.height()); + bmpimg.endDataAccess(); + + // Test bgr->rgb conversion in case of EColor16M. + bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(101, 89), EColor16M) == KErrNone); + bmp->BeginDataAccess(); + TUint32 *addr = bmp->DataAddress(); + uint rgb = QColor(10, 20, 30).rgb(); + qMemCopy(bmp->DataAddress(), &rgb, 3); + bmp->EndDataAccess(); + TRgb symrgb; + bmp->GetPixel(symrgb, TPoint(0, 0)); + QVERIFY(symrgb.Red() == 10 && symrgb.Green() == 20 && symrgb.Blue() == 30); + bmpimg = QVolatileImage(bmp); + QVERIFY(bmpimg.toImage().pixel(0, 0) == rgb); + // check if there really was a conversion + bmp->BeginDataAccess(); + bmpimg.beginDataAccess(); + qMemCopy(&rgb, bmpimg.constBits(), 3); + uint rgb2 = rgb; + qMemCopy(&rgb2, bmp->DataAddress(), 3); + QVERIFY(rgb != rgb2); + bmpimg.endDataAccess(true); + bmp->EndDataAccess(true); + delete bmp; + + bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(101, 89), EGray2) == KErrNone); + bmpimg = QVolatileImage(bmp); // inverts pixels, but should do it in place + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + QCOMPARE(bmpimg.format(), QImage::Format_MonoLSB); + bmpimg.ensureFormat(QImage::Format_ARGB32_Premultiplied); + QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress()); + QCOMPARE(bmpimg.format(), QImage::Format_ARGB32_Premultiplied); + delete bmp; + + // The following two formats must be optimal always. + bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(101, 89), EColor16MAP) == KErrNone); + bmpimg = QVolatileImage(bmp); + QCOMPARE(bmpimg.format(), QImage::Format_ARGB32_Premultiplied); + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + bmpimg.ensureFormat(QImage::Format_ARGB32_Premultiplied); + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + delete bmp; + bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(101, 89), EColor16MU) == KErrNone); + bmpimg = QVolatileImage(bmp); + QCOMPARE(bmpimg.format(), QImage::Format_RGB32); + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + bmpimg.ensureFormat(QImage::Format_RGB32); + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + delete bmp; + +#else + QSKIP("CFbsBitmap is only available on Symbian, skipping bitmap test", SkipSingle); +#endif +} + +int main(int argc, char *argv[]) +{ + QApplication::setGraphicsSystem("openvg"); + QApplication app(argc, argv); + tst_QVolatileImage tc; + return QTest::qExec(&tc, argc, argv); +} + +#include "tst_qvolatileimage.moc" diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 2208bea..35014c9 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -10576,7 +10576,7 @@ void tst_QWidget::nativeChildFocus() QTest::qWaitForWindowShown(&w); QCOMPARE(QApplication::activeWindow(), &w); - QCOMPARE(QApplication::focusWidget(), p1); + QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1)); } QTEST_MAIN(tst_QWidget) diff --git a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp index b0c5702..aa4c15a 100644 --- a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp +++ b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp b/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp index 497a556..a03e095 100644 --- a/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp +++ b/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/benchmarks/gui/kernel/qguimetatype/tst_qguimetatype.cpp b/tests/benchmarks/gui/kernel/qguimetatype/tst_qguimetatype.cpp index f94767b..fd5132c 100644 --- a/tests/benchmarks/gui/kernel/qguimetatype/tst_qguimetatype.cpp +++ b/tests/benchmarks/gui/kernel/qguimetatype/tst_qguimetatype.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/benchmarks/gui/kernel/qguivariant/tst_qguivariant.cpp b/tests/benchmarks/gui/kernel/qguivariant/tst_qguivariant.cpp index 4016be1..a9e49b5 100644 --- a/tests/benchmarks/gui/kernel/qguivariant/tst_qguivariant.cpp +++ b/tests/benchmarks/gui/kernel/qguivariant/tst_qguivariant.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/benchmarks/script/qscriptqobject/tst_qscriptqobject.cpp b/tests/benchmarks/script/qscriptqobject/tst_qscriptqobject.cpp index 62f3c2a..926d2ce 100644 --- a/tests/benchmarks/script/qscriptqobject/tst_qscriptqobject.cpp +++ b/tests/benchmarks/script/qscriptqobject/tst_qscriptqobject.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/benchmarks/script/script.pro b/tests/benchmarks/script/script.pro index d4fc822..80278d0 100644 --- a/tests/benchmarks/script/script.pro +++ b/tests/benchmarks/script/script.pro @@ -13,6 +13,8 @@ SUBDIRS = \ TRUSTED_BENCHMARKS += \ qscriptclass \ qscriptvalue \ - qscriptengine + qscriptengine \ + qscriptobject \ + context2d include(../trusted-benchmarks.pri) diff --git a/tests/benchmarks/script/sunspider/tst_sunspider.cpp b/tests/benchmarks/script/sunspider/tst_sunspider.cpp index 9e2bb6f..da1458e 100644 --- a/tests/benchmarks/script/sunspider/tst_sunspider.cpp +++ b/tests/benchmarks/script/sunspider/tst_sunspider.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/benchmarks/script/v8/tst_v8.cpp b/tests/benchmarks/script/v8/tst_v8.cpp index b9cb859..c23395a 100644 --- a/tests/benchmarks/script/v8/tst_v8.cpp +++ b/tests/benchmarks/script/v8/tst_v8.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/tests/manual/mkspecs/test.sh b/tests/manual/mkspecs/test.sh index 7e942a4..0aae76a 100755 --- a/tests/manual/mkspecs/test.sh +++ b/tests/manual/mkspecs/test.sh @@ -1,7 +1,7 @@ #!/bin/bash ############################################################################# ## -## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ## All rights reserved. ## Contact: Nokia Corporation (qt-info@nokia.com) ## diff --git a/tests/manual/qlocale/calendar.cpp b/tests/manual/qlocale/calendar.cpp new file mode 100644 index 0000000..bd4756e --- /dev/null +++ b/tests/manual/qlocale/calendar.cpp @@ -0,0 +1,405 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "calendar.h" + +CalendarWidget::CalendarWidget() +{ + createPreviewGroupBox(); + createGeneralOptionsGroupBox(); + createDatesGroupBox(); + createTextFormatsGroupBox(); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(previewGroupBox, 0, 0); + layout->addWidget(generalOptionsGroupBox, 0, 1); + layout->addWidget(datesGroupBox, 1, 0); + layout->addWidget(textFormatsGroupBox, 1, 1); + layout->setSizeConstraint(QLayout::SetFixedSize); + setLayout(layout); + + previewLayout->setRowMinimumHeight(0, calendar->sizeHint().height()); + previewLayout->setColumnMinimumWidth(0, calendar->sizeHint().width()); + + setWindowTitle(tr("Calendar Widget")); +} + +void CalendarWidget::localeChanged(QLocale locale) +{ + calendar->setLocale(locale); + firstDayCombo->setCurrentIndex(locale.firstDayOfWeek()-1); + updateWeekendDays(); +} + +void CalendarWidget::firstDayChanged(int index) +{ + calendar->setFirstDayOfWeek(Qt::DayOfWeek( + firstDayCombo->itemData(index).toInt())); +} + +void CalendarWidget::selectionModeChanged(int index) +{ + calendar->setSelectionMode(QCalendarWidget::SelectionMode( + selectionModeCombo->itemData(index).toInt())); +} + +void CalendarWidget::horizontalHeaderChanged(int index) +{ + calendar->setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat( + horizontalHeaderCombo->itemData(index).toInt())); +} + +void CalendarWidget::verticalHeaderChanged(int index) +{ + calendar->setVerticalHeaderFormat(QCalendarWidget::VerticalHeaderFormat( + verticalHeaderCombo->itemData(index).toInt())); +} + +void CalendarWidget::selectedDateChanged() +{ + currentDateEdit->setDate(calendar->selectedDate()); +} + +void CalendarWidget::minimumDateChanged(const QDate &date) +{ + calendar->setMinimumDate(date); + maximumDateEdit->setDate(calendar->maximumDate()); +} + +void CalendarWidget::maximumDateChanged(const QDate &date) +{ + calendar->setMaximumDate(date); + minimumDateEdit->setDate(calendar->minimumDate()); +} + +bool CalendarWidget::isWeekendDay(Qt::DayOfWeek day) { + QList<Qt::DayOfWeek> week = calendar->locale().weekdays(); + return !week.contains(day); +} + +void CalendarWidget::updateWeekendDays() { + QTextCharFormat weekFormat, weekendFormat; + weekFormat.setForeground(qvariant_cast<QColor>( + weekdayColorCombo->itemData(weekdayColorCombo->currentIndex()))); + weekendFormat.setForeground(qvariant_cast<QColor>( + weekendColorCombo->itemData(weekendColorCombo->currentIndex()))); + + calendar->setWeekdayTextFormat(Qt::Monday, isWeekendDay(Qt::Monday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Tuesday, isWeekendDay(Qt::Tuesday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Wednesday, isWeekendDay(Qt::Wednesday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Thursday, isWeekendDay(Qt::Thursday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Friday, isWeekendDay(Qt::Friday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Saturday, isWeekendDay(Qt::Saturday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Sunday, isWeekendDay(Qt::Sunday) ? weekendFormat : weekFormat); +} + +void CalendarWidget::weekdayFormatChanged() +{ + updateWeekendDays(); +} + +void CalendarWidget::weekendFormatChanged() +{ + updateWeekendDays(); +} + +void CalendarWidget::reformatHeaders() +{ + QString text = headerTextFormatCombo->currentText(); + QTextCharFormat format; + + if (text == tr("Bold")) { + format.setFontWeight(QFont::Bold); + } else if (text == tr("Italic")) { + format.setFontItalic(true); + } else if (text == tr("Green")) { + format.setForeground(Qt::green); + } + calendar->setHeaderTextFormat(format); +} + +void CalendarWidget::reformatCalendarPage() +{ + if (firstFridayCheckBox->isChecked()) { + QDate firstFriday(calendar->yearShown(), calendar->monthShown(), 1); + while (firstFriday.dayOfWeek() != Qt::Friday) + firstFriday = firstFriday.addDays(1); + QTextCharFormat firstFridayFormat; + firstFridayFormat.setForeground(Qt::blue); + calendar->setDateTextFormat(firstFriday, firstFridayFormat); + } + + //May First in Red takes precedence + if (mayFirstCheckBox->isChecked()) { + const QDate mayFirst(calendar->yearShown(), 5, 1); + QTextCharFormat mayFirstFormat; + mayFirstFormat.setForeground(Qt::red); + calendar->setDateTextFormat(mayFirst, mayFirstFormat); + } +} + +void CalendarWidget::createPreviewGroupBox() +{ + previewGroupBox = new QGroupBox(tr("Preview")); + + calendar = new QCalendarWidget; + calendar->setMinimumDate(QDate(1900, 1, 1)); + calendar->setMaximumDate(QDate(3000, 1, 1)); + calendar->setGridVisible(true); + + connect(calendar, SIGNAL(currentPageChanged(int,int)), + this, SLOT(reformatCalendarPage())); + + previewLayout = new QGridLayout; + previewLayout->addWidget(calendar, 0, 0, Qt::AlignCenter); + previewGroupBox->setLayout(previewLayout); +} + +void CalendarWidget::createGeneralOptionsGroupBox() +{ + generalOptionsGroupBox = new QGroupBox(tr("General Options")); + + firstDayCombo = new QComboBox; + firstDayCombo->addItem(tr("Monday"), Qt::Monday); + firstDayCombo->addItem(tr("Tuesday"), Qt::Tuesday); + firstDayCombo->addItem(tr("Wednesday"), Qt::Wednesday); + firstDayCombo->addItem(tr("Thursday"), Qt::Thursday); + firstDayCombo->addItem(tr("Friday"), Qt::Friday); + firstDayCombo->addItem(tr("Saturday"), Qt::Saturday); + firstDayCombo->addItem(tr("Sunday"), Qt::Sunday); + + firstDayLabel = new QLabel(tr("Wee&k starts on:")); + firstDayLabel->setBuddy(firstDayCombo); + + selectionModeCombo = new QComboBox; + selectionModeCombo->addItem(tr("Single selection"), + QCalendarWidget::SingleSelection); + selectionModeCombo->addItem(tr("None"), QCalendarWidget::NoSelection); + + selectionModeLabel = new QLabel(tr("&Selection mode:")); + selectionModeLabel->setBuddy(selectionModeCombo); + + gridCheckBox = new QCheckBox(tr("&Grid")); + gridCheckBox->setChecked(calendar->isGridVisible()); + + navigationCheckBox = new QCheckBox(tr("&Navigation bar")); + navigationCheckBox->setChecked(true); + + horizontalHeaderCombo = new QComboBox; + horizontalHeaderCombo->addItem(tr("Single letter day names"), + QCalendarWidget::SingleLetterDayNames); + horizontalHeaderCombo->addItem(tr("Short day names"), + QCalendarWidget::ShortDayNames); + horizontalHeaderCombo->addItem(tr("None"), + QCalendarWidget::NoHorizontalHeader); + horizontalHeaderCombo->setCurrentIndex(1); + + horizontalHeaderLabel = new QLabel(tr("&Horizontal header:")); + horizontalHeaderLabel->setBuddy(horizontalHeaderCombo); + + verticalHeaderCombo = new QComboBox; + verticalHeaderCombo->addItem(tr("ISO week numbers"), + QCalendarWidget::ISOWeekNumbers); + verticalHeaderCombo->addItem(tr("None"), QCalendarWidget::NoVerticalHeader); + + verticalHeaderLabel = new QLabel(tr("&Vertical header:")); + verticalHeaderLabel->setBuddy(verticalHeaderCombo); + + connect(firstDayCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(firstDayChanged(int))); + connect(selectionModeCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(selectionModeChanged(int))); + connect(gridCheckBox, SIGNAL(toggled(bool)), + calendar, SLOT(setGridVisible(bool))); + connect(navigationCheckBox, SIGNAL(toggled(bool)), + calendar, SLOT(setNavigationBarVisible(bool))); + connect(horizontalHeaderCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(horizontalHeaderChanged(int))); + connect(verticalHeaderCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(verticalHeaderChanged(int))); + + QHBoxLayout *checkBoxLayout = new QHBoxLayout; + checkBoxLayout->addWidget(gridCheckBox); + checkBoxLayout->addStretch(); + checkBoxLayout->addWidget(navigationCheckBox); + + QGridLayout *outerLayout = new QGridLayout; + outerLayout->addWidget(firstDayLabel, 0, 0); + outerLayout->addWidget(firstDayCombo, 0, 1); + outerLayout->addWidget(selectionModeLabel, 1, 0); + outerLayout->addWidget(selectionModeCombo, 1, 1); + outerLayout->addLayout(checkBoxLayout, 2, 0, 1, 2); + outerLayout->addWidget(horizontalHeaderLabel, 3, 0); + outerLayout->addWidget(horizontalHeaderCombo, 3, 1); + outerLayout->addWidget(verticalHeaderLabel, 4, 0); + outerLayout->addWidget(verticalHeaderCombo, 4, 1); + generalOptionsGroupBox->setLayout(outerLayout); + + firstDayChanged(firstDayCombo->currentIndex()); + selectionModeChanged(selectionModeCombo->currentIndex()); + horizontalHeaderChanged(horizontalHeaderCombo->currentIndex()); + verticalHeaderChanged(verticalHeaderCombo->currentIndex()); +} + +void CalendarWidget::createDatesGroupBox() +{ + datesGroupBox = new QGroupBox(tr("Dates")); + + minimumDateEdit = new QDateEdit; + minimumDateEdit->setDisplayFormat("MMM d yyyy"); + minimumDateEdit->setDateRange(calendar->minimumDate(), + calendar->maximumDate()); + minimumDateEdit->setDate(calendar->minimumDate()); + + minimumDateLabel = new QLabel(tr("&Minimum Date:")); + minimumDateLabel->setBuddy(minimumDateEdit); + + currentDateEdit = new QDateEdit; + currentDateEdit->setDisplayFormat("MMM d yyyy"); + currentDateEdit->setDate(calendar->selectedDate()); + currentDateEdit->setDateRange(calendar->minimumDate(), + calendar->maximumDate()); + + currentDateLabel = new QLabel(tr("&Current Date:")); + currentDateLabel->setBuddy(currentDateEdit); + + maximumDateEdit = new QDateEdit; + maximumDateEdit->setDisplayFormat("MMM d yyyy"); + maximumDateEdit->setDateRange(calendar->minimumDate(), + calendar->maximumDate()); + maximumDateEdit->setDate(calendar->maximumDate()); + + maximumDateLabel = new QLabel(tr("Ma&ximum Date:")); + maximumDateLabel->setBuddy(maximumDateEdit); + + connect(currentDateEdit, SIGNAL(dateChanged(QDate)), + calendar, SLOT(setSelectedDate(QDate))); + connect(calendar, SIGNAL(selectionChanged()), + this, SLOT(selectedDateChanged())); + connect(minimumDateEdit, SIGNAL(dateChanged(QDate)), + this, SLOT(minimumDateChanged(QDate))); + connect(maximumDateEdit, SIGNAL(dateChanged(QDate)), + this, SLOT(maximumDateChanged(QDate))); + + QGridLayout *dateBoxLayout = new QGridLayout; + dateBoxLayout->addWidget(currentDateLabel, 1, 0); + dateBoxLayout->addWidget(currentDateEdit, 1, 1); + dateBoxLayout->addWidget(minimumDateLabel, 0, 0); + dateBoxLayout->addWidget(minimumDateEdit, 0, 1); + dateBoxLayout->addWidget(maximumDateLabel, 2, 0); + dateBoxLayout->addWidget(maximumDateEdit, 2, 1); + dateBoxLayout->setRowStretch(3, 1); + + datesGroupBox->setLayout(dateBoxLayout); +} + +void CalendarWidget::createTextFormatsGroupBox() +{ + textFormatsGroupBox = new QGroupBox(tr("Text Formats")); + + weekdayColorCombo = createColorComboBox(); + weekdayColorCombo->setCurrentIndex( + weekdayColorCombo->findText(tr("Black"))); + + weekdayColorLabel = new QLabel(tr("&Weekday color:")); + weekdayColorLabel->setBuddy(weekdayColorCombo); + + weekendColorCombo = createColorComboBox(); + weekendColorCombo->setCurrentIndex( + weekendColorCombo->findText(tr("Red"))); + + weekendColorLabel = new QLabel(tr("Week&end color:")); + weekendColorLabel->setBuddy(weekendColorCombo); + + headerTextFormatCombo = new QComboBox; + headerTextFormatCombo->addItem(tr("Bold")); + headerTextFormatCombo->addItem(tr("Italic")); + headerTextFormatCombo->addItem(tr("Plain")); + + headerTextFormatLabel = new QLabel(tr("&Header text:")); + headerTextFormatLabel->setBuddy(headerTextFormatCombo); + + firstFridayCheckBox = new QCheckBox(tr("&First Friday in blue")); + + mayFirstCheckBox = new QCheckBox(tr("May &1 in red")); + + connect(weekdayColorCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(weekdayFormatChanged())); + connect(weekendColorCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(weekendFormatChanged())); + connect(headerTextFormatCombo, SIGNAL(currentIndexChanged(QString)), + this, SLOT(reformatHeaders())); + connect(firstFridayCheckBox, SIGNAL(toggled(bool)), + this, SLOT(reformatCalendarPage())); + connect(mayFirstCheckBox, SIGNAL(toggled(bool)), + this, SLOT(reformatCalendarPage())); + + QHBoxLayout *checkBoxLayout = new QHBoxLayout; + checkBoxLayout->addWidget(firstFridayCheckBox); + checkBoxLayout->addStretch(); + checkBoxLayout->addWidget(mayFirstCheckBox); + + QGridLayout *outerLayout = new QGridLayout; + outerLayout->addWidget(weekdayColorLabel, 0, 0); + outerLayout->addWidget(weekdayColorCombo, 0, 1); + outerLayout->addWidget(weekendColorLabel, 1, 0); + outerLayout->addWidget(weekendColorCombo, 1, 1); + outerLayout->addWidget(headerTextFormatLabel, 2, 0); + outerLayout->addWidget(headerTextFormatCombo, 2, 1); + outerLayout->addLayout(checkBoxLayout, 3, 0, 1, 2); + textFormatsGroupBox->setLayout(outerLayout); + + weekdayFormatChanged(); + weekendFormatChanged(); + reformatHeaders(); + reformatCalendarPage(); +} + +QComboBox *CalendarWidget::createColorComboBox() +{ + QComboBox *comboBox = new QComboBox; + comboBox->addItem(tr("Red"), Qt::red); + comboBox->addItem(tr("Blue"), Qt::blue); + comboBox->addItem(tr("Black"), Qt::black); + comboBox->addItem(tr("Magenta"), Qt::magenta); + return comboBox; +} diff --git a/tests/manual/qlocale/calendar.h b/tests/manual/qlocale/calendar.h new file mode 100644 index 0000000..b5bb3c9 --- /dev/null +++ b/tests/manual/qlocale/calendar.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CALENDAR_H +#define CALENDAR_H + +#include <QtGui> + +class CalendarWidget : public QWidget +{ + Q_OBJECT + +public: + CalendarWidget(); + +private slots: + void localeChanged(QLocale locale); + void firstDayChanged(int index); + void selectionModeChanged(int index); + void horizontalHeaderChanged(int index); + void verticalHeaderChanged(int index); + void selectedDateChanged(); + void minimumDateChanged(const QDate &date); + void maximumDateChanged(const QDate &date); + void updateWeekendDays(); + void weekdayFormatChanged(); + void weekendFormatChanged(); + void reformatHeaders(); + void reformatCalendarPage(); + +private: + bool isWeekendDay(Qt::DayOfWeek); + void createPreviewGroupBox(); + void createGeneralOptionsGroupBox(); + void createDatesGroupBox(); + void createTextFormatsGroupBox(); + QComboBox *createColorComboBox(); + + QGroupBox *previewGroupBox; + QGridLayout *previewLayout; + QCalendarWidget *calendar; + + QGroupBox *generalOptionsGroupBox; + QLabel *localeLabel; + QLabel *firstDayLabel; + + QLabel *selectionModeLabel; + QLabel *horizontalHeaderLabel; + QLabel *verticalHeaderLabel; + QComboBox *localeCombo; + QComboBox *firstDayCombo; + QComboBox *selectionModeCombo; + QCheckBox *gridCheckBox; + QCheckBox *navigationCheckBox; + QComboBox *horizontalHeaderCombo; + QComboBox *verticalHeaderCombo; + + QGroupBox *datesGroupBox; + QLabel *currentDateLabel; + QLabel *minimumDateLabel; + QLabel *maximumDateLabel; + QDateEdit *currentDateEdit; + QDateEdit *minimumDateEdit; + QDateEdit *maximumDateEdit; + + QGroupBox *textFormatsGroupBox; + QLabel *weekdayColorLabel; + QLabel *weekendColorLabel; + QLabel *headerTextFormatLabel; + QComboBox *weekdayColorCombo; + QComboBox *weekendColorCombo; + QComboBox *headerTextFormatCombo; + + QCheckBox *firstFridayCheckBox; + QCheckBox *mayFirstCheckBox; +}; + +#endif diff --git a/tests/manual/qlocale/currency.cpp b/tests/manual/qlocale/currency.cpp new file mode 100644 index 0000000..4ef157c --- /dev/null +++ b/tests/manual/qlocale/currency.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "currency.h" + +CurrencyWidget::CurrencyWidget() +{ + QGridLayout *l = new QGridLayout; + + currencySymbolLabel = new QLabel("Symbol:"); + currencySymbol = new QLineEdit; + currencyISOLabel = new QLabel("ISO Code:"); + currencyISO = new QLineEdit; + currencyNameLabel = new QLabel("Display name:"); + currencyName = new QLineEdit; + currencyFormattingLabel = new QLabel("Currency formatting:"); + currencyFormattingValue = new QLineEdit(QString::number(1234.56, 'f', 2)); + currencyFormattingSymbolLabel = new QLabel("currency:"); + currencyFormattingSymbol = new QLineEdit; + currencyFormatting = new QLineEdit; + + currencyFormattingValue->setFixedWidth(150); + currencyFormattingSymbol->setFixedWidth(50); + + l->addWidget(currencySymbolLabel, 0, 0); + l->addWidget(currencySymbol, 0, 1, 1, 4); + l->addWidget(currencyISOLabel, 1, 0); + l->addWidget(currencyISO, 1, 1, 1, 4); + l->addWidget(currencyNameLabel, 2, 0); + l->addWidget(currencyName, 2, 1, 1, 4); + l->addWidget(currencyFormattingLabel, 3, 0); + l->addWidget(currencyFormattingValue, 3, 1); + l->addWidget(currencyFormattingSymbolLabel, 3, 2); + l->addWidget(currencyFormattingSymbol, 3, 3); + l->addWidget(currencyFormatting, 3, 4); + + QVBoxLayout *v = new QVBoxLayout(this); + v->addLayout(l); + v->addStretch(); + + connect(currencyFormattingSymbol, SIGNAL(textChanged(QString)), + this, SLOT(updateCurrencyFormatting())); + connect(currencyFormattingValue, SIGNAL(textChanged(QString)), + this, SLOT(updateCurrencyFormatting())); +} + +void CurrencyWidget::updateCurrencyFormatting() +{ + QString result; + bool ok; + QString symbol = currencyFormattingSymbol->text(); + QString value = currencyFormattingValue->text(); + int i = value.toInt(&ok); + if (ok) { + result = locale().toCurrencyString(i, symbol); + } else { + double d = value.toDouble(&ok); + if (ok) + result = locale().toCurrencyString(d, symbol); + } + currencyFormatting->setText(result); +} + +void CurrencyWidget::localeChanged(QLocale locale) +{ + setLocale(locale); + currencySymbol->setText(locale.currencySymbol()); + currencyISO->setText(locale.currencySymbol(QLocale::CurrencyIsoCode)); + currencyName->setText(locale.currencySymbol(QLocale::CurrencyDisplayName)); + updateCurrencyFormatting(); +} + diff --git a/tests/manual/qlocale/currency.h b/tests/manual/qlocale/currency.h new file mode 100644 index 0000000..3a12553 --- /dev/null +++ b/tests/manual/qlocale/currency.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CURRENCY_H +#define CURRENCY_H + +#include <QtGui> + +class CurrencyWidget : public QWidget +{ + Q_OBJECT +public: + CurrencyWidget(); + +private: + QLabel *currencySymbolLabel; + QLineEdit *currencySymbol; + QLabel *currencyISOLabel; + QLineEdit *currencyISO; + QLabel *currencyNameLabel; + QLineEdit *currencyName; + QLabel *currencyFormattingLabel; + QLineEdit *currencyFormattingValue; + QLabel *currencyFormattingSymbolLabel; + QLineEdit *currencyFormattingSymbol; + QLineEdit *currencyFormatting; + +private slots: + void localeChanged(QLocale locale); + void updateCurrencyFormatting(); +}; + +#endif diff --git a/tests/manual/qlocale/dateformats.cpp b/tests/manual/qlocale/dateformats.cpp new file mode 100644 index 0000000..25b3e7a --- /dev/null +++ b/tests/manual/qlocale/dateformats.cpp @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "dateformats.h" + +DateFormatsWidget::DateFormatsWidget() +{ + scrollArea = new QScrollArea; + scrollAreaWidget = new QWidget; + scrollArea->setWidget(scrollAreaWidget); + scrollArea->setWidgetResizable(true); + layout = new QGridLayout(scrollAreaWidget); + QVBoxLayout *l = new QVBoxLayout(this); + l->addWidget(scrollArea); + + shortDateFormat = addItem("Date format (short):"); + longDateFormat = addItem("Date format (long):"); + shortTimeFormat = addItem("Time format (short):"); + longTimeFormat = addItem("Time format (long):"); + shortDateTimeFormat = addItem("DateTime format (short):"); + longDateTimeFormat = addItem("DateTime format (long):"); + amText = addItem("Before noon:"); + pmText = addItem("After noon:"); + firstDayOfWeek = addItem("First day of week:"); + + monthNamesShort = new QComboBox; + monthNamesLong = new QComboBox; + standaloneMonthNamesShort = new QComboBox; + standaloneMonthNamesLong = new QComboBox; + dayNamesShort = new QComboBox; + dayNamesLong = new QComboBox; + standaloneDayNamesShort = new QComboBox; + standaloneDayNamesLong = new QComboBox; + + int row = layout->rowCount(); + layout->addWidget(new QLabel("Month names [short/long]:"), row, 0); + layout->addWidget(monthNamesShort, row, 1); + layout->addWidget(monthNamesLong, row, 2); + row = layout->rowCount(); + layout->addWidget(new QLabel("Standalone month names [short/long]:"), row, 0); + layout->addWidget(standaloneMonthNamesShort, row, 1); + layout->addWidget(standaloneMonthNamesLong, row, 2); + row = layout->rowCount(); + layout->addWidget(new QLabel("Day names [short/long]:"), row, 0); + layout->addWidget(dayNamesShort, row, 1); + layout->addWidget(dayNamesLong, row, 2); + row = layout->rowCount(); + layout->addWidget(new QLabel("Standalone day names [short/long]:"), row, 0); + layout->addWidget(standaloneDayNamesShort, row, 1); + layout->addWidget(standaloneDayNamesLong, row, 2); +} + +QString toString(Qt::DayOfWeek dow) +{ + static const char *names[] = { + "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + }; + return QString::fromLatin1(names[dow-1]); +} + +void DateFormatsWidget::localeChanged(QLocale locale) +{ + setLocale(locale); + QDateTime now = QDateTime::currentDateTime(); + shortDateFormat->setText(locale.toString(now.date(), QLocale::ShortFormat)); + shortDateFormat->setToolTip(locale.dateFormat(QLocale::ShortFormat)); + longDateFormat->setText(locale.toString(now.date(), QLocale::LongFormat)); + longDateFormat->setToolTip(locale.dateFormat(QLocale::LongFormat)); + shortTimeFormat->setText(locale.toString(now.time(), QLocale::ShortFormat)); + shortTimeFormat->setToolTip(locale.timeFormat(QLocale::ShortFormat)); + longTimeFormat->setText(locale.toString(now.time(), QLocale::LongFormat)); + longTimeFormat->setToolTip(locale.timeFormat(QLocale::LongFormat)); + shortDateTimeFormat->setText(locale.toString(now, QLocale::ShortFormat)); + shortDateTimeFormat->setToolTip(locale.dateTimeFormat(QLocale::ShortFormat)); + longDateTimeFormat->setText(locale.toString(now, QLocale::LongFormat)); + longDateTimeFormat->setToolTip(locale.dateTimeFormat(QLocale::LongFormat)); + amText->setText(locale.amText()); + pmText->setText(locale.pmText()); + firstDayOfWeek->setText(toString(locale.firstDayOfWeek())); + + int mns = monthNamesShort->currentIndex(); + int mnl = monthNamesLong->currentIndex(); + int smns = standaloneMonthNamesShort->currentIndex(); + int smnl = standaloneMonthNamesLong->currentIndex(); + int dnl = dayNamesLong->currentIndex(); + int dns = dayNamesShort->currentIndex(); + int sdnl = standaloneDayNamesLong->currentIndex(); + int sdns = standaloneDayNamesShort->currentIndex(); + + monthNamesShort->clear(); + monthNamesLong->clear(); + standaloneMonthNamesShort->clear(); + standaloneMonthNamesLong->clear(); + dayNamesLong->clear(); + dayNamesShort->clear(); + standaloneDayNamesLong->clear(); + standaloneDayNamesShort->clear(); + + for (int i = 1; i <= 12; ++i) + monthNamesShort->addItem(locale.monthName(i, QLocale::ShortFormat)); + monthNamesShort->setCurrentIndex(mns >= 0 ? mns : 0); + for (int i = 1; i <= 12; ++i) + monthNamesLong->addItem(locale.monthName(i, QLocale::LongFormat)); + monthNamesLong->setCurrentIndex(mnl >= 0 ? mnl : 0); + + for (int i = 1; i <= 12; ++i) + standaloneMonthNamesShort->addItem(locale.standaloneMonthName(i, QLocale::ShortFormat)); + standaloneMonthNamesShort->setCurrentIndex(smns >= 0 ? smns : 0); + for (int i = 1; i <= 12; ++i) + standaloneMonthNamesLong->addItem(locale.standaloneMonthName(i, QLocale::LongFormat)); + standaloneMonthNamesLong->setCurrentIndex(smnl >= 0 ? smnl : 0); + + for (int i = 1; i <= 7; ++i) + dayNamesLong->addItem(locale.dayName(i, QLocale::LongFormat)); + dayNamesLong->setCurrentIndex(dnl >= 0 ? dnl : 0); + for (int i = 1; i <= 7; ++i) + dayNamesShort->addItem(locale.dayName(i, QLocale::ShortFormat)); + dayNamesShort->setCurrentIndex(dns >= 0 ? dns : 0); + + for (int i = 1; i <= 7; ++i) + standaloneDayNamesLong->addItem(locale.standaloneDayName(i, QLocale::LongFormat)); + standaloneDayNamesLong->setCurrentIndex(sdnl >= 0 ? sdnl : 0); + for (int i = 1; i <= 7; ++i) + standaloneDayNamesShort->addItem(locale.standaloneDayName(i, QLocale::ShortFormat)); + standaloneDayNamesShort->setCurrentIndex(sdns >= 0 ? sdns : 0); +} + +void DateFormatsWidget::addItem(const QString &label, QWidget *w) +{ + QLabel *lbl = new QLabel(label); + int row = layout->rowCount(); + layout->addWidget(lbl, row, 0); + layout->addWidget(w, row, 1, 1, 2); +} + +QLineEdit *DateFormatsWidget::addItem(const QString &label) +{ + QLineEdit *le = new QLineEdit; + le->setReadOnly(true); + addItem(label, le); + return le; +} diff --git a/tests/manual/qlocale/dateformats.h b/tests/manual/qlocale/dateformats.h new file mode 100644 index 0000000..f05ad2a --- /dev/null +++ b/tests/manual/qlocale/dateformats.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DATEFORMATS_H +#define DATEFORMATS_H + +#include <QtGui> + +class DateFormatsWidget : public QWidget +{ + Q_OBJECT +public: + DateFormatsWidget(); + +private: + void addItem(const QString &label, QWidget *); + QLineEdit *addItem(const QString &label); + + QScrollArea *scrollArea; + QWidget *scrollAreaWidget; + QGridLayout *layout; + + QLineEdit *shortDateFormat; + QLineEdit *longDateFormat; + QLineEdit *shortTimeFormat; + QLineEdit *longTimeFormat; + QLineEdit *shortDateTimeFormat; + QLineEdit *longDateTimeFormat; + QLineEdit *amText; + QLineEdit *pmText; + QLineEdit *firstDayOfWeek; + QComboBox *monthNamesShort, *monthNamesLong; + QComboBox *standaloneMonthNamesShort, *standaloneMonthNamesLong; + QComboBox *dayNamesShort, *dayNamesLong; + QComboBox *standaloneDayNamesShort, *standaloneDayNamesLong; + +private slots: + void localeChanged(QLocale locale); +}; + +#endif diff --git a/tests/manual/qlocale/languages.cpp b/tests/manual/qlocale/languages.cpp new file mode 100644 index 0000000..18d72d7 --- /dev/null +++ b/tests/manual/qlocale/languages.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "languages.h" + +LanguagesWidget::LanguagesWidget() +{ + QVBoxLayout *l = new QVBoxLayout(this); + + languagesLabel = new QLabel("Preferred languages:"); + languagesList = new QListWidget; + + l->addWidget(languagesLabel); + l->addWidget(languagesList); + + localeChanged(QLocale()); +} + +void LanguagesWidget::localeChanged(QLocale locale) +{ + languagesList->clear(); + foreach (const QString &lang, locale.uiLanguages()) { + QListWidgetItem *item = new QListWidgetItem(lang, languagesList); + QLocale l(lang); + if (l.language() != QLocale::C) { + QString language = QLocale::languageToString(l.language()); + QString country = QLocale::countryToString(l.country()); + QString tooltip = QString(QLatin1String("%1: %2/%3")).arg(l.name(), language, country); + item->setToolTip(tooltip); + } + } +} + + diff --git a/tests/manual/qlocale/languages.h b/tests/manual/qlocale/languages.h new file mode 100644 index 0000000..18e503f --- /dev/null +++ b/tests/manual/qlocale/languages.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LANGUAGES_H +#define LANGUAGES_H + +#include <QtGui> + +class LanguagesWidget : public QWidget +{ + Q_OBJECT +public: + LanguagesWidget(); + +private: + QLocale currentLocale; + + QLabel *languagesLabel; + QListWidget *languagesList; + +private slots: + void localeChanged(QLocale locale); +}; + +#endif diff --git a/tests/manual/qlocale/main.cpp b/tests/manual/qlocale/main.cpp new file mode 100644 index 0000000..c85bd19 --- /dev/null +++ b/tests/manual/qlocale/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "window.h" + +int main(int argv, char *args[]) +{ + QApplication app(argv, args); + Window window; +#if !defined(Q_OS_SYMBIAN) + window.show(); +#else + window.showFullScreen(); +#endif + return app.exec(); +} diff --git a/tests/manual/qlocale/miscellaneous.cpp b/tests/manual/qlocale/miscellaneous.cpp new file mode 100644 index 0000000..89c80dc --- /dev/null +++ b/tests/manual/qlocale/miscellaneous.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "miscellaneous.h" + +MiscWidget::MiscWidget() +{ + QGridLayout *l = new QGridLayout; + + createLineEdit("Text to quote:", &textToQuoteLabel, &textToQuote); + createLineEdit("Standard quotes:", &standardQuotedTextLabel, &standardQuotedText); + createLineEdit("Alternate quotes:", &alternateQuotedTextLabel, &alternateQuotedText); + textToQuote->setText("some text"); + createLineEdit("Text direction:", &textDirectionLabel, &textDirection); + createLineEdit("List to separated string:", &listToSeparatedStringLabel, &listToSeparatedStringText); + + l->addWidget(textToQuoteLabel, 0, 0); + l->addWidget(textToQuote, 0, 1); + l->addWidget(standardQuotedTextLabel, 0, 2); + l->addWidget(standardQuotedText, 0, 3); + l->addWidget(alternateQuotedTextLabel, 1, 2); + l->addWidget(alternateQuotedText, 1, 3); + l->addWidget(textDirectionLabel, 2, 0); + l->addWidget(textDirection, 2, 1, 1, 3); + l->addWidget(listToSeparatedStringLabel, 3, 0); + l->addWidget(listToSeparatedStringText, 3, 1, 1, 3); + + connect(textToQuote, SIGNAL(textChanged(QString)), this, SLOT(updateQuotedText(QString))); + + QVBoxLayout *v = new QVBoxLayout(this); + v->addLayout(l); + v->addStretch(); +} + +void MiscWidget::updateQuotedText(QString str) +{ + standardQuotedText->setText(locale().quoteString(str)); + alternateQuotedText->setText(locale().quoteString(str, QLocale::AlternateQuotation)); +} + +void MiscWidget::updateListToSeparatedStringText() +{ + QStringList test; + test << "aaa" << "bbb" << "ccc" << "ddd"; + listToSeparatedStringText->setText(locale().createSeparatedList(test)); +} + +void MiscWidget::localeChanged(QLocale locale) +{ + setLocale(locale); + updateQuotedText(textToQuote->text()); + updateListToSeparatedStringText(); + textDirection->setText(locale.textDirection() == Qt::LeftToRight ? "Left To Right" : "Right To Left"); +} + +void MiscWidget::createLineEdit(const QString &label, QLabel **labelWidget, QLineEdit **lineEditWidget) +{ + QLabel *lbl = new QLabel(label); + QLineEdit *le = new QLineEdit; + le->setReadOnly(true); + lbl->setBuddy(le); + if (labelWidget) + *labelWidget = lbl; + if (lineEditWidget) + *lineEditWidget = le; +} diff --git a/tests/manual/qlocale/miscellaneous.h b/tests/manual/qlocale/miscellaneous.h new file mode 100644 index 0000000..3b635b8 --- /dev/null +++ b/tests/manual/qlocale/miscellaneous.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MISCELLANEOUS_H +#define MISCELLANEOUS_H + +#include <QtGui> + +class MiscWidget : public QWidget +{ + Q_OBJECT +public: + MiscWidget(); + +private: + void createLineEdit(const QString &label, QLabel **labelWidget = 0, QLineEdit **lineEditWidget = 0); + + QLabel *textToQuoteLabel; + QLabel *standardQuotedTextLabel; + QLabel *alternateQuotedTextLabel; + QLabel *textDirectionLabel; + QLabel *listToSeparatedStringLabel; + QLineEdit *textToQuote; + QLineEdit *standardQuotedText; + QLineEdit *alternateQuotedText; + QLineEdit *textDirection; + QLineEdit *listToSeparatedStringText; + +private slots: + void localeChanged(QLocale locale); + void updateQuotedText(QString str); + void updateListToSeparatedStringText(); +}; + +#endif // MISCELLANEOUS_H diff --git a/tests/manual/qlocale/numberformats.cpp b/tests/manual/qlocale/numberformats.cpp new file mode 100644 index 0000000..7b5fce4 --- /dev/null +++ b/tests/manual/qlocale/numberformats.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "numberformats.h" + +NumberFormatsWidget::NumberFormatsWidget() +{ + QGridLayout *l = new QGridLayout; + + QLabel *numbersLabel = new QLabel("Numbers:"); + number1 = createLineEdit(); + number2 = createLineEdit(); + number3 = createLineEdit(); + + measurementLabel = new QLabel("Measurement units:"); + measurementSystem = createLineEdit(); + + l->addWidget(numbersLabel, 0, 0); + l->addWidget(number1, 0, 1); + l->addWidget(number2, 0, 2); + l->addWidget(number3, 0, 3); + + l->addWidget(measurementLabel, 1, 0); + l->addWidget(measurementSystem, 1, 1, 1, 3); + + QVBoxLayout *v = new QVBoxLayout(this); + v->addLayout(l); + v->addStretch(); +} + +void NumberFormatsWidget::localeChanged(QLocale locale) +{ + number1->setText(locale.toString(-123456)); + number2->setText(locale.toString(1234.56, 'f', 2)); + number3->setText(locale.toString(1234.56, 'e', 4)); + + measurementSystem->setText( + locale.measurementSystem() == QLocale::ImperialSystem ? "US" : "Metric"); +} + +QLineEdit *NumberFormatsWidget::createLineEdit() +{ + QLineEdit *le = new QLineEdit; + le->setReadOnly(true); + return le; +} diff --git a/tests/manual/qlocale/numberformats.h b/tests/manual/qlocale/numberformats.h new file mode 100644 index 0000000..4a3ab36 --- /dev/null +++ b/tests/manual/qlocale/numberformats.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NUMBERFORMATS_H +#define NUMBERFORMATS_H + +#include <QtGui> + +class NumberFormatsWidget : public QWidget +{ + Q_OBJECT +public: + NumberFormatsWidget(); + +private: + QLineEdit *createLineEdit(); + + QLineEdit *number1, *number2, *number3; + QLabel *measurementLabel; + QLineEdit *measurementSystem; + +private slots: + void localeChanged(QLocale locale); +}; + +#endif diff --git a/tests/manual/qlocale/qlocale.pro b/tests/manual/qlocale/qlocale.pro new file mode 100644 index 0000000..6f0bf88 --- /dev/null +++ b/tests/manual/qlocale/qlocale.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +HEADERS += currency.h calendar.h dateformats.h numberformats.h languages.h window.h miscellaneous.h +SOURCES += currency.cpp main.cpp calendar.cpp dateformats.cpp numberformats.cpp languages.cpp window.cpp miscellaneous.cpp diff --git a/tests/manual/qlocale/window.cpp b/tests/manual/qlocale/window.cpp new file mode 100644 index 0000000..89e3ec6 --- /dev/null +++ b/tests/manual/qlocale/window.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "window.h" + +Window::Window() +{ + localeCombo = new QComboBox; + + localeCombo->addItem("System", QLocale::system()); + + QStringList locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry); + foreach (const QString &name, locales) { + QLocale locale(name); + QString label = QLocale::languageToString(locale.language()); + label += QLatin1Char('/'); + if (locale.script() != QLocale::AnyScript) { + label += QLocale::scriptToString(locale.script()); + label += QLatin1Char('/'); + } + label += QLocale::countryToString(locale.country()); + localeCombo->addItem(label, locale); + } + + connect(localeCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(localeChanged(int))); + + tabWidget = new QTabWidget; + calendar = new CalendarWidget; + connect(this, SIGNAL(localeChanged(QLocale)), calendar, SLOT(localeChanged(QLocale))); + currency = new CurrencyWidget; + connect(this, SIGNAL(localeChanged(QLocale)), currency, SLOT(localeChanged(QLocale))); + languages = new LanguagesWidget; + connect(this, SIGNAL(localeChanged(QLocale)), languages, SLOT(localeChanged(QLocale))); + dateFormats = new DateFormatsWidget; + connect(this, SIGNAL(localeChanged(QLocale)), dateFormats, SLOT(localeChanged(QLocale))); + numberFormats = new NumberFormatsWidget; + connect(this, SIGNAL(localeChanged(QLocale)), numberFormats, SLOT(localeChanged(QLocale))); + miscellaneous = new MiscWidget; + connect(this, SIGNAL(localeChanged(QLocale)), miscellaneous, SLOT(localeChanged(QLocale))); + + localeName = new QLabel("Locale: foo_BAR"); + + QWidget *w = new QWidget; + QHBoxLayout *headerLayout = new QHBoxLayout(w); + headerLayout->addWidget(localeCombo); + headerLayout->addWidget(localeName); + + QWidget *central = new QWidget; + QVBoxLayout *l = new QVBoxLayout(central); + l->addWidget(w); + l->addWidget(tabWidget); + + tabWidget->addTab(calendar, "Calendar"); + tabWidget->addTab(currency, "Currency"); + tabWidget->addTab(languages, "Languages"); + tabWidget->addTab(dateFormats, "Date Formats"); + tabWidget->addTab(numberFormats, "Number Formats"); + tabWidget->addTab(miscellaneous, "Text"); + + localeCombo->setCurrentIndex(0); + systemLocaleChanged(); + + setCentralWidget(central); +} + +void Window::systemLocaleChanged() +{ + QLocale l = QLocale::system(); + QString lang = QLocale::languageToString(l.language()); + QString script = QLocale::scriptToString(l.script()); + QString country = QLocale::countryToString(l.country()); + if (l.script() != QLocale::AnyScript) + localeCombo->setItemText(0, QString("System: %1-%2-%3").arg(lang, script, country)); + else + localeCombo->setItemText(0, QString("System: %1-%2").arg(lang, country)); + emit localeChanged(0); +} + +void Window::localeChanged(int idx) +{ + QLocale locale = localeCombo->itemData(idx).toLocale(); + localeName->setText(QString("Locale: %1 (%2)").arg(locale.bcp47Name(), locale.name())); + emit localeChanged(locale); +} + +bool Window::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::LocaleChange: { + if (localeCombo->currentIndex() == 0) + systemLocaleChanged(); + return true; + } + default: + break; + } + return QMainWindow::event(event); +} diff --git a/tests/manual/qlocale/window.h b/tests/manual/qlocale/window.h new file mode 100644 index 0000000..dfef895 --- /dev/null +++ b/tests/manual/qlocale/window.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WINDOW_H +#define WINDOW_H + +#include <QtGui> + +#include "calendar.h" +#include "currency.h" +#include "languages.h" +#include "dateformats.h" +#include "numberformats.h" +#include "miscellaneous.h" + +class Window : public QMainWindow +{ + Q_OBJECT +public: + Window(); + + QLabel *localeName; + QComboBox *localeCombo; + QTabWidget *tabWidget; + CalendarWidget *calendar; + CurrencyWidget *currency; + LanguagesWidget *languages; + DateFormatsWidget *dateFormats; + NumberFormatsWidget *numberFormats; + MiscWidget *miscellaneous; + +private: + bool event(QEvent *); + void systemLocaleChanged(); + +signals: + void localeChanged(QLocale); + +private slots: + void localeChanged(int); +}; + +#endif |