From 948bcdbc01a2c4a2df3eed187908b006f199ecc9 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 14 Aug 2015 09:36:41 +0200 Subject: Move createQmlCallableForFunction out of the binding wrapper It's now QV4::FunctionObject::createQmlFunction, which I believe is a better place and name for the method, esp. as it has no real connnection to the binding wrapper anymore. Change-Id: I59e20e120db72e53735b3a986e0b91bc7c3347d7 Reviewed-by: Simon Hausmann --- tests/auto/qml/qqmllanguage/testtypes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index 6fc4bae438..0b44daca30 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -121,7 +121,7 @@ void CustomBinding::componentComplete() QQmlContextData *context = QQmlContextData::get(qmlContext(this)); QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this))); - QV4::ScopedValue function(scope, QV4::QmlBindingWrapper::createQmlCallableForFunction(context, m_target, cdata->compilationUnit->runtimeFunctions[bindingId])); + QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, m_target, cdata->compilationUnit->runtimeFunctions[bindingId])); QQmlBinding *qmlBinding = new QQmlBinding(function, m_target, context); QQmlProperty property(m_target, name, qmlContext(this)); -- cgit v1.2.3 From ea89d156afaf7d22c069e92a1666be584f01d5ac Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 10 Sep 2015 12:35:31 +0200 Subject: Fix autotests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 35793cea28c4bd1d6d8fbae884d9ae3c19745c61 caused changes to font metrics on Mac when running our autotests. This change adjust auto tests to pass again after the change. Fix QQuickText::fontSizeMode autotests. The calculations are font dependent, and with small differences in the fonts between different OSes it's difficult to find values that work everywhere. Also fix the baseline calculations for some items that were using the wrong fonts (exchanging empty and non empty calculations). Fix language dependent differences on metrics calculations in tst_qquicktextinput. Change-Id: I7d0c7c79c8c62a4619b2f0e95ef53660b7feb782 Reviewed-by: Tor Arne Vestbø --- tests/auto/quick/qquicktext/data/fontSizeMode.qml | 4 ++-- tests/auto/quick/qquicktext/data/hAlignImplicitWidth.qml | 2 +- tests/auto/quick/qquicktext/tst_qquicktext.cpp | 10 +++++----- tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp | 6 ++++-- 4 files changed, 12 insertions(+), 10 deletions(-) (limited to 'tests') diff --git a/tests/auto/quick/qquicktext/data/fontSizeMode.qml b/tests/auto/quick/qquicktext/data/fontSizeMode.qml index 84f7ce8d50..48e7c7b6d0 100644 --- a/tests/auto/quick/qquicktext/data/fontSizeMode.qml +++ b/tests/auto/quick/qquicktext/data/fontSizeMode.qml @@ -13,10 +13,10 @@ Item { id: myText objectName: "myText" width: 250 - height: 41 + height: 35 minimumPointSize: 8 minimumPixelSize: 8 - font.pixelSize: 30 + font.pixelSize: 25 font.family: "Helvetica" } } diff --git a/tests/auto/quick/qquicktext/data/hAlignImplicitWidth.qml b/tests/auto/quick/qquicktext/data/hAlignImplicitWidth.qml index 9c9318d3cc..45255691fb 100644 --- a/tests/auto/quick/qquicktext/data/hAlignImplicitWidth.qml +++ b/tests/auto/quick/qquicktext/data/hAlignImplicitWidth.qml @@ -1,7 +1,7 @@ import QtQuick 2.0 Rectangle { - width: 200 + width: 220 height: 100 Text { diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index c1f10f9788..6042c08891 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -913,7 +913,7 @@ void tst_qquicktext::hAlignImplicitWidth() // Try to check whether alignment works by checking the number of black // pixels in the thirds of the grabbed image. - const int windowWidth = 200; + const int windowWidth = 220; const int textWidth = qCeil(text->implicitWidth()); QVERIFY2(textWidth < windowWidth, "System font too large."); const int sectionWidth = textWidth / 3; @@ -3756,8 +3756,8 @@ void tst_qquicktext::baselineOffset_data() << "hello world" << "hello
world
" << QByteArray("height: 200") - << &expectedBaselineTop - << &expectedBaselineBold; + << &expectedBaselineBold + << &expectedBaselineTop; QTest::newRow("richText") << "hello world" @@ -3852,8 +3852,8 @@ void tst_qquicktext::baselineOffset_data() << "hello world" << "hello
world
" << QByteArray("height: 200; topPadding: 10; bottomPadding: 20") - << &expectedBaselineTop - << &expectedBaselineBold; + << &expectedBaselineBold + << &expectedBaselineTop; QTest::newRow("richText with padding") << "hello world" diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index 079f73ae34..85123c6f92 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -3092,14 +3092,16 @@ void tst_qquicktextinput::cursorRectangle() } else { QCOMPARE(r.left(), input.width()); } - QVERIFY(r.top() >= line.height() - 1); + // we can't be exact here, as the space character can have a different ascent/descent from the arabic chars + // this then leads to different line heights between the wrapped and non wrapped texts + QVERIFY(r.top() >= line.height() - 5); COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r); QCOMPARE(input.positionToRectangle(11), r); for (int i = wrapPosition + 1; i < text.length(); ++i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.top() >= line.height() - 1); + QVERIFY(r.top() >= line.height() - 5); COMPARE_INPUT_METHOD_QUERY(QRectF, (&input), Qt::ImCursorRectangle, toRectF, r); QCOMPARE(input.positionToRectangle(i), r); } -- cgit v1.2.3 From 4253f11774ed113cfc69794435e7e66b373bc2cd Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Thu, 3 Sep 2015 15:55:54 +0200 Subject: Implement QQmlListModel::setData() Extending QQmlListModel by setData allows us to modify the content of the ListModel from within a delegate by doing an 'model.someProp = someValue' assignment. Change-Id: I87e4c31aca3813f099b2a4fd694beb2492a03bd0 Reviewed-by: Alan Alpert --- tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'tests') diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp index 5c252013ea..519ee7ac26 100644 --- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp +++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp @@ -125,6 +125,7 @@ private slots: void datetime(); void datetime_data(); void about_to_be_signals(); + void modify_through_delegate(); }; bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object) @@ -1427,6 +1428,36 @@ void tst_qqmllistmodel::about_to_be_signals() QCOMPARE(tester.rowsRemovedCount, 0); } +void tst_qqmllistmodel::modify_through_delegate() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData( + "import QtQuick 2.0\n" + "Item {\n" + " ListModel {\n" + " id: testModel\n" + " objectName: \"testModel\"\n" + " ListElement { name: \"Joe\"; age: 22 }\n" + " ListElement { name: \"Doe\"; age: 33 }\n" + " }\n" + " ListView {\n" + " model: testModel\n" + " delegate: Item {\n" + " Component.onCompleted: model.age = 18;\n" + " }\n" + " }\n" + "}\n", QUrl()); + + QObject *scene = component.create(); + QQmlListModel *model = scene->findChild("testModel"); + + const QHash roleNames = model->roleNames(); + + QCOMPARE(model->data(model->index(0, 0, QModelIndex()), roleNames.key("age")).toInt(), 18); + QCOMPARE(model->data(model->index(1, 0, QModelIndex()), roleNames.key("age")).toInt(), 18); +} + QTEST_MAIN(tst_qqmllistmodel) #include "tst_qqmllistmodel.moc" -- cgit v1.2.3 From da705f4036356a3203957c2a7852fa396227fc78 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 15 Sep 2015 14:20:59 +0200 Subject: Refactor TestHTTPServer. - Prefix member variables by m_. - Coding style fixes, wrap line long lines and statements. - Compile with QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII. - Introducde Qt 5 connection syntax. - Streamline code. - Use iterators for hashes. Change-Id: Ib6528220063248e09f7c19594233b7cd5940e0a8 Reviewed-by: Simon Hausmann --- tests/auto/shared/testhttpserver.cpp | 170 ++++++++++++++++++----------------- tests/auto/shared/testhttpserver.h | 21 +++-- 2 files changed, 96 insertions(+), 95 deletions(-) (limited to 'tests') diff --git a/tests/auto/shared/testhttpserver.cpp b/tests/auto/shared/testhttpserver.cpp index 7235246fc0..6c466293b6 100644 --- a/tests/auto/shared/testhttpserver.cpp +++ b/tests/auto/shared/testhttpserver.cpp @@ -81,15 +81,14 @@ The following request urls will then result in the appropriate action: \endtable */ TestHTTPServer::TestHTTPServer() -: m_state(AwaitingHeader) + : m_state(AwaitingHeader) { - QObject::connect(&server, SIGNAL(newConnection()), this, SLOT(newConnection())); - + QObject::connect(&m_server, &QTcpServer::newConnection, this, &TestHTTPServer::newConnection); } bool TestHTTPServer::listen() { - return server.listen(QHostAddress::LocalHost, 0); + return m_server.listen(QHostAddress::LocalHost, 0); } QUrl TestHTTPServer::baseUrl() const @@ -97,7 +96,7 @@ QUrl TestHTTPServer::baseUrl() const QUrl url; url.setScheme(QStringLiteral("http")); url.setHost(QStringLiteral("127.0.0.1")); - url.setPort(server.serverPort()); + url.setPort(m_server.serverPort()); return url; } @@ -113,12 +112,12 @@ QString TestHTTPServer::urlString(const QString &documentPath) const QString TestHTTPServer::errorString() const { - return server.errorString(); + return m_server.errorString(); } bool TestHTTPServer::serveDirectory(const QString &dir, Mode mode) { - dirs.append(qMakePair(dir, mode)); + m_directories.append(qMakePair(dir, mode)); return true; } @@ -128,17 +127,17 @@ bool TestHTTPServer::serveDirectory(const QString &dir, Mode mode) */ void TestHTTPServer::addAlias(const QString &filename, const QString &alias) { - aliases.insert(filename, alias); + m_aliases.insert(filename, alias); } void TestHTTPServer::addRedirect(const QString &filename, const QString &redirectName) { - redirects.insert(filename, redirectName); + m_redirects.insert(filename, redirectName); } void TestHTTPServer::registerFileNameForContentSubstitution(const QString &fileName) { - contentSubstitutedFileNames.insert(fileName); + m_contentSubstitutedFileNames.insert(fileName); } bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &body) @@ -147,19 +146,23 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod m_data.clear(); QFile expectFile(expect.toLocalFile()); - if (!expectFile.open(QIODevice::ReadOnly)) return false; + if (!expectFile.open(QIODevice::ReadOnly)) + return false; QFile replyFile(reply.toLocalFile()); - if (!replyFile.open(QIODevice::ReadOnly)) return false; + if (!replyFile.open(QIODevice::ReadOnly)) + return false; - bodyData = QByteArray(); + m_bodyData = QByteArray(); if (body.isValid()) { QFile bodyFile(body.toLocalFile()); - if (!bodyFile.open(QIODevice::ReadOnly)) return false; - bodyData = bodyFile.readAll(); + if (!bodyFile.open(QIODevice::ReadOnly)) + return false; + m_bodyData = bodyFile.readAll(); } - const QByteArray serverHostUrl = QByteArrayLiteral("127.0.0.1:") + QByteArray::number(server.serverPort()); + const QByteArray serverHostUrl + = QByteArrayLiteral("127.0.0.1:")+ QByteArray::number(m_server.serverPort()); QByteArray line; bool headers_done = false; @@ -170,10 +173,10 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod continue; } if (headers_done) { - waitData.body.append(line); + m_waitData.body.append(line); } else { line.replace("{{ServerHostUrl}}", serverHostUrl); - waitData.headers.append(line); + m_waitData.headers.append(line); } } /* @@ -181,20 +184,21 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod waitData = waitData.left(waitData.count() - 1); */ - replyData = replyFile.readAll(); + m_replyData = replyFile.readAll(); - if (!replyData.endsWith('\n')) - replyData.append("\n"); - replyData.append("Content-length: " + QByteArray::number(bodyData.length())); - replyData .append("\n\n"); + if (!m_replyData.endsWith('\n')) + m_replyData.append('\n'); + m_replyData.append("Content-length: "); + m_replyData.append(QByteArray::number(m_bodyData.length())); + m_replyData.append("\n\n"); - for (int ii = 0; ii < replyData.count(); ++ii) { - if (replyData.at(ii) == '\n' && (!ii || replyData.at(ii - 1) != '\r')) { - replyData.insert(ii, '\r'); + for (int ii = 0; ii < m_replyData.count(); ++ii) { + if (m_replyData.at(ii) == '\n' && (!ii || m_replyData.at(ii - 1) != '\r')) { + m_replyData.insert(ii, '\r'); ++ii; } } - replyData.append(bodyData); + m_replyData.append(m_bodyData); return true; } @@ -206,25 +210,27 @@ bool TestHTTPServer::hasFailed() const void TestHTTPServer::newConnection() { - QTcpSocket *socket = server.nextPendingConnection(); - if (!socket) return; + QTcpSocket *socket = m_server.nextPendingConnection(); + if (!socket) + return; - if (!dirs.isEmpty()) - dataCache.insert(socket, QByteArray()); + if (!m_directories.isEmpty()) + m_dataCache.insert(socket, QByteArray()); - QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected())); - QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead())); + QObject::connect(socket, &QAbstractSocket::disconnected, this, &TestHTTPServer::disconnected); + QObject::connect(socket, &QIODevice::readyRead, this, &TestHTTPServer::readyRead); } void TestHTTPServer::disconnected() { QTcpSocket *socket = qobject_cast(sender()); - if (!socket) return; + if (!socket) + return; - dataCache.remove(socket); - for (int ii = 0; ii < toSend.count(); ++ii) { - if (toSend.at(ii).first == socket) { - toSend.removeAt(ii); + m_dataCache.remove(socket); + for (int ii = 0; ii < m_toSend.count(); ++ii) { + if (m_toSend.at(ii).first == socket) { + m_toSend.removeAt(ii); --ii; } } @@ -235,14 +241,15 @@ void TestHTTPServer::disconnected() void TestHTTPServer::readyRead() { QTcpSocket *socket = qobject_cast(sender()); - if (!socket || socket->state() == QTcpSocket::ClosingState) return; + if (!socket || socket->state() == QTcpSocket::ClosingState) + return; - if (!dirs.isEmpty()) { + if (!m_directories.isEmpty()) { serveGET(socket, socket->readAll()); return; } - if (m_state == Failed || (waitData.body.isEmpty() && waitData.headers.count() == 0)) { + if (m_state == Failed || (m_waitData.body.isEmpty() && m_waitData.headers.count() == 0)) { qWarning() << "TestHTTPServer: Unexpected data" << socket->readAll(); return; } @@ -256,8 +263,9 @@ void TestHTTPServer::readyRead() m_data += socket->readAll(); break; } else { - if (!waitData.headers.contains(line)) { - qWarning() << "TestHTTPServer: Unexpected header:" << line << "\nExpected headers: " << waitData.headers; + if (!m_waitData.headers.contains(line)) { + qWarning() << "TestHTTPServer: Unexpected header:" << line + << "\nExpected headers: " << m_waitData.headers; m_state = Failed; socket->disconnectFromHost(); return; @@ -268,34 +276,38 @@ void TestHTTPServer::readyRead() m_data += socket->readAll(); } - if (!m_data.isEmpty() || waitData.body.isEmpty()) { - if (waitData.body != m_data) { - qWarning() << "TestHTTPServer: Unexpected data" << m_data << "\nExpected: " << waitData.body; + if (!m_data.isEmpty() || m_waitData.body.isEmpty()) { + if (m_waitData.body != m_data) { + qWarning() << "TestHTTPServer: Unexpected data" << m_data << "\nExpected: " << m_waitData.body; m_state = Failed; } else { - socket->write(replyData); + socket->write(m_replyData); } socket->disconnectFromHost(); } } -bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName) +bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileNameIn) { - if (redirects.contains(fileName)) { - QByteArray response = "HTTP/1.1 302 Found\r\nContent-length: 0\r\nContent-type: text/html; charset=UTF-8\r\nLocation: " + redirects[fileName].toUtf8() + "\r\n\r\n"; + const QString fileName = QLatin1String(fileNameIn); + if (m_redirects.contains(fileName)) { + const QByteArray response + = "HTTP/1.1 302 Found\r\nContent-length: 0\r\nContent-type: text/html; charset=UTF-8\r\nLocation: " + + m_redirects.value(fileName).toUtf8() + "\r\n\r\n"; socket->write(response); return true; } - for (int ii = 0; ii < dirs.count(); ++ii) { - QString dir = dirs.at(ii).first; - Mode mode = dirs.at(ii).second; + for (int ii = 0; ii < m_directories.count(); ++ii) { + const QString &dir = m_directories.at(ii).first; + const Mode mode = m_directories.at(ii).second; - QString dirFile = dir + QLatin1String("/") + QLatin1String(fileName); + QString dirFile = dir + QLatin1Char('/') + fileName; if (!QFile::exists(dirFile)) { - if (aliases.contains(fileName)) - dirFile = dir + QLatin1String("/") + aliases.value(fileName); + const QHash::const_iterator it = m_aliases.constFind(fileName); + if (it != m_aliases.constEnd()) + dirFile = dir + QLatin1Char('/') + it.value(); } QFile file(dirFile); @@ -305,18 +317,18 @@ bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName) return true; QByteArray data = file.readAll(); - if (contentSubstitutedFileNames.contains("/" + fileName)) { + if (m_contentSubstitutedFileNames.contains(QLatin1Char('/') + fileName)) data.replace(QByteArrayLiteral("{{ServerBaseUrl}}"), baseUrl().toString().toUtf8()); - } - QByteArray response = "HTTP/1.0 200 OK\r\nContent-type: text/html; charset=UTF-8\r\nContent-length: "; + QByteArray response + = "HTTP/1.0 200 OK\r\nContent-type: text/html; charset=UTF-8\r\nContent-length: "; response += QByteArray::number(data.count()); response += "\r\n\r\n"; response += data; if (mode == Delay) { - toSend.append(qMakePair(socket, response)); - QTimer::singleShot(500, this, SLOT(sendOne())); + m_toSend.append(qMakePair(socket, response)); + QTimer::singleShot(500, this, &TestHTTPServer::sendOne); return false; } else { socket->write(response); @@ -325,9 +337,7 @@ bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName) } } - - QByteArray response = "HTTP/1.0 404 Not found\r\nContent-type: text/html; charset=UTF-8\r\n\r\n"; - socket->write(response); + socket->write("HTTP/1.0 404 Not found\r\nContent-type: text/html; charset=UTF-8\r\n\r\n"); return true; } @@ -339,39 +349,31 @@ void TestHTTPServer::sendDelayedItem() void TestHTTPServer::sendOne() { - if (!toSend.isEmpty()) { - toSend.first().first->write(toSend.first().second); - toSend.first().first->close(); - toSend.removeFirst(); + if (!m_toSend.isEmpty()) { + m_toSend.first().first->write(m_toSend.first().second); + m_toSend.first().first->close(); + m_toSend.removeFirst(); } } void TestHTTPServer::serveGET(QTcpSocket *socket, const QByteArray &data) { - if (!dataCache.contains(socket)) + const QHash::iterator it = m_dataCache.find(socket); + if (it == m_dataCache.end()) return; - QByteArray total = dataCache[socket] + data; - dataCache[socket] = total; + QByteArray &total = it.value(); + total.append(data); if (total.contains("\n\r\n")) { - bool close = true; - if (total.startsWith("GET /")) { - - int space = total.indexOf(' ', 4); - if (space != -1) { - - QByteArray req = total.mid(5, space - 5); - close = reply(socket, req); - - } + const int space = total.indexOf(' ', 4); + if (space != -1) + close = reply(socket, total.mid(5, space - 5)); } - dataCache.remove(socket); - + m_dataCache.erase(it); if (close) socket->disconnectFromHost(); } } - diff --git a/tests/auto/shared/testhttpserver.h b/tests/auto/shared/testhttpserver.h index 0c0e799d8e..0fc8e4a79c 100644 --- a/tests/auto/shared/testhttpserver.h +++ b/tests/auto/shared/testhttpserver.h @@ -34,7 +34,6 @@ #ifndef TESTHTTPSERVER_H #define TESTHTTPSERVER_H -#include #include #include #include @@ -81,24 +80,24 @@ private: void serveGET(QTcpSocket *, const QByteArray &); bool reply(QTcpSocket *, const QByteArray &); - QList > dirs; - QHash dataCache; - QList > toSend; - QSet contentSubstitutedFileNames; + QList > m_directories; + QHash m_dataCache; + QList > m_toSend; + QSet m_contentSubstitutedFileNames; struct WaitData { QList headers; QByteArray body; - } waitData; - QByteArray replyData; - QByteArray bodyData; + } m_waitData; + QByteArray m_replyData; + QByteArray m_bodyData; QByteArray m_data; State m_state; - QHash aliases; - QHash redirects; + QHash m_aliases; + QHash m_redirects; - QTcpServer server; + QTcpServer m_server; }; #endif // TESTHTTPSERVER_H -- cgit v1.2.3 From c5b083b2a256823f4f47fcaa3140d4f79d99029f Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 4 Sep 2015 13:32:55 +0200 Subject: ListView: Set currentItem's culled state on geometry change When the viewport is moved, the ListView may cull its currentItem if it's out of the viewport bounds. However, it could be that this is only a transient state while the currentItem is being animated. Unfortunately, we don't uncull the currentItem at any moment during the animation. To solve this, we simply set the currentItem's culled state every time its geometry changes. Change-Id: I72d548f13f229029ccd8568721ea23e73f7b4392 Task-number: QTBUG-48044 Reviewed-by: J-P Nurmi --- .../auto/quick/qquicklistview/data/qtbug48044.qml | 144 +++++++++++++++++++++ .../quick/qquicklistview/tst_qquicklistview.cpp | 37 ++++++ 2 files changed, 181 insertions(+) create mode 100644 tests/auto/quick/qquicklistview/data/qtbug48044.qml (limited to 'tests') diff --git a/tests/auto/quick/qquicklistview/data/qtbug48044.qml b/tests/auto/quick/qquicklistview/data/qtbug48044.qml new file mode 100644 index 0000000000..d318643c1c --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/qtbug48044.qml @@ -0,0 +1,144 @@ +import QtQuick 2.0 + +Item { + width: 200 + height: 442 + + ListModel { + id: listModel + ListElement { + name: "h1" + txt: "Header 1" + header: true + collapsed: true + } + ListElement { + name: "h2" + txt: "Header 2" + header: true + collapsed: true + } + ListElement { + name: "h3" + txt: "Header 3" + header: true + collapsed: true + } + + function indexFromName(name) { + for (var i = 0; i < count; i++) + if (get(i).name === name) + return i + + console.warn("Did not find index for name " + name) + return -1 + } + } + + function populateModel(prefix, index, n) { + for (var k = 1; k <= n; k++) { + var name = prefix + k + var data = { + "collapsed": false, + "name": name, + "txt": name, + "header": false + } + listModel.insert(index + k, data) + } + } + + function h2(open) { + var i = listModel.indexFromName("h2") + if (listModel.get(i).collapsed === !open) + return + + listModel.setProperty(i, "collapsed", !open) + + var n = 15 + if (open) { + h3(false) + populateModel("c2_", listModel.indexFromName("h2"), n) + } else { + listModel.remove(i + 1, n) + } + + } + + function h3(open) { + var i = listModel.indexFromName("h3") + if (listModel.get(i).collapsed === !open) + return + + listModel.setProperty(i, "collapsed", !open) + + var n = 6 + if (open) { + h2(false) + populateModel("c3_", listModel.indexFromName("h3"), n) + } else { + listModel.remove(i + 1, n) + } + } + + ListView { + id: listView + width: parent.width + height: parent.height + cacheBuffer: 0 + model: listModel + + property bool transitionsDone: false + property int runningTransitions: 0 + onRunningTransitionsChanged: { + if (runningTransitions === 0) + transitionsDone = true + } + + displaced: Transition { + id: dispTrans + SequentialAnimation { + ScriptAction { + script: listView.runningTransitions++ + } + NumberAnimation { + property: "y"; + duration: 250 + } + ScriptAction { + script: listView.runningTransitions-- + } + } + } + + delegate: Rectangle { + id: rect + color: header ? "yellow" : "cyan" + border.color: "black" + height: 50 + width: parent.width + + Text { + anchors.centerIn: parent + font.pixelSize: 20 + text: txt + } + + MouseArea { + anchors.fill: parent + onClicked: { + listView.currentIndex = index + var i = listModel.indexFromName("h3") + if (i === -1) + return; + var isCollapsed = listModel.get(i).collapsed + if (name === "h2") + h2(isCollapsed) + else if (name === "h3") + h3(isCollapsed) + } + } + } + } +} + diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 8e7f93849c..e02c053208 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -247,6 +247,8 @@ private slots: void contentHeightWithDelayRemove(); void contentHeightWithDelayRemove_data(); + void QTBUG_48044_currentItemNotVisibleAfterTransition(); + private: template void items(const QUrl &source); template void changed(const QUrl &source); @@ -8231,6 +8233,41 @@ void tst_QQuickListView::contentHeightWithDelayRemove() delete window; } +void tst_QQuickListView::QTBUG_48044_currentItemNotVisibleAfterTransition() +{ + QQuickView *window = createView(); + window->setSource(testFileUrl("qtbug48044.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QQuickListView *listview = window->rootObject()->findChild(); + QTRY_VERIFY(listview != 0); + + // Expand 2nd header + listview->setProperty("transitionsDone", QVariant(false)); + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, 75)); + QTRY_VERIFY(listview->property("transitionsDone").toBool()); + + // Flick listview to the bottom + flick(window, QPoint(window->width() / 2, 400), QPoint(window->width() / 2, 0), 100); + QTRY_VERIFY(!listview->isMoving()); + + // Expand 3rd header + listview->setProperty("transitionsDone", QVariant(false)); + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() - 25)); + QTRY_VERIFY(listview->property("transitionsDone").toBool()); + + // Check current item is what we expect + QCOMPARE(listview->currentIndex(), 2); + QQuickItem *currentItem = listview->currentItem(); + QVERIFY(currentItem); + QVERIFY(currentItem->isVisible()); + + // This is the actual test + QQuickItemPrivate *currentPriv = QQuickItemPrivate::get(currentItem); + QVERIFY(!currentPriv->culled); +} + QTEST_MAIN(tst_QQuickListView) #include "tst_qquicklistview.moc" -- cgit v1.2.3 From 8614d4d8362e2fbc56f6b027d310a0d8f11a212f Mon Sep 17 00:00:00 2001 From: Nobuaki Sukegawa Date: Sun, 20 Sep 2015 12:16:34 +0900 Subject: Add DataView unsigned integer getter/setters with correct casings According to the spec, unsigned integer getter/setters should be cased "Uint". http://www.ecma-international.org/ecma-262/6.0/#sec-dataview.prototype.getuint8 For backword compatibility, this diff does not remove mis-cased methods. Change-Id: I8e65dca12b8358376dbb3c519246c8abca0d47b0 Reviewed-by: Lars Knoll --- tests/manual/v4/typedarrays.js | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/manual/v4/typedarrays.js b/tests/manual/v4/typedarrays.js index d52fd6bab0..8cf2b8c75a 100644 --- a/tests/manual/v4/typedarrays.js +++ b/tests/manual/v4/typedarrays.js @@ -51,11 +51,13 @@ function assertTrue(b) { throw "assertTrue failed:" + b } -function assertEquals(a, b) { +function assertEquals(a, b, delta) { if (isNaN(a) && isNaN(b)) return - if (a !== b) + if (!delta && a !== b) throw "assertEquals failed:" + a + "!==" + b + else if (Math.abs(a - b) > delta) + throw "assertEquals failed: Math.abs(" + a + " - " + b + ") > " + delta } function assertArrayEquals(a, b) @@ -700,9 +702,36 @@ function TestDataViewPropertyTypeChecks() { CheckProperty("byteLength"); } - TestDataViewPropertyTypeChecks(); +function TestDataGetterSetters() { + var a = new DataView(new ArrayBuffer(16)); + function TestGetterSetter(size, name, value0, value1, delta1, delta2) { + var getter = 'get' + name; + var setter = 'set' + name; + a[setter](0, value0); + a[setter](size, value1); + assertEquals(value0, a[getter](0), delta1); + assertEquals(value1, a[getter](size), delta2); + } + + TestGetterSetter(1, 'Int8', 111, -100); + TestGetterSetter(2, 'Int16', 31111, -30000); + TestGetterSetter(4, 'Int32', 2111111111, -2000000000); + TestGetterSetter(1, 'Uint8', 111, 200); + TestGetterSetter(2, 'Uint16', 31111, 60000); + TestGetterSetter(4, 'Uint32', 2111111111, 4000000000); + TestGetterSetter(4, 'Float32', Math.pow(10, 38), Math.pow(10, -38), Math.pow(10, 31), Math.pow(10, -45)); + TestGetterSetter(8, 'Float64', Math.pow(10, 308), Math.pow(10, -293), Math.pow(10, 293), Math.pow(10, -308)); + + // Backword compatibility + TestGetterSetter(1, 'UInt8', 111, 200); + TestGetterSetter(2, 'UInt16', 31111, 60000); + TestGetterSetter(4, 'UInt32', 2111111111, 4000000000); +} + +TestDataGetterSetters(); + // General tests for properties // Test property attribute [[Enumerable]] -- cgit v1.2.3 From 0f29340a10b9638666ded939b4f6bf3d891f1320 Mon Sep 17 00:00:00 2001 From: Dan Cape Date: Thu, 13 Aug 2015 14:59:52 -0400 Subject: TextEdit: selectedTextChanged not emitted when calling select 2nd time qquicktextcontrol was only checking if the text was previous selected or not and if the current state matched the previous state it would not dispatch a selectedTextChanged event. This is wrong if you programmatically select text a second time with a different start or end of selection. You must notify that the selected text changed since visually you can see the highlight changed locations. When correcting this and creating a test case, it was seen that other tests had QEXPECT_FAIL set for this specific case. Upon further inspection, I could remove those calls and adjust the expected data that was set before the test (changing false to true). testing of tst_qquicktext: Totals: 182 passed, 0 failed, 0 skipped, 0 blacklisted testing of tst_qquicktextedit: Totals: 354 passed, 0 failed, 3 skipped, 0 blacklisted Task-number: QTBUG-38704 Change-Id: Ib5244dc264ab76951bb722a31dcb64717282725a Reviewed-by: J-P Nurmi --- .../quick/qquicktextedit/tst_qquicktextedit.cpp | 40 ++++++++++++++-------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'tests') diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 5ec8fa2e83..eda3be5c1d 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -201,6 +201,7 @@ private slots: void emptytags_QTBUG_22058(); void cursorRectangle_QTBUG_38947(); void textCached_QTBUG_41583(); + void doubleSelect_QTBUG_38704(); void padding(); @@ -4044,7 +4045,7 @@ void tst_qquicktextedit::append_data() << QString("Hello") << standard.at(0) + QString("\nHello") << 18 << standard.at(0).length() + 6 << standard.at(0).length() + 6 - << false << true; + << true << true; QTest::newRow("reversed selection kept intact") << standard.at(0) << QQuickTextEdit::PlainText @@ -4126,11 +4127,8 @@ void tst_qquicktextedit::append() if (selectionStart > selectionEnd) qSwap(selectionStart, selectionEnd); - QEXPECT_FAIL("into selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue); - QEXPECT_FAIL("into reversed selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue); QCOMPARE(selectionSpy.count() > 0, selectionChanged); QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart); - QEXPECT_FAIL("into reversed selection", "selectionEndChanged signal not emitted", Continue); QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd); QCOMPARE(textSpy.count() > 0, text != expectedText); QCOMPARE(cursorPositionSpy.count() > 0, cursorPositionChanged); @@ -4213,7 +4211,7 @@ void tst_qquicktextedit::insert_data() << QString("Hello") << QString("Hello") + standard.at(0) << 19 << 24 << 24 - << false << true; + << true << true; QTest::newRow("before reversed selection") << standard.at(0) << QQuickTextEdit::PlainText @@ -4221,7 +4219,7 @@ void tst_qquicktextedit::insert_data() << QString("Hello") << QString("Hello") + standard.at(0) << 19 << 24 << 19 - << false << true; + << true << true; QTest::newRow("after selection") << standard.at(0) << QQuickTextEdit::PlainText @@ -4344,11 +4342,8 @@ void tst_qquicktextedit::insert() if (selectionStart > selectionEnd) qSwap(selectionStart, selectionEnd); - QEXPECT_FAIL("into selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue); - QEXPECT_FAIL("into reversed selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue); QCOMPARE(selectionSpy.count() > 0, selectionChanged); QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart); - QEXPECT_FAIL("into reversed selection", "selectionEndChanged signal not emitted", Continue); QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd); QCOMPARE(textSpy.count() > 0, text != expectedText); QCOMPARE(cursorPositionSpy.count() > 0, cursorPositionChanged); @@ -4458,7 +4453,7 @@ void tst_qquicktextedit::remove_data() << 0 << 5 << standard.at(0).mid(5) << 9 << 14 << 14 - << false << true; + << true << true; QTest::newRow("before reversed selection") << standard.at(0) << QQuickTextEdit::PlainText @@ -4466,7 +4461,7 @@ void tst_qquicktextedit::remove_data() << 0 << 5 << standard.at(0).mid(5) << 9 << 14 << 9 - << false << true; + << true << true; QTest::newRow("after selection") << standard.at(0) << QQuickTextEdit::PlainText @@ -4588,11 +4583,8 @@ void tst_qquicktextedit::remove() QCOMPARE(textEdit->selectionEnd(), expectedSelectionEnd); QCOMPARE(textEdit->cursorPosition(), expectedCursorPosition); - QEXPECT_FAIL("from selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue); - QEXPECT_FAIL("from reversed selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue); QCOMPARE(selectionSpy.count() > 0, selectionChanged); QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart); - QEXPECT_FAIL("from reversed selection", "selectionEndChanged signal not emitted", Continue); QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd); QCOMPARE(textSpy.count() > 0, text != expectedText); @@ -5374,6 +5366,26 @@ void tst_qquicktextedit::textCached_QTBUG_41583() QVERIFY(!textedit->property("empty").toBool()); } +void tst_qquicktextedit::doubleSelect_QTBUG_38704() +{ + QString componentStr = "import QtQuick 2.2\nTextEdit { text: \"TextEdit\" }"; + QQmlComponent textEditComponent(&engine); + textEditComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextEdit *textEdit = qobject_cast(textEditComponent.create()); + QVERIFY(textEdit != 0); + + QSignalSpy selectionSpy(textEdit, SIGNAL(selectedTextChanged())); + + textEdit->select(0,1); //Select some text initially + QCOMPARE(selectionSpy.count(), 1); + textEdit->select(0,1); //No change to selection start/end + QCOMPARE(selectionSpy.count(), 1); + textEdit->select(0,2); //Change selection end + QCOMPARE(selectionSpy.count(), 2); + textEdit->select(1,2); //Change selection start + QCOMPARE(selectionSpy.count(), 3); +} + void tst_qquicktextedit::padding() { QScopedPointer window(new QQuickView); -- cgit v1.2.3 From b7738beda651c2927e1a9d58c592148b1dc99576 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 14 Sep 2015 21:23:32 +0200 Subject: Make QML composite types inherit enums Problem: in Qt Quick Controls 2, enums declared in the abstract C++ base types were not accessible with the concrete QML type name, but had to be referenced using the base type name: Slider { snapMode: AbstractSlider.SnapOnRelease } Solution: this change resolves the C++ base type and creates the missing link between the composite type and its base type's meta- object. This allows referencing enums using the concrete/composite QML type name: Slider { snapMode: Slider.SnapOnRelease } Change-Id: Icefdec91b012b12728367fd54b4d16796233ee12 Task-number: QTBUG-43582 Reviewed-by: Simon Hausmann --- .../qml/qqmllanguage/data/CompositeTypeWithEnum.qml | 4 ++++ .../data/registeredCompositeTypeWithEnum.qml | 6 ++++++ tests/auto/qml/qqmllanguage/testtypes.cpp | 2 ++ tests/auto/qml/qqmllanguage/testtypes.h | 11 +++++++++++ tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 17 +++++++++++++++++ 5 files changed, 40 insertions(+) create mode 100644 tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnum.qml create mode 100644 tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml (limited to 'tests') diff --git a/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnum.qml b/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnum.qml new file mode 100644 index 0000000000..6a14e72a31 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnum.qml @@ -0,0 +1,4 @@ +import Test 1.0 + +MyCompositeBaseType { +} diff --git a/tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml b/tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml new file mode 100644 index 0000000000..5f8c11e5f6 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/registeredCompositeTypeWithEnum.qml @@ -0,0 +1,6 @@ +import Test 1.0 + +RegisteredCompositeTypeWithEnum { + property int enumValue0: RegisteredCompositeTypeWithEnum.EnumValue0 + property int enumValue42: RegisteredCompositeTypeWithEnum.EnumValue42 +} diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index 0b44daca30..95a98788c3 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -91,6 +91,8 @@ void registerTypes() qmlRegisterCustomExtendedType("Test", 1, 0, "SimpleExtendedObjectWithCustomParser", new SimpleObjectCustomParser); qmlRegisterType("Test", 1, 0, "RootObjectInCreationTester"); + + qmlRegisterType("Test", 1, 0, "MyCompositeBaseType"); } QVariant myCustomVariantTypeConverter(const QString &data) diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index b8792a892f..985acc2539 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -1079,9 +1079,19 @@ class MyEnumDerivedClass : public MyEnum2Class Q_OBJECT }; +class MyCompositeBaseType : public QObject +{ + Q_OBJECT + Q_ENUMS(CompositeEnum) + +public: + enum CompositeEnum { EnumValue0, EnumValue42 = 42 }; +}; + Q_DECLARE_METATYPE(MyEnum2Class::EnumB) Q_DECLARE_METATYPE(MyEnum1Class::EnumA) Q_DECLARE_METATYPE(Qt::TextFormat) +Q_DECLARE_METATYPE(MyCompositeBaseType::CompositeEnum) QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered) QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered) @@ -1089,6 +1099,7 @@ QML_DECLARE_TYPE(MyRevisionedClass) QML_DECLARE_TYPE(MyRevisionedSubclass) QML_DECLARE_TYPE(MySubclass) QML_DECLARE_TYPE(MyReceiversTestObject) +QML_DECLARE_TYPE(MyCompositeBaseType) class CustomBinding : public QObject, public QQmlParserStatus { diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 97501118dd..b48f3640f4 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -159,6 +159,7 @@ private slots: void readonlyObjectProperties(); void receivers(); void registeredCompositeType(); + void registeredCompositeTypeWithEnum(); void implicitImportsLast(); void basicRemote_data(); @@ -3174,6 +3175,7 @@ void tst_qqmllanguage::initTestCase() qmlRegisterType(testFileUrl("CompositeType.qml"), "Test", 1, 0, "RegisteredCompositeType"); qmlRegisterType(testFileUrl("CompositeType.DoesNotExist.qml"), "Test", 1, 0, "RegisteredCompositeType2"); qmlRegisterType(testFileUrl("invalidRoot.1.qml"), "Test", 1, 0, "RegisteredCompositeType3"); + qmlRegisterType(testFileUrl("CompositeTypeWithEnum.qml"), "Test", 1, 0, "RegisteredCompositeTypeWithEnum"); // Registering the TestType class in other modules should have no adverse effects qmlRegisterType("org.qtproject.TestPre", 1, 0, "Test"); @@ -3350,6 +3352,21 @@ void tst_qqmllanguage::registeredCompositeType() delete o; } +// QTBUG-43582 +void tst_qqmllanguage::registeredCompositeTypeWithEnum() +{ + QQmlComponent component(&engine, testFileUrl("registeredCompositeTypeWithEnum.qml")); + + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("enumValue0").toInt(), static_cast(MyCompositeBaseType::EnumValue0)); + QCOMPARE(o->property("enumValue42").toInt(), static_cast(MyCompositeBaseType::EnumValue42)); + + delete o; +} + // QTBUG-18268 void tst_qqmllanguage::remoteLoadCrash() { -- cgit v1.2.3 From 833c99db20a6ccbf337d77855098141e008b04ee Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 26 Aug 2015 16:40:11 +0200 Subject: Inline property data into the object Append the part of the objects property data that is known ad instantiation time to the object itself and by that avoid creating a separate MemberData. Saves some memory and should speed up object creation. Currently implemented only for Object and ArrayObject. Change-Id: I7693bf2f3a28fb718522398ebb94ac115e021fa4 Reviewed-by: Simon Hausmann --- tests/manual/v4/crypto.js | 1 + 1 file changed, 1 insertion(+) (limited to 'tests') diff --git a/tests/manual/v4/crypto.js b/tests/manual/v4/crypto.js index cd48bdb019..7c24b08439 100644 --- a/tests/manual/v4/crypto.js +++ b/tests/manual/v4/crypto.js @@ -1710,3 +1710,4 @@ if (typeof(print) === "undefined") print = console.log; print("done in", new Date - d1) +gc() -- cgit v1.2.3 From a9276971aa8018837b23a847b5dee3b63b39232e Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 21 Sep 2015 13:27:46 +0200 Subject: Use V4 double-to-string conversion instead of QVariant's V4's version makes an effort to find the shortest possible representation, which QVariant doesn't do. Task-number: QTBUG-47070 Change-Id: I49ce130020496592325074e0db29a6984ee7649a Reviewed-by: Simon Hausmann --- .../qqmlproperty/data/floatToStringPrecision.qml | 10 ++++++++++ tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml (limited to 'tests') diff --git a/tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml b/tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml new file mode 100644 index 0000000000..a0429e0cc8 --- /dev/null +++ b/tests/auto/qml/qqmlproperty/data/floatToStringPrecision.qml @@ -0,0 +1,10 @@ +import QtQuick 2.0 + +QtObject { + property double a: 3.4 + property string b: a + + property double c: 0.035003945 + property string d: c +} + diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index d6b1c86b88..6ada14ce79 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -147,6 +147,7 @@ private slots: void registeredCompositeTypeProperty(); void deeplyNestedObject(); void readOnlyDynamicProperties(); + void floatToStringPrecision(); void copy(); private: @@ -2054,6 +2055,27 @@ void tst_qqmlproperty::readOnlyDynamicProperties() delete obj; } +void tst_qqmlproperty::floatToStringPrecision() +{ + QQmlComponent comp(&engine, testFileUrl("floatToStringPrecision.qml")); + QObject *obj = comp.create(); + QVERIFY(obj != 0); + + QCOMPARE(obj->property("a").toDouble(), 3.4); + QEXPECT_FAIL("", "QVariant's double-to-string conversion is worse than V4's.", Continue); + QCOMPARE(obj->property("a").toString(), QLatin1String("3.4")); + QCOMPARE(obj->property("b").toDouble(), 3.4); + QCOMPARE(obj->property("b").toString(), QLatin1String("3.4")); + + QCOMPARE(obj->property("c").toDouble(), 0.035003945); + QEXPECT_FAIL("", "QVariant's double-to-string conversion is worse than V4's.", Continue); + QCOMPARE(obj->property("c").toString(), QLatin1String("0.035003945")); + QCOMPARE(obj->property("d").toDouble(), 0.035003945); + QCOMPARE(obj->property("d").toString(), QLatin1String("0.035003945")); + + delete obj; +} + void tst_qqmlproperty::initTestCase() { QQmlDataTest::initTestCase(); -- cgit v1.2.3 From 61ce37de40711ef2d4a6b4989d8183e1711fc47d Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Thu, 24 Sep 2015 10:24:20 +0200 Subject: Improve warning for QtQml.Binding Print a warning if there is no property with the given name of the specified target object, or the property is read-only. Change-Id: I5dc2e8330fb1ce53be396b7bf5baf13c1702d2f4 Task-number: QTBUG-39243 Reviewed-by: Simon Hausmann --- .../auto/qml/qqmlbinding/data/readonlyProperty.qml | 13 +++++++++ .../auto/qml/qqmlbinding/data/unknownProperty.qml | 11 +++++++ tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp | 34 ++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 tests/auto/qml/qqmlbinding/data/readonlyProperty.qml create mode 100644 tests/auto/qml/qqmlbinding/data/unknownProperty.qml (limited to 'tests') diff --git a/tests/auto/qml/qqmlbinding/data/readonlyProperty.qml b/tests/auto/qml/qqmlbinding/data/readonlyProperty.qml new file mode 100644 index 0000000000..fa8d93d355 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/readonlyProperty.qml @@ -0,0 +1,13 @@ +import QtQuick 2.0 + +Item { + id: root + + readonly property string name: "John" + + Binding { + target: root + property: "name" + value: "Doe" + } +} diff --git a/tests/auto/qml/qqmlbinding/data/unknownProperty.qml b/tests/auto/qml/qqmlbinding/data/unknownProperty.qml new file mode 100644 index 0000000000..36157bb4e7 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/unknownProperty.qml @@ -0,0 +1,11 @@ +import QtQuick 2.0 + +Item { + id: root + + Binding { + target: root + property: "unknown" + value: 42 + } +} diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp index 2d267cc668..3e49f3b3c4 100644 --- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp +++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp @@ -50,6 +50,8 @@ private slots: void restoreBindingWithLoop(); void restoreBindingWithoutCrash(); void deletedObject(); + void warningOnUnknownProperty(); + void warningOnReadOnlyProperty(); private: QQmlEngine engine; @@ -224,6 +226,38 @@ void tst_qqmlbinding::deletedObject() delete rect; } +void tst_qqmlbinding::warningOnUnknownProperty() +{ + QQmlTestMessageHandler messageHandler; + + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("unknownProperty.qml")); + QQuickItem *item = qobject_cast(c.create()); + QVERIFY(item); + delete item; + + QCOMPARE(messageHandler.messages().count(), 1); + + const QString expectedMessage = c.url().toString() + QLatin1String(":6:5: QML Binding: Property 'unknown' does not exist on Item."); + QCOMPARE(messageHandler.messages().first(), expectedMessage); +} + +void tst_qqmlbinding::warningOnReadOnlyProperty() +{ + QQmlTestMessageHandler messageHandler; + + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("readonlyProperty.qml")); + QQuickItem *item = qobject_cast(c.create()); + QVERIFY(item); + delete item; + + QCOMPARE(messageHandler.messages().count(), 1); + + const QString expectedMessage = c.url().toString() + QLatin1String(":8:5: QML Binding: Property 'name' on Item is read-only."); + QCOMPARE(messageHandler.messages().first(), expectedMessage); +} + QTEST_MAIN(tst_qqmlbinding) #include "tst_qqmlbinding.moc" -- cgit v1.2.3 From c47dacde0ba4a97f5eed9dc345f8c1450000082f Mon Sep 17 00:00:00 2001 From: Ron Hashimoto Date: Tue, 12 May 2015 11:22:26 +0900 Subject: V4: Fix SparseArray::deleteNode SparseArray::deleteNode should modify size_left only if the deleted node had a right child Change-Id: I0f3504a5c6568dbd9e392bf83eaf3f9780eb2b84 Task-number: QTBUG-46022 Reviewed-by: Simon Hausmann --- tests/auto/qml/qqmlecmascript/data/qtbug_46022.js | 21 +++++++++++++++++++++ tests/auto/qml/qqmlecmascript/data/qtbug_46022.qml | 7 +++++++ .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 11 +++++++++++ 3 files changed, 39 insertions(+) create mode 100644 tests/auto/qml/qqmlecmascript/data/qtbug_46022.js create mode 100644 tests/auto/qml/qqmlecmascript/data/qtbug_46022.qml (limited to 'tests') diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_46022.js b/tests/auto/qml/qqmlecmascript/data/qtbug_46022.js new file mode 100644 index 0000000000..385d7f9e97 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/qtbug_46022.js @@ -0,0 +1,21 @@ +var obj = {} +obj[5289] = 0 +obj[5290] = 0 +obj[5288] = 0 +obj[5287] = 0 +delete obj[5288] + +var a = Object.getOwnPropertyNames(obj) +var test1 = a.every(function(key) { + return obj.hasOwnProperty(key) +}) + +obj = {} +obj[8187] = 0 +obj[8188] = 0 +delete obj[8187] + +var b = Object.getOwnPropertyNames(obj) +var test2 = b.every(function(key) { + return obj.hasOwnProperty(key) +}) diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_46022.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_46022.qml new file mode 100644 index 0000000000..2d2375de3e --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/qtbug_46022.qml @@ -0,0 +1,7 @@ +import "qtbug_46022.js" as Test +import QtQuick 2.0 + +QtObject { + property bool test1: Test.test1 + property bool test2: Test.test2 +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 222e594d1a..8fc79719d5 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -326,6 +326,7 @@ private slots: void readUnregisteredQObjectProperty(); void writeUnregisteredQObjectProperty(); void switchExpression(); + void qtbug_46022(); private: // static void propertyVarWeakRefCallback(v8::Persistent object, void* parameter); @@ -7878,6 +7879,16 @@ void tst_qqmlecmascript::switchExpression() QCOMPARE(v.toBool(), true); } +void tst_qqmlecmascript::qtbug_46022() +{ + QQmlComponent component(&engine, testFileUrl("qtbug_46022.qml")); + + QScopedPointer obj(component.create()); + QVERIFY(obj != 0); + QCOMPARE(obj->property("test1").toBool(), true); + QCOMPARE(obj->property("test2").toBool(), true); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" -- cgit v1.2.3