aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSort.mjs117
-rw-r--r--tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSort.qml166
-rw-r--r--tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSortWorker.mjs38
-rw-r--r--tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/main.qml23
-rw-r--r--tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp17
5 files changed, 361 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSort.mjs b/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSort.mjs
new file mode 100644
index 0000000000..cfc1e1146f
--- /dev/null
+++ b/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSort.mjs
@@ -0,0 +1,117 @@
+/* Copyright 2020 Esri
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+//------------------------------------------------------------------------------
+
+export const OrderAscending = 0
+export const OrderDescending = 1
+
+//------------------------------------------------------------------------------
+
+export function sort(model, sortKey, descending, useMove) {
+
+ _sort(model, sortKey, descending, useMove);
+}
+
+//------------------------------------------------------------------------------
+
+function _sort(model, sortKey, descending, useMove) {
+ var lessThan = descending ? 1 : -1;
+ var greaterThan = -lessThan;
+
+ var indices = [...new Array(model.count).keys()];
+
+ function getKeyValue(index) {
+ return model.get(index)[sortKey];
+ }
+
+ function compareKey(index1, index2) {
+ var value1 = getKeyValue(index1);
+ var value2 = getKeyValue(index2);
+
+ return (value1 < value2)
+ ? lessThan
+ : (value1 > value2)
+ ? greaterThan
+ : 0;
+ }
+
+ indices.sort(compareKey);
+
+
+ function compareFrom(i1, i2) {
+ return (i1.from < i2.from)
+ ? -1
+ : (i1.from > i2.from)
+ ? 1
+ : 0;
+ }
+
+ var swapIndices = indices.map((e, i) => { return { from: e, to: i }}).sort(compareFrom).map(e => e.to);
+
+ function clone(o) {
+ return JSON.parse(JSON.stringify(o));
+ }
+
+ function cloneSwap(a, b) {
+ var o = clone(model.get(a));
+ model.set(a, model.get(b));
+ model.set(b, o);
+ }
+
+ function moveSwap(a, b) {
+ if (a < b) {
+ model.move(a, b, 1);
+ model.move(b - 1, a, 1);
+ }
+ else if (a > b) {
+ model.move(b, a, 1);
+ model.move(a - 1, b, 1);
+ }
+ }
+
+
+ var swap = useMove ? moveSwap : cloneSwap;
+ var swapCount = 0;
+
+
+ for (var iFrom = 0; iFrom < swapIndices.length; iFrom++) {
+ var iTo = swapIndices[iFrom];
+
+ if (iFrom === iTo) {
+ continue;
+ }
+
+ do {
+ swap(iFrom, iTo);
+
+ var t = swapIndices[iFrom];
+ swapIndices[iFrom] = swapIndices[iTo]
+ swapIndices[iTo] = t;
+
+ iTo = swapIndices[iFrom];
+
+ swapCount++;
+ }
+ while (iFrom !== iTo);
+ }
+
+}
+
+//------------------------------------------------------------------------------
+
+
+
diff --git a/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSort.qml b/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSort.qml
new file mode 100644
index 0000000000..2679925c80
--- /dev/null
+++ b/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSort.qml
@@ -0,0 +1,166 @@
+/* Copyright 2020 Esri
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import QtQml 2.13
+import QtQml.Models 2.13
+
+import QtQuick 2.13
+import QtQuick.Layouts 1.12
+
+import "ListModelSort.mjs" as ListModelSort
+
+Item {
+ Component.onCompleted: {
+ fillModel(namesModel, "A, D, E, B, C, A");
+ }
+
+
+ function verify() {
+ let expected = ["A", "A", "B", "C", "D", "E"]
+ let sorted = listView.count === 6
+ for (let i = 0; i<listView.count;++i) {
+ sorted = sorted && (listView.itemAtIndex(i).name === expected[i])
+ }
+ return sorted
+ }
+
+ function doSort() {
+ sortAsync(namesModel, "name", false, false)
+ }
+
+
+ function random(n) {
+ return Math.round(Math.random(new Date().valueOf()) * n);
+ }
+
+ function fillModel(model, values) {
+ var names = values.split(",").map(name => name.trim()).filter(name => name > "");
+
+
+ model.clear();
+
+ for (const name of names) {
+ model.append({
+ name: name,
+ number: random(names.length)
+ });
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
+ ListModel {
+ id: namesModel
+
+ objectName: "namesModel"
+ }
+
+ //--------------------------------------------------------------------------
+ ColumnLayout {
+ anchors {
+ fill: parent
+ margins: 10
+ }
+
+ ListView {
+ id: listView
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ model: namesModel
+ clip: true
+ spacing: 5
+
+ delegate: Text {
+ required property string name
+ required property int number
+ width: ListView.view.width
+ text: "%1 (%2)".arg(name).arg(number)
+ horizontalAlignment: Text.AlignHCenter
+ wrapMode: Text.WrapAtWordBoundaryOrAnywhere
+ }
+
+ add: Transition {
+ NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 }
+ NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 }
+ }
+
+ addDisplaced: Transition {
+ NumberAnimation { properties: "x,y"; duration: 100 }
+ }
+
+ move: Transition {
+ NumberAnimation { properties: "x,y"; duration: 100 }
+ }
+
+ moveDisplaced: Transition {
+ NumberAnimation { properties: "x,y"; duration: 100 }
+ }
+
+ displaced: Transition {
+ NumberAnimation { properties: "x,y"; duration: 40; easing.type: Easing.OutBounce }
+ }
+
+ populate: Transition {
+ NumberAnimation { properties: "x,y"; duration: 100 }
+ }
+
+ remove: Transition {
+ ParallelAnimation {
+ NumberAnimation { property: "opacity"; to: 0; duration: 100 }
+ NumberAnimation { properties: "x,y"; to: 100; duration: 100 }
+ }
+ }
+
+ removeDisplaced: Transition {
+ NumberAnimation { properties: "x,y"; duration: 100 }
+ }
+ }
+ }
+
+
+ function sortSync(model, sortKey, descending, useMove) {
+
+ ListModelSort.sort(model, sortKey, descending, useMove);
+ }
+
+ //--------------------------------------------------------------------------
+
+ function sortAsync(model, sortKey, descending, useMove) {
+
+ var params = {
+ debug: true,
+ model: model,
+ sortKey: sortKey,
+ descending: descending,
+ useMove: useMove
+ };
+
+
+ sortWorker.sendMessage(params);
+ }
+
+ WorkerScript {
+ id: sortWorker
+
+ source: "ListModelSortWorker.mjs"
+ }
+
+ //--------------------------------------------------------------------------
+
+}
+
diff --git a/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSortWorker.mjs b/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSortWorker.mjs
new file mode 100644
index 0000000000..fa3b5c27ec
--- /dev/null
+++ b/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/ListModelSortWorker.mjs
@@ -0,0 +1,38 @@
+/* Copyright 2020 Esri
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import * as ListModelSort from "ListModelSort.mjs";
+
+//------------------------------------------------------------------------------
+
+WorkerScript.onMessage = function(params) {
+
+ params.model.sync();
+
+ const debug = params.debug;
+
+ ListModelSort.sort(params.model, params.sortKey, !!params.descending, !!params.useMove);
+
+ params.model.sync();
+
+
+ WorkerScript.sendMessage({
+ text: "Sorted"
+ });
+}
+
+//------------------------------------------------------------------------------
+
diff --git a/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/main.qml b/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/main.qml
new file mode 100644
index 0000000000..88a23511fa
--- /dev/null
+++ b/tests/auto/qml/qqmllistmodelworkerscript/data/listmodel_async_sort/main.qml
@@ -0,0 +1,23 @@
+import QtQuick 2.13
+import QtQuick.Window 2.13
+
+Window {
+ visible: true
+ width: 640
+ height: 640
+ title: qsTr("Hello World")
+
+ ListModelSort {
+ id: lms
+ anchors.fill: parent
+ }
+
+ function doSort() {
+ lms.doSort()
+ }
+
+ function verify(): bool {
+ let ok = lms.verify()
+ return ok
+ }
+}
diff --git a/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp b/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
index 85814a54fb..262ac25d6a 100644
--- a/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
+++ b/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
@@ -104,6 +104,7 @@ private slots:
void worker_remove_list();
void dynamic_role_data();
void dynamic_role();
+ void correctMoves();
};
bool tst_qqmllistmodelworkerscript::compareVariantList(const QVariantList &testList, QVariant object)
@@ -842,6 +843,22 @@ void tst_qqmllistmodelworkerscript::dynamic_role()
qApp->processEvents();
}
+void tst_qqmllistmodelworkerscript::correctMoves()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("listmodel_async_sort/main.qml"));
+ QScopedPointer<QObject> root {component.create()};
+ QVERIFY2(root, qPrintable(component.errorString()));
+ bool ok =QMetaObject::invokeMethod(root.get(), "doSort");
+ QVERIFY(ok);
+ auto check = [&](){
+ bool success = false;
+ QMetaObject::invokeMethod(root.get(), "verify", Q_RETURN_ARG(bool, success));
+ return success;
+ };
+ QTRY_VERIFY(check());
+}
+
QTEST_MAIN(tst_qqmllistmodelworkerscript)
#include "tst_qqmllistmodelworkerscript.moc"