From 3c5330b81889b823490402bf19cf9886ab1c38e1 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 26 Apr 2020 23:09:29 +0300 Subject: [PATCH 1/5] cosmit --- examples/todo/MainWindow.qml | 1 - examples/todo/actions/ActionTypes.qml | 1 - examples/todo/actions/AppActions.qml | 1 - examples/todo/main.cpp | 1 - examples/todo/main.qml | 1 - examples/todo/middlewares/DialogMiddleware.qml | 1 - examples/todo/middlewares/SystemMiddleware.qml | 1 - examples/todo/stores/TodoStore.qml | 4 ---- examples/todo/views/Footer.qml | 1 - examples/todo/views/Header.qml | 2 -- examples/todo/views/TodoItem.qml | 1 - examples/todo/views/TodoList.qml | 1 - examples/todo/views/TodoVisualModel.qml | 1 - 13 files changed, 17 deletions(-) diff --git a/examples/todo/MainWindow.qml b/examples/todo/MainWindow.qml index e6ff1d0..c9b12a7 100644 --- a/examples/todo/MainWindow.qml +++ b/examples/todo/MainWindow.qml @@ -32,4 +32,3 @@ Window { } } } - diff --git a/examples/todo/actions/ActionTypes.qml b/examples/todo/actions/ActionTypes.qml index 82bbd2a..f5b8ee1 100644 --- a/examples/todo/actions/ActionTypes.qml +++ b/examples/todo/actions/ActionTypes.qml @@ -13,4 +13,3 @@ KeyTable { property string startApp } - diff --git a/examples/todo/actions/AppActions.qml b/examples/todo/actions/AppActions.qml index 3a99d45..83e4b2c 100644 --- a/examples/todo/actions/AppActions.qml +++ b/examples/todo/actions/AppActions.qml @@ -15,4 +15,3 @@ ActionCreator { signal setShowCompletedTasks(bool value) } - diff --git a/examples/todo/main.cpp b/examples/todo/main.cpp index 30f14a9..5117ddb 100644 --- a/examples/todo/main.cpp +++ b/examples/todo/main.cpp @@ -19,4 +19,3 @@ int main(int argc, char *argv[]) return app.exec(); } - diff --git a/examples/todo/main.qml b/examples/todo/main.qml index a122e62..5a05f2a 100644 --- a/examples/todo/main.qml +++ b/examples/todo/main.qml @@ -23,4 +23,3 @@ Item { id: mainWindow } } - diff --git a/examples/todo/middlewares/DialogMiddleware.qml b/examples/todo/middlewares/DialogMiddleware.qml index 722895b..809bf5f 100644 --- a/examples/todo/middlewares/DialogMiddleware.qml +++ b/examples/todo/middlewares/DialogMiddleware.qml @@ -36,5 +36,4 @@ Middleware { /// Pass the action to next middleware / store next(type, message); } - } diff --git a/examples/todo/middlewares/SystemMiddleware.qml b/examples/todo/middlewares/SystemMiddleware.qml index 192de63..ce0f0f6 100644 --- a/examples/todo/middlewares/SystemMiddleware.qml +++ b/examples/todo/middlewares/SystemMiddleware.qml @@ -25,5 +25,4 @@ Middleware { console.log("closing"); } } - } diff --git a/examples/todo/stores/TodoStore.qml b/examples/todo/stores/TodoStore.qml index 73f77a0..df2943b 100644 --- a/examples/todo/stores/TodoStore.qml +++ b/examples/todo/stores/TodoStore.qml @@ -72,8 +72,4 @@ Store { } } } - } - - - diff --git a/examples/todo/views/Footer.qml b/examples/todo/views/Footer.qml index 80e505d..b9f235a 100644 --- a/examples/todo/views/Footer.qml +++ b/examples/todo/views/Footer.qml @@ -29,4 +29,3 @@ Item { } } } - diff --git a/examples/todo/views/Header.qml b/examples/todo/views/Header.qml index e0404dd..0b049c5 100644 --- a/examples/todo/views/Header.qml +++ b/examples/todo/views/Header.qml @@ -23,6 +23,4 @@ Item { value: MainStore.userPrefs.showCompletedTasks } } - } - diff --git a/examples/todo/views/TodoItem.qml b/examples/todo/views/TodoItem.qml index b20d45c..3e7be9a 100644 --- a/examples/todo/views/TodoItem.qml +++ b/examples/todo/views/TodoItem.qml @@ -30,4 +30,3 @@ Rectangle { AppActions.setTaskDone(uid,checked); } } - diff --git a/examples/todo/views/TodoList.qml b/examples/todo/views/TodoList.qml index 46ef551..3d0f8b1 100644 --- a/examples/todo/views/TodoList.qml +++ b/examples/todo/views/TodoList.qml @@ -13,4 +13,3 @@ ScrollView { } } } - diff --git a/examples/todo/views/TodoVisualModel.qml b/examples/todo/views/TodoVisualModel.qml index 52b11c6..33010da 100644 --- a/examples/todo/views/TodoVisualModel.qml +++ b/examples/todo/views/TodoVisualModel.qml @@ -27,4 +27,3 @@ VisualDataModel { } } } - From 3aec02f38469e1f8aad89094dc49e12464cc3461 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 26 Apr 2020 20:55:49 +0300 Subject: [PATCH 2/5] examples/todo: update cmake, use KF5::I18n --- examples/todo/CMakeLists.txt | 15 ++++++++++----- examples/todo/main.cpp | 4 ++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/examples/todo/CMakeLists.txt b/examples/todo/CMakeLists.txt index 5cda897..de73e3c 100644 --- a/examples/todo/CMakeLists.txt +++ b/examples/todo/CMakeLists.txt @@ -2,6 +2,13 @@ cmake_minimum_required(VERSION 3.1.0) project(todo) +################# set KDE specific information ################# +find_package(ECM REQUIRED NO_MODULE) + +# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) + + set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -12,10 +19,8 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) -find_package(Qt5Qml CONFIG REQUIRED) -find_package(Qt5Gui CONFIG REQUIRED) -find_package(Qt5Core CONFIG REQUIRED) -find_package(Qt5Quick CONFIG REQUIRED) +find_package(Qt5 REQUIRED COMPONENTS Core Gui Qml QuickControls2) +find_package(KF5 REQUIRED COMPONENTS Kirigami2 I18n) set(todo_SRCS main.cpp @@ -40,4 +45,4 @@ add_executable(todo WIN32 ${todo_SRCS}) add_dependencies(todo QuickFlux) target_link_libraries(todo debug quickfluxd optimized quickflux) -target_link_libraries(todo Qt5::Qml Qt5::Gui Qt5::Core Qt5::Quick) +target_link_libraries(todo Qt5::Qml Qt5::Gui Qt5::Core Qt5::Quick KF5::I18n) diff --git a/examples/todo/main.cpp b/examples/todo/main.cpp index 5117ddb..c347aa3 100644 --- a/examples/todo/main.cpp +++ b/examples/todo/main.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include @@ -12,6 +14,8 @@ int main(int argc, char *argv[]) registerQuickFluxQmlTypes(); // It is not necessary to call this function if the QuickFlux library is installed via qpm QQmlApplicationEngine engine; + + engine.rootContext()->setContextObject(new KLocalizedContext(&engine)); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); QFAppDispatcher* dispatcher = QFAppDispatcher::instance(&engine); From f9bbfcb90f7b73e1e9d43c91e2e32ab106f95711 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 26 Apr 2020 22:24:53 +0300 Subject: [PATCH 3/5] examples/todo WIP: update stores, optimize imports --- examples/todo/stores/MainStore.qml | 1 - examples/todo/stores/RootStore.qml | 1 - examples/todo/stores/TodoStore.qml | 9 +++++---- examples/todo/stores/UserPrefsStore.qml | 1 - 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/examples/todo/stores/MainStore.qml b/examples/todo/stores/MainStore.qml index ef9e309..e4dedb2 100644 --- a/examples/todo/stores/MainStore.qml +++ b/examples/todo/stores/MainStore.qml @@ -1,5 +1,4 @@ pragma Singleton -import QtQuick 2.0 import QuickFlux 1.1 RootStore { diff --git a/examples/todo/stores/RootStore.qml b/examples/todo/stores/RootStore.qml index 1c1c429..310b413 100644 --- a/examples/todo/stores/RootStore.qml +++ b/examples/todo/stores/RootStore.qml @@ -1,4 +1,3 @@ -import QtQuick 2.0 import QuickFlux 1.1 Store { diff --git a/examples/todo/stores/TodoStore.qml b/examples/todo/stores/TodoStore.qml index df2943b..e0449fc 100644 --- a/examples/todo/stores/TodoStore.qml +++ b/examples/todo/stores/TodoStore.qml @@ -51,7 +51,7 @@ Store { type: ActionTypes.addTask onDispatched: { - var item = { + const item = { uid: nextUid++, title: message.title, done: false @@ -63,10 +63,11 @@ Store { Filter { type: ActionTypes.setTaskDone onDispatched: { - for (var i = 0 ; i < model.count ; i++) { - var item = model.get(i); + // quick and dirty + for (let i = 0; i < model.count; i++) { + const item = model.get(i); if (item.uid === message.uid) { - model.setProperty(i,"done",message.done); + model.setProperty(i, "done", message.done); break; } } diff --git a/examples/todo/stores/UserPrefsStore.qml b/examples/todo/stores/UserPrefsStore.qml index b9b755b..e4d421a 100644 --- a/examples/todo/stores/UserPrefsStore.qml +++ b/examples/todo/stores/UserPrefsStore.qml @@ -1,4 +1,3 @@ -import QtQuick 2.0 import QuickFlux 1.1 import "../actions" From 08879451fe08ff6a3ec2933e91cdd6f7119b7373 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Mon, 27 Apr 2020 05:24:57 +0300 Subject: [PATCH 4/5] examples/todo WIP: restructure app's entry point --- examples/todo/MainPage.qml | 20 +++++++++++++++++++ examples/todo/MainWindow.qml | 37 ++++++------------------------------ examples/todo/main.qml | 4 +--- examples/todo/qml.qrc | 1 + 4 files changed, 28 insertions(+), 34 deletions(-) create mode 100644 examples/todo/MainPage.qml diff --git a/examples/todo/MainPage.qml b/examples/todo/MainPage.qml new file mode 100644 index 0000000..e91d358 --- /dev/null +++ b/examples/todo/MainPage.qml @@ -0,0 +1,20 @@ +import org.kde.kirigami 2.2 as Kirigami +import "./views" + +Kirigami.ScrollablePage { + id: page + + // space for title will be reserved anyway, + // so why not just fill it with something meaningful + title: "Todo list" + + header: Header {} + footer: Footer {} + + // page content item goes inline + TodoList {} + + // Kirigami.ScrollablePage has undocumented feature: + // it looks differently when the child item is ListModel + Kirigami.Theme.colorSet: Kirigami.Theme.Window +} diff --git a/examples/todo/MainWindow.qml b/examples/todo/MainWindow.qml index c9b12a7..798ff4f 100644 --- a/examples/todo/MainWindow.qml +++ b/examples/todo/MainWindow.qml @@ -1,34 +1,9 @@ -import QtQuick 2.3 -import QtQuick.Window 2.2 -import QtQuick.Layouts 1.0 -import QuickFlux 1.1 -import "./views" -import "./middlewares" -import "./actions" +import org.kde.kirigami 2.0 as Kirigami -Window { - width: 480 - height: 640 - visible: true +// Wraps single-page application in a platform window +Kirigami.ApplicationWindow { + width: 18 * Kirigami.Units.gridUnit + height: 20 * Kirigami.Units.gridUnit - ColumnLayout { - anchors.fill: parent - anchors.leftMargin: 16 - anchors.rightMargin: 16 - - Header { - Layout.fillWidth: true - Layout.fillHeight: false - } - - TodoList { - Layout.fillWidth: true - Layout.fillHeight: true - } - - Footer { - Layout.fillWidth: true - Layout.fillHeight: false - } - } + pageStack.initialPage: MainPage {} } diff --git a/examples/todo/main.qml b/examples/todo/main.qml index 5a05f2a..5256bde 100644 --- a/examples/todo/main.qml +++ b/examples/todo/main.qml @@ -1,11 +1,9 @@ import QtQuick 2.3 -import QtQuick.Window 2.2 -import QtQuick.Layouts 1.0 import QuickFlux 1.1 -import "./views" import "./middlewares" import "./actions" +// Non-visual container for application-wide components Item { MiddlewareList { diff --git a/examples/todo/qml.qrc b/examples/todo/qml.qrc index 571e503..4e773cc 100644 --- a/examples/todo/qml.qrc +++ b/examples/todo/qml.qrc @@ -17,5 +17,6 @@ middlewares/DialogMiddleware.qml MainWindow.qml middlewares/SystemMiddleware.qml + MainPage.qml From 89d1805bbc25b07a659bdd96d93e649d97707156 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Mon, 27 Apr 2020 05:39:56 +0300 Subject: [PATCH 5/5] examples/todo: modernize using QQC2, Kirigami Updated all imports & uses of QtQuick.Controls to 2.0+; Used Kirigami for page layout and style management; Provided localization support via KF5::I18n (just to promote good practices and all); Added animations, to show that QuickFlux is compatible with them; Used ECMAScript 2016 features like const keyword and arrow functions. --- examples/todo/actions/ActionTypes.qml | 2 +- examples/todo/actions/AppActions.qml | 5 +- .../todo/middlewares/DialogMiddleware.qml | 39 ++++++++-- .../todo/middlewares/SystemMiddleware.qml | 4 +- examples/todo/stores/TodoStore.qml | 2 +- examples/todo/views/Footer.qml | 51 ++++++++----- examples/todo/views/Header.qml | 30 ++++---- examples/todo/views/TodoItem.qml | 72 +++++++++++++++---- examples/todo/views/TodoList.qml | 71 +++++++++++++++--- examples/todo/views/TodoVisualModel.qml | 4 +- 10 files changed, 210 insertions(+), 70 deletions(-) diff --git a/examples/todo/actions/ActionTypes.qml b/examples/todo/actions/ActionTypes.qml index f5b8ee1..abd9cdb 100644 --- a/examples/todo/actions/ActionTypes.qml +++ b/examples/todo/actions/ActionTypes.qml @@ -1,6 +1,6 @@ pragma Singleton import QtQuick 2.0 -import QuickFlux 1.0 +import QuickFlux 1.1 KeyTable { // KeyTable is an object with properties equal to its key name diff --git a/examples/todo/actions/AppActions.qml b/examples/todo/actions/AppActions.qml index 83e4b2c..e863c15 100644 --- a/examples/todo/actions/AppActions.qml +++ b/examples/todo/actions/AppActions.qml @@ -1,7 +1,6 @@ pragma Singleton import QtQuick 2.0 import QuickFlux 1.1 -import "./" ActionCreator { @@ -9,9 +8,9 @@ ActionCreator { signal addTask(string title); // Set/unset done on a task - signal setTaskDone(var uid, bool done) + signal setTaskDone(int uid, bool done) // Show/hide completed task - signal setShowCompletedTasks(bool value) + signal setShowCompletedTasks(bool value, Item contextItem) } diff --git a/examples/todo/middlewares/DialogMiddleware.qml b/examples/todo/middlewares/DialogMiddleware.qml index 809bf5f..b817c05 100644 --- a/examples/todo/middlewares/DialogMiddleware.qml +++ b/examples/todo/middlewares/DialogMiddleware.qml @@ -1,6 +1,6 @@ import QtQuick 2.0 +import QtQuick.Controls 2.1 import QuickFlux 1.1 -import QtQuick.Dialogs 1.2 import "../actions" import "../stores" @@ -8,20 +8,48 @@ Middleware { property RootStore store: MainStore - MessageDialog { + Dialog { id: dialog - title: "Confirmation" - text: "Are you sure want to show completed tasks?" - standardButtons: StandardButton.Ok | StandardButton.Cancel + modal: true + anchors.centerIn: parent + + title: i18n("Confirmation") + Label { + text: i18n("Are you sure want to show completed tasks?") + } + standardButtons: Dialog.Ok | Dialog.Cancel onAccepted: { + _cleanup(); next(ActionTypes.setShowCompletedTasks, {value: true}); } onRejected: { + _cleanup(); /// Trigger the changed signal even it is unchanged. It forces the checkbox to be turned off. store.userPrefs.showCompletedTasksChanged(); } + + function reparent(item) { + // attach dialog to the root item, so that it stays centerred + parent = _findRoot(item) + } + + // Drills up to the top of component hierarchy. + function _findRoot(/* Item */ item) { + if (item === null) { + return null; + } + while (item.parent !== null) { + item = item.parent; + } + return item; + } + + function _cleanup() { + // free the parent + reparent(null); + } } function dispatch(type, message) { @@ -29,6 +57,7 @@ Middleware { if (type === ActionTypes.setShowCompletedTasks && message.value === true) { // If user want to show completed tasks, drop the action and show a dialog + dialog.reparent(message.contextItem); dialog.open(); return; } diff --git a/examples/todo/middlewares/SystemMiddleware.qml b/examples/todo/middlewares/SystemMiddleware.qml index ce0f0f6..56084aa 100644 --- a/examples/todo/middlewares/SystemMiddleware.qml +++ b/examples/todo/middlewares/SystemMiddleware.qml @@ -1,6 +1,6 @@ import QtQuick 2.0 +import QtQuick.Window 2.0 import QuickFlux 1.1 -import QtQuick.Dialogs 1.2 import "../actions" import "../stores" @@ -8,7 +8,7 @@ Middleware { property RootStore store: MainStore - property var mainWindow: null + property Window mainWindow: null function dispatch(type, message) { if (type === ActionTypes.startApp) { diff --git a/examples/todo/stores/TodoStore.qml b/examples/todo/stores/TodoStore.qml index e0449fc..6720dc5 100644 --- a/examples/todo/stores/TodoStore.qml +++ b/examples/todo/stores/TodoStore.qml @@ -56,7 +56,7 @@ Store { title: message.title, done: false } - model.append(item); + model.insert(0, item); } } diff --git a/examples/todo/views/Footer.qml b/examples/todo/views/Footer.qml index b9f235a..fb11b96 100644 --- a/examples/todo/views/Footer.qml +++ b/examples/todo/views/Footer.qml @@ -1,31 +1,44 @@ -import QtQuick 2.0 -import QtQuick.Controls 1.0 +import QtQuick 2.1 +import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 +import org.kde.kirigami 2.7 as Kirigami import "../actions" -Item { - height: 56 +RowLayout { + id: row - function add() { - AppActions.addTask(textField.text); - textField.text = ""; + width: parent.width + implicitHeight: row.implicitHeight + + spacing: Kirigami.Units.smallSpacing + + Label { + text: i18n("To do:") + + leftPadding: Kirigami.Units.smallSpacing + rightPadding: Kirigami.Units.smallSpacing } - RowLayout { - anchors.fill: parent + Kirigami.ActionTextField { + id: textField + Layout.fillWidth: true - TextField { - id: textField - Layout.fillWidth: true - focus: true - onAccepted: add(); - } + placeholderText: i18n("New task...") - Button { - text: "ADD" - onClicked: { - add(); + focus: true + onAccepted: add(); + rightActions: Kirigami.Action { + text: i18n("Add") + // icon from Breeze (breeze-icons) package + iconName: "list-add" + visible: textField.text !== "" + onTriggered: { + textField.add(); } } + function add() { + AppActions.addTask(textField.text); + textField.text = ""; + } } } diff --git a/examples/todo/views/Header.qml b/examples/todo/views/Header.qml index 0b049c5..6888189 100644 --- a/examples/todo/views/Header.qml +++ b/examples/todo/views/Header.qml @@ -1,26 +1,28 @@ import QtQuick 2.0 -import QtQuick.Controls 1.0 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.0 +import org.kde.kirigami 2.0 as Kirigami import "../actions" import "../stores" -Item { - height: 48 +// It fills width of parent, and uses as much height as needed. +RowLayout { + width: parent.width + + Label { + text: i18n("Items:") + leftPadding: Kirigami.Units.smallSpacing + rightPadding: Kirigami.Units.smallSpacing + } CheckBox { id: checkBox - checked: false - text: "Show Completed"; - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + text: i18n("Show Completed"); + checked: MainStore.userPrefs.showCompletedTasks onCheckedChanged: { - AppActions.setShowCompletedTasks(checked); - } - - Binding { - target: checkBox - property: "checked" - value: MainStore.userPrefs.showCompletedTasks + AppActions.setShowCompletedTasks(checked, this); } } } diff --git a/examples/todo/views/TodoItem.qml b/examples/todo/views/TodoItem.qml index 3e7be9a..983d6bc 100644 --- a/examples/todo/views/TodoItem.qml +++ b/examples/todo/views/TodoItem.qml @@ -1,32 +1,74 @@ import QtQuick 2.0 -import QtQuick.Controls 1.0 -import QtQuick.Layouts 1.0 +import QtQuick.Controls 2.0 +import org.kde.kirigami 2.2 as Kirigami import "../actions" -Rectangle { +Item { id: item - color: "white" - height: 48 + + width: parent.width + implicitHeight: 48 property int uid; - property string title + property alias title: checkBox.text property alias checked: checkBox.checked - RowLayout { + CheckBox { + id: checkBox anchors.fill: parent + } + + onCheckedChanged: { + AppActions.setTaskDone(uid, checked); + } + + // QFlux is compatible with default QML states and transitions. + // However, use them with care. In particular, avoid any complex + // logic in PropertyChanges updates. + Item { + // this is just a layout container for the animated component + id: container + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: Kirigami.Units.smallSpacing + anchors.verticalCenter: parent.verticalCenter + height: 2 - CheckBox { - id: checkBox - anchors.verticalCenter: parent.verticalCenter + // animated component + Rectangle { + id: strikethrough + width: 0 + height: parent.height + + color: Kirigami.Theme.disabledTextColor + z: 1 + } + + // animation states & transitions + states: State { + name: "checked" + when: item.checked + PropertyChanges { + target: strikethrough + width: container.width + } } - Text { - text: title - Layout.fillWidth: true + transitions: Transition { + to: "checked" + reversible: true + NumberAnimation { + properties: "width" + duration: Kirigami.Units.shortDuration + easing.type: Easing.OutQuad + } } } - onCheckedChanged: { - AppActions.setTaskDone(uid,checked); + // add background to avoid overlapping during animations of surrounding items + Rectangle { + anchors.fill: parent + color: Kirigami.Theme.backgroundColor + z: -1 } } diff --git a/examples/todo/views/TodoList.qml b/examples/todo/views/TodoList.qml index 3d0f8b1..a9aa45f 100644 --- a/examples/todo/views/TodoList.qml +++ b/examples/todo/views/TodoList.qml @@ -1,15 +1,68 @@ import QtQuick 2.0 -import QuickFlux 1.0 -import QtQuick.Controls 1.0 -import QtQuick.Layouts 1.0 -import "../stores" +import org.kde.kirigami 2.0 as Kirigami -ScrollView { - ListView { - anchors.fill: parent +ListView { + id: listView + model: TodoVisualModel {} - model: TodoVisualModel { - id: visualModel + // In theory, animations could be handled with actions, stored etc., + // but it's better to let QtQuick manage it natively. + // + // Cascade effect is taken from Qt docs: + // https://doc.qt.io/qt-5/qml-qtquick-viewtransition.html#animating-items-to-intermediate-positions + + // Slides in right from the above. + add: Transition { + id: addTransition + NumberAnimation { + property: "y" + from: _getPrevItemPosition(addTransition.ViewTransition.index).y + duration: Kirigami.Units.veryLongDuration + easing.type: Easing.OutBounce } } + + // Just moves to the new place with animation. + displaced: Transition { + NumberAnimation { + property: "y" + duration: Kirigami.Units.veryLongDuration + easing.type: Easing.OutBounce + } + } + + // Swipes out to the right, cascading timing. + remove: Transition { + id: removeTransition + SequentialAnimation { + PauseAnimation { + duration: { + const offset = (removeTransition.ViewTransition.index + - Math.min.apply(null, removeTransition.ViewTransition.targetIndexes)); + const duration = Kirigami.Units.shortDuration / 2; + return offset * duration; + } + } + ParallelAnimation { + NumberAnimation { + property: "x" + to: removeTransition.ViewTransition.item.width + duration: Kirigami.Units.shortDuration + easing.type: Easing.InQuad + } + NumberAnimation { + property: "opacity" + to: 0 + duration: Kirigami.Units.shortDuration + easing.type: Easing.InQuad + } + } + } + } + + function _getPrevItemPosition(index) { + const prevIdx = index - 1; + const prevItem = listView.itemAtIndex(prevIdx); + return listView.mapFromItem(prevItem, 0, 0); + } } diff --git a/examples/todo/views/TodoVisualModel.qml b/examples/todo/views/TodoVisualModel.qml index 33010da..501b9ab 100644 --- a/examples/todo/views/TodoVisualModel.qml +++ b/examples/todo/views/TodoVisualModel.qml @@ -21,9 +21,11 @@ VisualDataModel { uid: model.uid title: model.title checked: model.done + // for animations + z: -index Component.onCompleted: { - item.VisualDataModel.inNonCompleted = Qt.binding(function() { return !model.done}) + item.VisualDataModel.inNonCompleted = Qt.binding(() => !model.done) } } }