shift-shell/initialstart/qml/Wizard.qml

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

342 lines
10 KiB
QML
Raw Normal View History

// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.20 as Kirigami
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
import initialstart 1.0 as InitialStart
Kirigami.Page {
id: root
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
property int currentIndex: 0
property int stepCount: 0
property bool showingLanding: true
// filled by items
property var currentStepItem
property var nextStepItem
property var previousStepItem
readonly property bool onFinalPage: currentIndex === (stepCount - 1)
// step animation
// manually doing the animation is more performant and less glitchy with window resize than a SwipeView
property real previousStepItemX: 0
property real currentStepItemX: 0
property real nextStepItemX: 0
NumberAnimation on previousStepItemX {
id: previousStepAnim
duration: 400
easing.type: Easing.OutExpo
onFinished: {
if (root.previousStepItemX != 0) {
root.previousStepItem.visible = false;
}
}
}
NumberAnimation on currentStepItemX {
id: currentStepAnim
duration: 400
easing.type: Easing.OutExpo
}
NumberAnimation on nextStepItemX {
id: nextStepAnim
duration: 400
easing.type: Easing.OutExpo
onFinished: {
if (root.nextStepItemX != 0) {
root.nextStepItem.visible = false;
}
}
}
function finishFinalPage() {
InitialStart.Wizard.wizardFinished();
applicationWindow().close();
}
function requestNextPage() {
if (previousStepAnim.running || currentStepAnim.running || nextStepAnim.running) {
return;
}
previousStepItemX = 0;
currentIndex++;
stepHeading.changeText(currentStepItem.name);
currentStepItemX = root.width;
currentStepItem.visible = true;
previousStepAnim.to = -root.width;
previousStepAnim.restart();
currentStepAnim.to = 0;
currentStepAnim.restart();
}
function requestPreviousPage() {
if (previousStepAnim.running || currentStepAnim.running || nextStepAnim.running) {
return;
}
if (currentIndex === 0) {
root.showingLanding = true;
landingComponent.returnToLanding();
} else {
nextStepItemX = 0;
currentIndex--;
stepHeading.changeText(currentStepItem.name);
currentStepItemX = -root.width;
currentStepItem.visible = true;
nextStepAnim.to = root.width;
nextStepAnim.restart();
currentStepAnim.to = 0;
currentStepAnim.restart();
}
}
// top status bar
MobileShell.StatusBar {
id: statusBar
z: 1
2023-09-27 06:06:08 +00:00
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: Kirigami.Units.gridUnit * 1.25
backgroundColor: "transparent"
showSecondRow: false
showDropShadow: true
showTime: true
disableSystemTray: true // prevent SIGABRT, since loading the system tray leads to bad... things
}
LandingComponent {
id: landingComponent
anchors.fill: parent
onRequestNextPage: {
root.showingLanding = false;
stepHeading.changeText(root.currentStepItem.name);
}
}
Item {
id: stepsComponent
anchors.fill: parent
// animation when we switch to step stage
opacity: root.showingLanding ? 0 : 1
property real translateY: root.showingLanding ? overlaySteps.height : 0
Behavior on opacity {
NumberAnimation {
duration: 1000
easing.type: Easing.OutExpo
}
}
Behavior on translateY {
NumberAnimation {
duration: 1000
easing.type: Easing.OutExpo
}
}
transform: Translate { y: stepsComponent.translateY }
// heading for all the wizard steps
Label {
id: stepHeading
opacity: 0
color: "white"
horizontalAlignment: Text.AlignHCenter
font.pointSize: 18
anchors.left: parent.left
anchors.leftMargin: Kirigami.Units.gridUnit
anchors.right: parent.right
anchors.rightMargin: Kirigami.Units.gridUnit
anchors.bottom: parent.bottom
anchors.bottomMargin: root.height * 0.7 + Kirigami.Units.gridUnit
property string toText
function changeText(text) {
toText = text;
toHidden.restart();
}
NumberAnimation on opacity {
id: toHidden
duration: 200
to: 0
onFinished: {
stepHeading.text = stepHeading.toText;
toShown.restart();
}
}
NumberAnimation on opacity {
id: toShown
duration: 200
to: 1
}
}
Rectangle {
id: overlaySteps
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
color: Kirigami.Theme.backgroundColor
anchors.fill: parent
anchors.topMargin: root.height * 0.3
// all steps are in this container
Item {
anchors.fill: parent
anchors.bottomMargin: stepFooter.implicitHeight
// setup steps
Repeater {
model: InitialStart.Wizard.steps
delegate: MobileShell.BaseItem {
id: item
visible: model.index === 0 // the binding is broken later
contentItem: modelData
transform: Translate {
x: {
if (item.currentIndex === root.currentIndex - 1) {
return previousStepItemX;
} else if (item.currentIndex === root.currentIndex + 1) {
return nextStepItemX;
} else if (item.currentIndex === root.currentIndex) {
return currentStepItemX;
}
return 0;
}
}
anchors.fill: parent
// pass up the property
property string name: contentItem.name
property int currentIndex: model.index
function updateRootItems() {
if (model.index === root.currentIndex) {
root.currentStepItem = item;
} else if (model.index === root.currentIndex - 1) {
root.previousStepItem = item;
} else if (model.index === root.currentIndex + 1) {
root.nextStepItem = item;
}
}
Component.onCompleted: {
root.stepCount++
updateRootItems();
}
// keep root properties updated
Connections {
target: root
function onCurrentIndexChanged() {
item.updateRootItems();
}
}
}
}
}
// bottom footer
RowLayout {
id: stepFooter
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
Button {
Layout.alignment: Qt.AlignLeft
Layout.leftMargin: Kirigami.Units.gridUnit
Layout.bottomMargin: Kirigami.Units.gridUnit
topPadding: Kirigami.Units.gridUnit
bottomPadding: Kirigami.Units.gridUnit
leftPadding: Kirigami.Units.gridUnit
rightPadding: Kirigami.Units.gridUnit
text: i18n("Back")
icon.name: "arrow-left"
onClicked: root.requestPreviousPage()
}
Item {}
Button {
Layout.alignment: Qt.AlignRight
Layout.rightMargin: Kirigami.Units.gridUnit
Layout.bottomMargin: Kirigami.Units.gridUnit
topPadding: Kirigami.Units.gridUnit
bottomPadding: Kirigami.Units.gridUnit
leftPadding: Kirigami.Units.gridUnit
rightPadding: Kirigami.Units.gridUnit
visible: !root.onFinalPage
text: i18n("Next")
icon.name: "arrow-right"
onClicked: root.requestNextPage();
}
Button {
Layout.alignment: Qt.AlignRight
Layout.rightMargin: Kirigami.Units.gridUnit
Layout.bottomMargin: Kirigami.Units.gridUnit
topPadding: Kirigami.Units.gridUnit
bottomPadding: Kirigami.Units.gridUnit
leftPadding: Kirigami.Units.gridUnit
rightPadding: Kirigami.Units.gridUnit
visible: root.onFinalPage
text: i18n("Finish")
icon.name: "dialog-ok"
onClicked: root.finishFinalPage();
}
}
}
}
}