From 730fcef6dee30f5c502c23d401238a87a9a15b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Thu, 26 Sep 2024 20:16:30 +0200 Subject: [PATCH] StatusQ: Introduce LazyStackLayout - stack layout with deferred instantiation (#16417) Closes: #16416 --- .../qmlTests/tests/tst_LazyStackLayout.qml | 101 ++++++++++++++++++ .../StatusQ/Core/Utils/LazyStackLayout.qml | 40 +++++++ ui/StatusQ/src/StatusQ/Core/Utils/qmldir | 1 + ui/StatusQ/src/statusq.qrc | 1 + 4 files changed, 143 insertions(+) create mode 100644 storybook/qmlTests/tests/tst_LazyStackLayout.qml create mode 100644 ui/StatusQ/src/StatusQ/Core/Utils/LazyStackLayout.qml diff --git a/storybook/qmlTests/tests/tst_LazyStackLayout.qml b/storybook/qmlTests/tests/tst_LazyStackLayout.qml new file mode 100644 index 0000000000..e1e8b0040e --- /dev/null +++ b/storybook/qmlTests/tests/tst_LazyStackLayout.qml @@ -0,0 +1,101 @@ +import QtQuick 2.15 +import QtTest 1.15 + +import StatusQ.Core.Utils 0.1 + +Item { + id: root + + width: 600 + height: 400 + + Component { + id: empty + + LazyStackLayout {} + } + + Component { + id: nonEmpty + + LazyStackLayout { + property int counter: 0 + + anchors.fill: parent + + Component { + Rectangle { + color: "green" + + Component.onCompleted: counter++ + } + } + + Component { + Rectangle { + color: "red" + + Component.onCompleted: counter++ + } + } + + Component { + Rectangle { + color: "yellow" + + Component.onCompleted: counter++ + } + } + } + } + + TestCase { + name: "LazyStackLayout" + when: windowShown + + function test_emptyLayout() { + const layout = createTemporaryObject(empty, root) + + compare(layout.count, 0) + compare(layout.currentItem, null) + } + + function test_itemsInitialization() { + const layout = createTemporaryObject(nonEmpty, root) + + compare(layout.count, 3) + compare(layout.currentIndex, 0) + compare(layout.counter, 1) + verify(layout.currentItem !== null) + verify(layout.currentItem instanceof Rectangle) + compare(layout.currentItem.color, "#008000") + + layout.currentIndex = 1 + + compare(layout.count, 3) + compare(layout.currentIndex, 1) + compare(layout.counter, 2) + verify(layout.currentItem !== null) + verify(layout.currentItem instanceof Rectangle) + compare(layout.currentItem.color, "#ff0000") + + layout.currentIndex = 0 + + compare(layout.count, 3) + compare(layout.currentIndex, 0) + compare(layout.counter, 2) + verify(layout.currentItem !== null) + verify(layout.currentItem instanceof Rectangle) + compare(layout.currentItem.color, "#008000") + + layout.currentIndex = 2 + + compare(layout.count, 3) + compare(layout.currentIndex, 2) + compare(layout.counter, 3) + verify(layout.currentItem !== null) + verify(layout.currentItem instanceof Rectangle) + compare(layout.currentItem.color, "#ffff00") + } + } +} diff --git a/ui/StatusQ/src/StatusQ/Core/Utils/LazyStackLayout.qml b/ui/StatusQ/src/StatusQ/Core/Utils/LazyStackLayout.qml new file mode 100644 index 0000000000..2a82f25c7f --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Core/Utils/LazyStackLayout.qml @@ -0,0 +1,40 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 + +/*! + \qmltype LazyStackLayout + \inherits StackLayout + \inqmlmodule StatusQ.Core.Utils + \since StatusQ.Core.Utils 0.1 + + \brief A component similar to StackLayout but operating on Component objects. + Those objects are instantiated when given index is accessed first time. + Therefore only one item is instantiated on startup, instantiation of others + is deferred, potentially resulting with more responsive UI. +*/ +StackLayout { + id: root + + default property list children + + readonly property Item currentItem: + repeater.count ? repeater.itemAt(currentIndex).item : null + + Repeater { + id: repeater + + model: root.children.length + + delegate: Loader { + active: false + sourceComponent: root.children[model.index] + + onVisibleChanged: { + if (visible) + active = true + } + + Component.onCompleted: active = visible + } + } +} diff --git a/ui/StatusQ/src/StatusQ/Core/Utils/qmldir b/ui/StatusQ/src/StatusQ/Core/Utils/qmldir index 8bfaec233d..e6b99df069 100644 --- a/ui/StatusQ/src/StatusQ/Core/Utils/qmldir +++ b/ui/StatusQ/src/StatusQ/Core/Utils/qmldir @@ -5,6 +5,7 @@ DoubleFlickable 0.1 DoubleFlickable.qml DoubleFlickableWithFolding 0.1 DoubleFlickableWithFolding.qml EmojiJSON 1.0 emojiList.js JSONListModel 0.1 JSONListModel.qml +LazyStackLayout 0.1 LazyStackLayout.qml ModelChangeGuard 0.1 ModelChangeGuard.qml ModelChangeTracker 0.1 ModelChangeTracker.qml ModelsComparator 0.1 ModelsComparator.qml diff --git a/ui/StatusQ/src/statusq.qrc b/ui/StatusQ/src/statusq.qrc index 59afeb7fc6..b14093a45e 100644 --- a/ui/StatusQ/src/statusq.qrc +++ b/ui/StatusQ/src/statusq.qrc @@ -199,6 +199,7 @@ StatusQ/Core/Utils/DoubleFlickableWithFolding.qml StatusQ/Core/Utils/Emoji.qml StatusQ/Core/Utils/JSONListModel.qml + StatusQ/Core/Utils/LazyStackLayout.qml StatusQ/Core/Utils/ModelChangeGuard.qml StatusQ/Core/Utils/ModelChangeTracker.qml StatusQ/Core/Utils/ModelUtils.qml