aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp9
-rw-r--r--tests/auto/qml/qqmlecmascript/data/sequenceConversion.array.qml37
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.cpp60
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h45
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp28
-rw-r--r--tests/auto/qmltest/listview/tst_listview.qml41
-rw-r--r--tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp2
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp9
-rw-r--r--tests/auto/quick/qquickitem2/data/keysforward.qml6
-rw-r--r--tests/auto/quick/qquicklistview/data/layoutChangeSort.qml58
-rw-r--r--tests/auto/quick/qquicklistview/data/simplelistview.qml11
-rw-r--r--tests/auto/quick/qquicklistview/qquicklistview.pro7
-rw-r--r--tests/auto/quick/qquicklistview/randomsortmodel.cpp107
-rw-r--r--tests/auto/quick/qquicklistview/randomsortmodel.h64
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp102
-rw-r--r--tests/auto/quick/qquickpathview/data/changePathDuringRefill.qml45
-rw-r--r--tests/auto/quick/qquickpathview/data/incorrectSteal.qml85
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp98
-rw-r--r--tests/auto/quick/qquickwindow/data/unloadSubWindow.qml22
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp23
20 files changed, 845 insertions, 14 deletions
diff --git a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
index 26919af1b6..f91d0135a9 100644
--- a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
+++ b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
@@ -84,10 +84,15 @@ void tst_QPacketProtocol::init()
QVERIFY(m_server->listen(QHostAddress("127.0.0.1")));
m_client = new QTcpSocket(this);
+
+ QSignalSpy serverSpy(m_server, SIGNAL(newConnection()));
+ QSignalSpy clientSpy(m_client, SIGNAL(connected()));
+
m_client->connectToHost(m_server->serverAddress(), m_server->serverPort());
- QVERIFY(m_client->waitForConnected());
- QVERIFY(m_server->waitForNewConnection(10000));
+ QVERIFY(clientSpy.count() > 0 || clientSpy.wait());
+ QVERIFY(serverSpy.count() > 0 || serverSpy.wait());
+
m_serverConn = m_server->nextPendingConnection();
}
diff --git a/tests/auto/qml/qqmlecmascript/data/sequenceConversion.array.qml b/tests/auto/qml/qqmlecmascript/data/sequenceConversion.array.qml
index 8847055a70..5103168fd3 100644
--- a/tests/auto/qml/qqmlecmascript/data/sequenceConversion.array.qml
+++ b/tests/auto/qml/qqmlecmascript/data/sequenceConversion.array.qml
@@ -165,6 +165,43 @@ Item {
}
}
}
+
+ // unshift
+ msco.stringListProperty = [ "one", "two" ]
+ var unshiftedVal = msco.stringListProperty.unshift("zero")
+ expected = [ "zero", "one", "two" ]
+ if (msco.stringListProperty.toString() != expected.toString()) success = false;
+ expected = 3
+ if (msco.stringListProperty.length != expected) success = false
+ msco.stringListProperty = [ ]
+ msco.stringListProperty.unshift("zero", "one")
+ expected = [ "zero", "one" ]
+ if (msco.stringListProperty.toString() != expected.toString()) success = false;
+ expected = 2
+ if (msco.stringListProperty.length != expected) success = false
+
+ // shift
+ msco.stringListProperty = [ "one", "two", "three" ]
+ var shiftVal = msco.stringListProperty.shift()
+ expected = [ "two", "three" ]
+ if (msco.stringListProperty.toString() != expected.toString()) success = false;
+ expected = "one"
+ if (shiftVal != expected) success = false
+ shiftVal = msco.stringListProperty.shift()
+ expected = [ "three" ]
+ if (msco.stringListProperty.toString() != expected.toString()) success = false;
+ expected = "two"
+ if (shiftVal != expected) success = false
+ shiftVal = msco.stringListProperty.shift()
+ expected = 0
+ if (msco.stringListProperty.length != expected) success = false;
+ expected = "three"
+ if (shiftVal != expected) success = false
+ shiftVal = msco.stringListProperty.shift()
+ expected = 0
+ if (msco.stringListProperty.length != expected) success = false;
+ expected = undefined
+ if (shiftVal != expected) success = false
}
property variant variantList: [ 1, 2, 3, 4, 5 ];
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp
index eb06b9e57d..560d86005c 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.cpp
+++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp
@@ -300,6 +300,62 @@ static QObject *create_singletonWithEnum(QQmlEngine *, QJSEngine *)
return new SingletonWithEnum;
}
+QObjectContainer::QObjectContainer()
+ : widgetParent(0)
+ , gcOnAppend(false)
+{}
+
+QQmlListProperty<QObject> QObjectContainer::data()
+{
+ return QQmlListProperty<QObject>(this, 0, children_append, children_count, children_at, children_clear);
+}
+
+void QObjectContainer::children_append(QQmlListProperty<QObject> *prop, QObject *o)
+{
+ QObjectContainer *that = static_cast<QObjectContainer*>(prop->object);
+ that->dataChildren.append(o);
+ QObject::connect(o, SIGNAL(destroyed(QObject*)), prop->object, SLOT(childDestroyed(QObject*)));
+
+ if (that->gcOnAppend) {
+ QQmlEngine *engine = qmlEngine(that);
+ engine->collectGarbage();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+ }
+}
+
+int QObjectContainer::children_count(QQmlListProperty<QObject> *prop)
+{
+ return static_cast<QObjectContainer*>(prop->object)->dataChildren.count();
+}
+
+QObject *QObjectContainer::children_at(QQmlListProperty<QObject> *prop, int index)
+{
+ return static_cast<QObjectContainer*>(prop->object)->dataChildren.at(index);
+}
+
+void QObjectContainer::children_clear(QQmlListProperty<QObject> *prop)
+{
+ QObjectContainer *that = static_cast<QObjectContainer*>(prop->object);
+ foreach (QObject *c, that->dataChildren)
+ QObject::disconnect(c, SIGNAL(destroyed(QObject*)), that, SLOT(childDestroyed(QObject*)));
+ that->dataChildren.clear();
+}
+
+void QObjectContainer::childDestroyed(QObject *child) {
+ dataChildren.removeAll(child);
+}
+
+void FloatingQObject::classBegin()
+{
+ setParent(0);
+}
+
+void FloatingQObject::componentComplete()
+{
+ Q_ASSERT(!parent());
+}
+
void registerTypes()
{
qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObjectAlias");
@@ -381,6 +437,10 @@ void registerTypes()
qmlRegisterSingletonType<testImportOrderApi>("Qt.test.importOrderApi2",1,0,"Data",testImportOrder_api2);
qmlRegisterSingletonType<SingletonWithEnum>("Qt.test.singletonWithEnum", 1, 0, "SingletonWithEnum", create_singletonWithEnum);
+
+ qmlRegisterType<QObjectContainer>("Qt.test", 1, 0, "QObjectContainer");
+ qmlRegisterType<QObjectContainerWithGCOnAppend>("Qt.test", 1, 0, "QObjectContainerWithGCOnAppend");
+ qmlRegisterType<FloatingQObject>("Qt.test", 1, 0, "FloatingQObject");
}
#include "testtypes.moc"
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index 928d594f62..d5a1220f23 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -1661,6 +1661,51 @@ public:
};
};
+// Like QtObject, but with default property
+class QObjectContainer : public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("DefaultProperty", "data")
+ Q_PROPERTY(QQmlListProperty<QObject> data READ data DESIGNABLE false)
+public:
+ QObjectContainer();
+
+ QQmlListProperty<QObject> data();
+
+ static void children_append(QQmlListProperty<QObject> *prop, QObject *o);
+ static int children_count(QQmlListProperty<QObject> *prop);
+ static QObject *children_at(QQmlListProperty<QObject> *prop, int index);
+ static void children_clear(QQmlListProperty<QObject> *prop);
+
+ QList<QObject*> dataChildren;
+ QWidget *widgetParent;
+ bool gcOnAppend;
+
+protected slots:
+ void childDestroyed(QObject *child);
+};
+
+class QObjectContainerWithGCOnAppend : public QObjectContainer
+{
+ Q_OBJECT
+public:
+ QObjectContainerWithGCOnAppend()
+ {
+ gcOnAppend = true;
+ }
+};
+
+class FloatingQObject : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QQmlParserStatus)
+public:
+ FloatingQObject() {}
+
+ virtual void classBegin();
+ virtual void componentComplete();
+};
+
void registerTypes();
#endif // TESTTYPES_H
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index a1e36b42e6..a9486a8e63 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -322,6 +322,7 @@ private slots:
void varPropertyAccessOnObjectWithInvalidContext();
void importedScriptsAccessOnObjectWithInvalidContext();
void contextObjectOnLazyBindings();
+ void garbageCollectionDuringCreation();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -7603,6 +7604,33 @@ void tst_qqmlecmascript::contextObjectOnLazyBindings()
QCOMPARE(subObject->property("testValue").toInt(), int(42));
}
+void tst_qqmlecmascript::garbageCollectionDuringCreation()
+{
+ QQmlComponent component(&engine);
+ component.setData("import Qt.test 1.0\n"
+ "QObjectContainerWithGCOnAppend {\n"
+ " objectName: \"root\"\n"
+ " FloatingQObject {\n"
+ " objectName: \"parentLessChild\"\n"
+ " property var blah;\n" // Ensure we have JS wrapper
+ " }\n"
+ "}\n",
+ QUrl());
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QObjectContainer *container = qobject_cast<QObjectContainer*>(object.data());
+ QCOMPARE(container->dataChildren.count(), 1);
+
+ QObject *child = container->dataChildren.first();
+ QQmlData *ddata = QQmlData::get(child);
+ QVERIFY(!ddata->jsWrapper.isNullOrUndefined());
+
+ gc(engine);
+ QCOMPARE(container->dataChildren.count(), 0);
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qmltest/listview/tst_listview.qml b/tests/auto/qmltest/listview/tst_listview.qml
index 03be57909f..069b62a726 100644
--- a/tests/auto/qmltest/listview/tst_listview.qml
+++ b/tests/auto/qmltest/listview/tst_listview.qml
@@ -108,6 +108,33 @@ Item {
property int createdDelegates: 0
}
+ ListView
+ {
+ id: listInteractiveCurrentIndexEnforce
+ width: 600
+ height: 600
+
+ snapMode: ListView.SnapOneItem
+ orientation: ListView.Horizontal
+ interactive: !currentItem.moving
+ highlightRangeMode: ListView.StrictlyEnforceRange
+
+ model: 4
+
+ focus: true
+ Keys.onPressed: if (event.key == Qt.Key_K) currentIndex = currentIndex + 1;
+
+ delegate: Flickable {
+ width: 600
+ height: 600
+ contentWidth: 600
+ contentHeight: 1200
+
+ MouseArea { anchors.fill: parent }
+ Rectangle { anchors.fill: parent; color: index == 0 ? "red" : index == 1 ? "green" : index == 2 ? "blue" : "white" }
+ }
+ }
+
Component {
id: delegateModelAfterCreateComponent
Rectangle {
@@ -272,5 +299,19 @@ Item {
listViewDelegateModelAfterCreate.model = 40;
verify(listViewDelegateModelAfterCreate.createdDelegates > 0);
}
+
+ function test_listInteractiveCurrentIndexEnforce() {
+ mousePress(listInteractiveCurrentIndexEnforce, 10, 50);
+ mouseMove(listInteractiveCurrentIndexEnforce, 10, 40);
+ mouseMove(listInteractiveCurrentIndexEnforce, 10, 30);
+ mouseMove(listInteractiveCurrentIndexEnforce, 10, 20);
+ mouseMove(listInteractiveCurrentIndexEnforce, 10, 10);
+ compare(listInteractiveCurrentIndexEnforce.interactive, false);
+ mouseRelease(listInteractiveCurrentIndexEnforce, 10, 10);
+ tryCompare(listInteractiveCurrentIndexEnforce, "interactive", true);
+ keyClick("k");
+ compare(listInteractiveCurrentIndexEnforce.currentIndex, 1);
+ tryCompare(listInteractiveCurrentIndexEnforce, "contentX", listInteractiveCurrentIndexEnforce.width);
+ }
}
}
diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
index 7d50e130f2..760cdd7b49 100644
--- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
+++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
@@ -281,7 +281,7 @@ void tst_QQuickAccessible::basicPropertiesTest()
QVERIFY(item);
QCOMPARE(item->childCount(), 2);
QCOMPARE(item->rect().size(), QSize(400, 400));
- QCOMPARE(item->role(), QAccessible::Pane);
+ QCOMPARE(item->role(), QAccessible::Client);
QCOMPARE(iface->indexOfChild(item), 0);
QAccessibleInterface *text = item->child(0);
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index 863fb69b84..a350074b42 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -3613,12 +3613,13 @@ void tst_QQuickGridView::resetModel_headerFooter()
model.reset();
- header = findItem<QQuickItem>(contentItem, "header");
- QVERIFY(header);
+ // A reset should not force a new header or footer to be created.
+ QQuickItem *newHeader = findItem<QQuickItem>(contentItem, "header");
+ QVERIFY(newHeader == header);
QCOMPARE(header->y(), -header->height());
- footer = findItem<QQuickItem>(contentItem, "footer");
- QVERIFY(footer);
+ QQuickItem *newFooter = findItem<QQuickItem>(contentItem, "footer");
+ QVERIFY(newFooter == footer);
QCOMPARE(footer->y(), 60.*2);
delete window;
diff --git a/tests/auto/quick/qquickitem2/data/keysforward.qml b/tests/auto/quick/qquickitem2/data/keysforward.qml
index f0cb4d9508..5677aa62f1 100644
--- a/tests/auto/quick/qquickitem2/data/keysforward.qml
+++ b/tests/auto/quick/qquickitem2/data/keysforward.qml
@@ -58,7 +58,7 @@ Item {
objectName: "primary"
property var pressedKeys: []
property var releasedKeys: []
- Keys.forwardTo: secondaryTarget
+ Keys.forwardTo: [ secondaryTarget, extraTarget ]
Keys.onPressed: { event.accepted = event.key === Qt.Key_P; var keys = pressedKeys; keys.push(event.key); pressedKeys = keys }
Keys.onReleased: { event.accepted = event.key === Qt.Key_P; var keys = releasedKeys; keys.push(event.key); releasedKeys = keys }
@@ -81,4 +81,8 @@ Item {
Keys.onPressed: { event.accepted = event.key === Qt.Key_S; var keys = pressedKeys; keys.push(event.key); pressedKeys = keys }
Keys.onReleased: { event.accepted = event.key === Qt.Key_S; var keys = releasedKeys; keys.push(event.key); releasedKeys = keys }
}
+
+ Item {
+ id: extraTarget
+ }
}
diff --git a/tests/auto/quick/qquicklistview/data/layoutChangeSort.qml b/tests/auto/quick/qquicklistview/data/layoutChangeSort.qml
new file mode 100644
index 0000000000..e54f164e45
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/layoutChangeSort.qml
@@ -0,0 +1,58 @@
+import QtQuick 2.0
+import QtQml.Models 2.1
+
+Rectangle {
+ id: root
+ width: 240
+ height: 320
+ color: "#ffffff"
+
+
+ Component {
+ id: myDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ height: 20
+ width: 240
+ Text {
+ objectName: "delegateText"
+ text: display
+ }
+ color: ListView.isCurrentItem ? "lightsteelblue" : "white"
+ }
+ }
+
+ DelegateModel {
+ id: delegateModel
+ objectName: "delegateModel"
+ model: testModel
+ delegate: myDelegate
+ }
+
+ ListView {
+ id: list
+ objectName: "listView"
+ model: delegateModel;
+ focus: true
+ anchors.fill: parent
+
+
+ section {
+ property: "SortRole";
+ delegate: Rectangle {
+ width: parent.width;
+ height: 20;
+ color: "steelblue";
+
+ Text {
+ anchors {
+ fill: parent;
+ margins: 5;
+ }
+ text: section;
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/simplelistview.qml b/tests/auto/quick/qquicklistview/data/simplelistview.qml
new file mode 100644
index 0000000000..56a96150c5
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/simplelistview.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+ListView {
+ width: 400
+ height: 400
+ model: 100
+ delegate: Rectangle {
+ height: 40; width: 400
+ color: index % 2 ? "lightsteelblue" : "lightgray"
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/qquicklistview.pro b/tests/auto/quick/qquicklistview/qquicklistview.pro
index 2ae04d32fe..c9b634b9e8 100644
--- a/tests/auto/quick/qquicklistview/qquicklistview.pro
+++ b/tests/auto/quick/qquicklistview/qquicklistview.pro
@@ -4,10 +4,13 @@ TARGET = tst_qquicklistview
macx:CONFIG -= app_bundle
HEADERS += incrementalmodel.h \
- proxytestinnermodel.h
+ proxytestinnermodel.h \
+ randomsortmodel.h
SOURCES += tst_qquicklistview.cpp \
incrementalmodel.cpp \
- proxytestinnermodel.cpp
+ proxytestinnermodel.cpp \
+ randomsortmodel.cpp
+
include (../../shared/util.pri)
include (../shared/util.pri)
diff --git a/tests/auto/quick/qquicklistview/randomsortmodel.cpp b/tests/auto/quick/qquicklistview/randomsortmodel.cpp
new file mode 100644
index 0000000000..e9082e39c9
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/randomsortmodel.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "randomsortmodel.h"
+
+RandomSortModel::RandomSortModel(QObject* parent):
+ QAbstractListModel(parent)
+{
+ for (int i = 0; i < 10; ++i) {
+ mData.append(qMakePair(QString::fromLatin1("Item %1").arg(i), i * 10));
+ }
+}
+
+QHash<int, QByteArray> RandomSortModel::roleNames() const
+{
+ QHash<int,QByteArray> roles = QAbstractItemModel::roleNames();
+ roles[Qt::UserRole] = "SortRole";
+ return roles;
+}
+
+
+int RandomSortModel::rowCount(const QModelIndex& parent) const
+{
+ if (!parent.isValid())
+ return mData.count();
+
+ return 0;
+}
+
+QVariant RandomSortModel::data(const QModelIndex& index, int role) const
+{
+ if (!index.isValid()) {
+ return QVariant();
+ }
+
+ if (index.row() >= mData.count()) {
+ return QVariant();
+ }
+
+ if (role == Qt::DisplayRole) {
+ return QString::fromLatin1("%1 (weight %2)").arg(mData[index.row()].first).arg(mData[index.row()].second);
+ } else if (role == Qt::UserRole) {
+ return mData[index.row()].second;
+ }
+
+ return QVariant();
+}
+
+void RandomSortModel::randomize()
+{
+ const int row = qrand() % mData.count();
+ int random;
+ bool exists = false;
+ // Make sure we won't end up with two items with the same weight, as that
+ // would make unit-testing much harder
+ do {
+ exists = false;
+ random = qrand() % (mData.count() * 10);
+ QList<QPair<QString, int> >::ConstIterator iter, end;
+ for (iter = mData.constBegin(), end = mData.constEnd(); iter != end; ++iter) {
+ if ((*iter).second == random) {
+ exists = true;
+ break;
+ }
+ }
+ } while (exists);
+ mData[row].second = random;
+ Q_EMIT dataChanged(index(row, 0), index(row, 0));
+}
diff --git a/tests/auto/quick/qquicklistview/randomsortmodel.h b/tests/auto/quick/qquicklistview/randomsortmodel.h
new file mode 100644
index 0000000000..8d28698d9b
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/randomsortmodel.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RANDOMSORTMODEL_H
+#define RANDOMSORTMODEL_H
+
+#include <QAbstractListModel>
+
+class RandomSortModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ explicit RandomSortModel(QObject* parent = 0);
+ QHash<int, QByteArray> roleNames() const;
+
+ QVariant data(const QModelIndex& index, int role) const;
+ int rowCount(const QModelIndex& parent = QModelIndex()) const;
+
+ void randomize();
+
+ private:
+ QList<QPair<QString, int> > mData;
+};
+
+#endif // RANDOMSORTMODEL_H
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index f267b93b26..d22f3487da 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -58,6 +58,7 @@
#include "../shared/visualtestutil.h"
#include "incrementalmodel.h"
#include "proxytestinnermodel.h"
+#include "randomsortmodel.h"
#include <math.h>
Q_DECLARE_METATYPE(Qt::LayoutDirection)
@@ -232,6 +233,11 @@ private slots:
void roundingErrors();
void roundingErrors_data();
+ void QTBUG_38209();
+ void programmaticFlickAtBounds();
+
+ void layoutChange();
+
void QTBUG_39492_data();
void QTBUG_39492();
@@ -4085,12 +4091,13 @@ void tst_QQuickListView::resetModel_headerFooter()
model.reset();
- header = findItem<QQuickItem>(contentItem, "header");
- QVERIFY(header);
+ // A reset should not force a new header or footer to be created.
+ QQuickItem *newHeader = findItem<QQuickItem>(contentItem, "header");
+ QVERIFY(newHeader == header);
QCOMPARE(header->y(), -header->height());
- footer = findItem<QQuickItem>(contentItem, "footer");
- QVERIFY(footer);
+ QQuickItem *newFooter = findItem<QQuickItem>(contentItem, "footer");
+ QVERIFY(newFooter == footer);
QCOMPARE(footer->y(), 30.*4);
delete window;
@@ -7316,6 +7323,93 @@ void tst_QQuickListView::roundingErrors_data()
QTest::newRow("pixelAligned=false") << false;
}
+void tst_QQuickListView::QTBUG_38209()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("simplelistview.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = qobject_cast<QQuickListView *>(window->rootObject());
+ QVERIFY(listview);
+
+ // simulate mouse flick
+ flick(window.data(), QPoint(200, 200), QPoint(200, 50), 100);
+ QTRY_VERIFY(listview->isMoving() == false);
+ qreal contentY = listview->contentY();
+
+ // flick down
+ listview->flick(0, 1000);
+
+ // ensure we move more than just a couple pixels
+ QTRY_VERIFY(contentY - listview->contentY() > qreal(100.0));
+}
+
+void tst_QQuickListView::programmaticFlickAtBounds()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("simplelistview.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = qobject_cast<QQuickListView *>(window->rootObject());
+ QVERIFY(listview);
+ QSignalSpy spy(listview, SIGNAL(contentYChanged()));
+
+ // flick down
+ listview->flick(0, 1000);
+
+ // verify that there is movement beyond bounds
+ QVERIFY(spy.wait(100));
+
+ // reset, and test with StopAtBounds
+ listview->cancelFlick();
+ listview->returnToBounds();
+ QTRY_COMPARE(listview->contentY(), qreal(0.0));
+ listview->setBoundsBehavior(QQuickFlickable::StopAtBounds);
+
+ // flick down
+ listview->flick(0, 1000);
+
+ // verify that there is no movement beyond bounds
+ QVERIFY(!spy.wait(100));
+}
+
+void tst_QQuickListView::layoutChange()
+{
+ RandomSortModel *model = new RandomSortModel;
+ QSortFilterProxyModel *sortModel = new QSortFilterProxyModel;
+ sortModel->setSourceModel(model);
+ sortModel->setSortRole(Qt::UserRole);
+ sortModel->setDynamicSortFilter(true);
+ sortModel->sort(0);
+
+ QScopedPointer<QQuickView> window(createView());
+ window->rootContext()->setContextProperty("testModel", QVariant::fromValue(sortModel));
+ window->setSource(testFileUrl("layoutChangeSort.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = window->rootObject()->findChild<QQuickListView *>("listView");
+ QVERIFY(listview);
+
+ for (int iter = 0; iter < 100; iter++) {
+ for (int i = 0; i < sortModel->rowCount(); ++i) {
+ QQuickItem *delegateItem = listview->itemAt(10, 10 + 2 * i * 20 + 20); // item + group
+ QVERIFY(delegateItem);
+ QQuickItem *delegateText = delegateItem->findChild<QQuickItem *>("delegateText");
+ QVERIFY(delegateText);
+
+ QCOMPARE(delegateText->property("text").toString(),
+ sortModel->index(i, 0, QModelIndex()).data().toString());
+ }
+
+ model->randomize();
+ listview->forceLayout();
+ QTest::qWait(5); // give view a chance to update
+ }
+}
+
void tst_QQuickListView::QTBUG_39492_data()
{
QStandardItemModel *sourceModel = new QStandardItemModel(this);
diff --git a/tests/auto/quick/qquickpathview/data/changePathDuringRefill.qml b/tests/auto/quick/qquickpathview/data/changePathDuringRefill.qml
new file mode 100644
index 0000000000..f02ab35faf
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/changePathDuringRefill.qml
@@ -0,0 +1,45 @@
+import QtQuick 2.3
+
+PathView {
+ id: view
+ objectName: "pathView"
+ width: 100
+ height: delegateHeight * pathItemCount
+ model: ["A", "B", "C"]
+ pathItemCount: 3
+ anchors.centerIn: parent
+
+ property int delegateHeight: 0
+
+ activeFocusOnTab: true
+ Keys.onDownPressed: view.incrementCurrentIndex()
+ Keys.onUpPressed: view.decrementCurrentIndex()
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+
+ delegate: Rectangle {
+ objectName: "delegate" + modelData
+ width: view.width
+ height: textItem.height
+ border.color: "red"
+
+ onHeightChanged: {
+ if (index == 0)
+ view.delegateHeight = textItem.height
+ }
+
+ Text {
+ id: textItem
+ text: modelData
+ }
+ }
+
+ path: Path {
+ startX: view.width / 2
+ startY: 0
+ PathLine {
+ x: view.width / 2
+ y: view.pathItemCount * view.delegateHeight
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpathview/data/incorrectSteal.qml b/tests/auto/quick/qquickpathview/data/incorrectSteal.qml
new file mode 100644
index 0000000000..bcd6923b73
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/incorrectSteal.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Flickable {
+ objectName: "flickable"
+ width: 400; height: 400
+
+ contentHeight: height
+ contentWidth: width * 3
+ contentX: 400
+
+ Row {
+ Rectangle { width: 400; height: 400; color: "green" }
+ Rectangle {
+ width: 400; height: 400; color: "blue"
+ clip: true
+
+ PathView {
+ id: pathView
+ objectName: "pathView"
+ width: parent.width
+ height: 200
+ anchors.verticalCenter: parent.verticalCenter
+
+ dragMargin: 400
+ pathItemCount: 6
+
+ model: 10
+ path: Path {
+ startX: -pathView.width / 2
+ startY: pathView.height / 2
+ PathLine { x: pathView.width + pathView.width / 2; y: pathView.height / 2 }
+ }
+
+ delegate: Rectangle {
+ width: 100; height: 200
+ color: "purple"
+ MouseArea {
+ anchors.fill: parent
+ }
+ }
+ }
+ }
+ Rectangle { width: 400; height: 400; color: "yellow" }
+ }
+}
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index 579cb954aa..1960775ad3 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -47,6 +47,7 @@
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlincubator.h>
#include <QtQuick/private/qquickpathview_p.h>
+#include <QtQuick/private/qquickflickable_p.h>
#include <QtQuick/private/qquickpath_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
@@ -142,6 +143,8 @@ private slots:
void indexAt_itemAt();
void indexAt_itemAt_data();
void cacheItemCount();
+ void incorrectSteal();
+ void changePathDuringRefill();
};
class TestObject : public QObject
@@ -2120,7 +2123,102 @@ void tst_QQuickPathView::cacheItemCount()
bool b = true;
controller.incubateWhile(&b);
}
+}
+
+static void testCurrentIndexChange(QQuickPathView *pathView, const QStringList &objectNamesInOrder)
+{
+ for (int visualIndex = 0; visualIndex < objectNamesInOrder.size() - 1; ++visualIndex) {
+ QQuickRectangle *delegate = findItem<QQuickRectangle>(pathView, objectNamesInOrder.at(visualIndex));
+ QVERIFY(delegate);
+
+ QQuickRectangle *nextDelegate = findItem<QQuickRectangle>(pathView, objectNamesInOrder.at(visualIndex + 1));
+ QVERIFY(nextDelegate);
+
+ QVERIFY(delegate->y() < nextDelegate->y());
+ }
+}
+
+void tst_QQuickPathView::changePathDuringRefill()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("changePathDuringRefill.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QCOMPARE(window.data(), qGuiApp->focusWindow());
+
+ QQuickPathView *pathView = qobject_cast<QQuickPathView*>(window->rootObject());
+ QVERIFY(pathView != 0);
+
+ testCurrentIndexChange(pathView, QStringList() << "delegateC" << "delegateA" << "delegateB");
+
+ pathView->incrementCurrentIndex();
+ /*
+ Decrementing moves delegateA down, resulting in an offset of 1,
+ so incrementing will move it up, resulting in an offset of 2:
+
+ delegateC delegateA
+ delegateA => delegateB
+ delegateB delegateC
+ */
+ QTRY_COMPARE(pathView->offset(), 2.0);
+ testCurrentIndexChange(pathView, QStringList() << "delegateA" << "delegateB" << "delegateC");
+}
+
+void tst_QQuickPathView::incorrectSteal()
+{
+ QScopedPointer<QQuickView> window(createView());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+ window->setSource(testFileUrl("incorrectSteal.qml"));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QCOMPARE(window.data(), qGuiApp->focusWindow());
+
+ QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "pathView");
+ QVERIFY(pathview != 0);
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
+ QVERIFY(flickable != 0);
+
+ QSignalSpy movingSpy(pathview, SIGNAL(movingChanged()));
+ QSignalSpy moveStartedSpy(pathview, SIGNAL(movementStarted()));
+ QSignalSpy moveEndedSpy(pathview, SIGNAL(movementEnded()));
+
+ QSignalSpy fflickingSpy(flickable, SIGNAL(flickingChanged()));
+ QSignalSpy fflickStartedSpy(flickable, SIGNAL(flickStarted()));
+ QSignalSpy fflickEndedSpy(flickable, SIGNAL(flickEnded()));
+
+ int waitInterval = 5;
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(23,218));
+
+ QTest::mouseMove(window.data(), QPoint(25,218), waitInterval);
+ QTest::mouseMove(window.data(), QPoint(26,218), waitInterval);
+ QTest::mouseMove(window.data(), QPoint(28,219), waitInterval);
+ QTest::mouseMove(window.data(), QPoint(31,219), waitInterval);
+ QTest::mouseMove(window.data(), QPoint(39,219), waitInterval);
+
+ // first move beyond threshold does not trigger drag
+ QVERIFY(!pathview->isMoving());
+ QVERIFY(!pathview->isDragging());
+ QCOMPARE(movingSpy.count(), 0);
+ QCOMPARE(moveStartedSpy.count(), 0);
+ QCOMPARE(moveEndedSpy.count(), 0);
+ QCOMPARE(fflickingSpy.count(), 0);
+ QCOMPARE(fflickStartedSpy.count(), 0);
+ QCOMPARE(fflickEndedSpy.count(), 0);
+
+ // no further moves after the initial move beyond threshold
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(53,219));
+ QTRY_COMPARE(movingSpy.count(), 2);
+ QTRY_COMPARE(moveEndedSpy.count(), 1);
+ QCOMPARE(moveStartedSpy.count(), 1);
+ // Flickable should not handle this
+ QEXPECT_FAIL("", "QTBUG-37859", Abort);
+ QCOMPARE(fflickingSpy.count(), 0);
+ QCOMPARE(fflickStartedSpy.count(), 0);
+ QCOMPARE(fflickEndedSpy.count(), 0);
}
QTEST_MAIN(tst_QQuickPathView)
diff --git a/tests/auto/quick/qquickwindow/data/unloadSubWindow.qml b/tests/auto/quick/qquickwindow/data/unloadSubWindow.qml
new file mode 100644
index 0000000000..bf9df4867d
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/unloadSubWindow.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.3
+import QtQuick.Window 2.2
+
+Window {
+ id: root
+ property var transientWindow
+ property Loader loader1: Loader {
+ sourceComponent: Item {
+ Loader {
+ id: loader2
+ sourceComponent : Window {
+ id: inner
+ visible: true
+ Component.onCompleted: root.transientWindow = inner
+ }
+ }
+ Component.onDestruction: {
+ loader2.active = false;
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index b05146fa3a..b8f9102775 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -47,6 +47,7 @@
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtQuick/private/qquickloader_p.h>
#include "../../shared/util.h"
#include "../shared/visualtestutil.h"
#include <QSignalSpy>
@@ -347,6 +348,8 @@ private slots:
void crashWhenHoverItemDeleted();
+ void unloadSubWindow();
+
void qobjectEventFilter_touch();
void qobjectEventFilter_key();
void qobjectEventFilter_mouse();
@@ -1705,6 +1708,26 @@ void tst_qquickwindow::crashWhenHoverItemDeleted()
}
}
+// QTBUG-33436
+void tst_qquickwindow::unloadSubWindow()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("unloadSubWindow.qml"));
+ QQuickWindow *window = qobject_cast<QQuickWindow *>(component.create());
+ QVERIFY(window);
+ window->show();
+ QTest::qWaitForWindowExposed(window);
+ QQuickWindow *transient = Q_NULLPTR;
+ QTRY_VERIFY(transient = window->property("transientWindow").value<QQuickWindow*>());
+ QTest::qWaitForWindowExposed(transient);
+
+ // Unload the inner window (in nested Loaders) and make sure it doesn't crash
+ QQuickLoader *loader = window->property("loader1").value<QQuickLoader*>();
+ loader->setActive(false);
+ QTRY_VERIFY(!transient->isVisible());
+}
+
// QTBUG-32004
void tst_qquickwindow::qobjectEventFilter_touch()
{