shift-shell/initialstart/modules/deviceprofile/contents/ui/main.qml
Marco Allegretti 42d41351e2 Add profile-aware initial setup
Detect the device class, stage the selected experience, and write the resulting setup choices through SetupState.

Load the new device and experience modules before the existing setup pages, and use the Shift icon on the finished page.
2026-05-11 10:03:07 +02:00

174 lines
6.8 KiB
QML

// SPDX-FileCopyrightText: 2026 Marco Allegretti
// SPDX-License-Identifier: EUPL-1.2
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.plasma.mobileinitialstart.initialstart
InitialStartModule {
name: i18n("Device")
contentItem: Item {
id: root
readonly property real cardWidth: Math.min(Kirigami.Units.gridUnit * 30, root.width - Kirigami.Units.gridUnit * 2)
function chooseDevice(deviceClass, primaryInput) {
SetupState.applyDeviceDefaults(deviceClass, primaryInput)
}
function selectedDeviceLabel() {
switch (SetupState.deviceClass) {
case "phone":
return i18n("Phone")
case "tablet":
return i18n("Tablet or 2-in-1")
case "laptop":
return i18n("Laptop")
case "desktop":
return i18n("Desktop PC")
case "handheld":
return i18n("Gaming handheld")
case "mini-pc":
return i18n("Gaming PC")
case "dual-screen":
return i18n("Dual-screen device")
case "foldable":
return i18n("Foldable device")
default:
return SetupState.deviceClass
}
}
function selectedInputLabel() {
switch (SetupState.primaryInput) {
case "touch":
return i18n("touch")
case "keyboardMouse":
return i18n("keyboard and pointer")
case "gamepad":
return i18n("gamepad")
default:
return SetupState.primaryInput
}
}
ScrollView {
anchors {
fill: parent
topMargin: Kirigami.Units.gridUnit
}
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
contentWidth: -1
ColumnLayout {
width: root.width
spacing: Kirigami.Units.gridUnit
Label {
Layout.leftMargin: Kirigami.Units.gridUnit
Layout.rightMargin: Kirigami.Units.gridUnit
Layout.alignment: Qt.AlignTop
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
text: i18n("What are you setting up SHIFT on?")
}
FormCard.FormCard {
maximumWidth: root.cardWidth
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
FormCard.FormTextDelegate {
text: i18n("Current selection")
description: i18n("%1, controlled with %2", root.selectedDeviceLabel(), root.selectedInputLabel())
}
FormCard.FormButtonDelegate {
text: i18n("Use Hardware Recommendation")
icon.name: "emblem-ok-symbolic"
onClicked: SetupState.useRecommendedSettings()
}
FormCard.FormDelegateSeparator {}
FormCard.FormRadioDelegate {
text: i18n("Phone")
description: i18n("Pocket touch device. Starts with the simple mobile home screen and full-screen apps.")
onClicked: root.chooseDevice("phone", "touch")
Binding on checked {
value: SetupState.deviceClass === "phone"
}
}
FormCard.FormRadioDelegate {
text: i18n("Tablet or 2-in-1")
description: i18n("Touch device that may rotate, dock, or use a keyboard. Starts with adaptive defaults.")
onClicked: root.chooseDevice("tablet", "touch")
Binding on checked {
value: SetupState.deviceClass === "tablet"
}
}
FormCard.FormRadioDelegate {
text: i18n("Laptop or Desktop")
description: i18n("Keyboard and pointer computer. Starts with windows, Overview, dock, tiling, and snap layouts.")
onClicked: root.chooseDevice(DeviceContext.hasBattery ? "laptop" : "desktop", "keyboardMouse")
Binding on checked {
value: SetupState.deviceClass === "laptop" || SetupState.deviceClass === "desktop"
}
}
FormCard.FormRadioDelegate {
text: i18n("Gaming PC or Handheld")
description: i18n("Gamepad-first setup for a handheld, console-style mini PC, or living-room gaming device.")
onClicked: root.chooseDevice(DeviceContext.hasBattery ? "handheld" : "mini-pc", "gamepad")
Binding on checked {
value: SetupState.deviceClass === "handheld" || SetupState.deviceClass === "mini-pc"
}
}
FormCard.FormRadioDelegate {
text: i18n("Dual-screen or Foldable")
description: i18n("Hardware whose screen layout changes by posture, hinge, external display, or dock.")
onClicked: root.chooseDevice(DeviceContext.displayCount > 1 ? "dual-screen" : "foldable", SetupState.primaryInput)
Binding on checked {
value: SetupState.deviceClass === "dual-screen" || SetupState.deviceClass === "foldable"
}
}
}
FormCard.FormCard {
maximumWidth: root.cardWidth
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
FormCard.FormTextDelegate {
text: i18n("Detected context")
description: i18n("Recommended: %1 with %2 layout. Displays: %3, Touch: %4, Battery: %5",
DeviceContext.recommendedDeviceClass,
DeviceContext.recommendedExperienceProfile,
DeviceContext.displayCount,
DeviceContext.hasTouch ? i18n("yes") : i18n("no"),
DeviceContext.hasBattery ? i18n("yes") : i18n("no"))
}
}
Item {
Layout.fillHeight: true
}
}
}
}
}