feat: add panels page + subpages

This commit is contained in:
2 * r + 2 * t 2026-06-07 18:01:13 +10:00
parent 7f2fafb6fe
commit 75fb84b0f6
8 changed files with 898 additions and 0 deletions

View file

@ -9,6 +9,7 @@ import qs.modules.nexus.common
import qs.modules.nexus.pages
import qs.modules.nexus.pages.audio
import qs.modules.nexus.pages.bluetooth
import qs.modules.nexus.pages.panels
import qs.modules.nexus.pages.wallandstyle
QtObject {
@ -67,6 +68,36 @@ QtObject {
AppVolumes {}
}
}
},
// System
Component {
PlaceholderComp {}
},
Component {
PlaceholderComp {}
},
// Shell
Component {
// Panels
StackPage {
Component {
PanelsPage {}
}
Component {
DashboardPanel {}
}
Component {
TaskbarPanel {}
}
Component {
LauncherPanel {}
}
Component {
SidebarPanel {}
}
}
}
]

View file

@ -0,0 +1,18 @@
import QtQuick
import QtQuick.Layouts
import Caelestia.Config
import qs.components
import qs.services
StyledText {
property bool first
Layout.fillWidth: true
Layout.topMargin: first ? 0 : Tokens.spacing.largeIncreased - ((parent as ColumnLayout).spacing ?? 0)
Layout.bottomMargin: Tokens.spacing.extraSmall
Layout.leftMargin: Tokens.padding.small
color: Colours.palette.m3onSurfaceVariant
font: Tokens.font.label.medium
elide: Text.ElideRight
}

View file

@ -0,0 +1,64 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Caelestia.Config
import qs.components
import qs.components.controls
import qs.services
import qs.modules.nexus.common
ConnectedRect {
id: root
property alias label: label.text
property string subtext
property real value
property real from: 0
property real to: 99
property real stepSize: 1
signal moved(value: real)
implicitHeight: rowLayout.implicitHeight + rowLayout.anchors.margins * 2
RowLayout {
id: rowLayout
anchors.fill: parent
anchors.margins: Tokens.padding.medium
anchors.leftMargin: Tokens.padding.largeIncreased
anchors.rightMargin: Tokens.padding.largeIncreased
spacing: Tokens.spacing.medium
ColumnLayout {
Layout.fillWidth: true
spacing: 0
StyledText {
id: label
Layout.fillWidth: true
font: Tokens.font.body.small
elide: Text.ElideRight
}
StyledText {
Layout.fillWidth: true
visible: root.subtext
text: root.subtext
color: Colours.palette.m3outline
font: Tokens.font.label.small
elide: Text.ElideRight
}
}
CustomSpinBox {
min: root.from
max: root.to
step: root.stepSize
value: root.value
onValueModified: v => root.moved(v)
}
}
}

View file

@ -0,0 +1,114 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Caelestia.Config
import qs.components
import qs.services
import qs.modules.nexus.common
PageBase {
id: root
title: qsTr("Panels")
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
width: root.cappedWidth
spacing: Tokens.spacing.extraSmall / 2
NavRow {
first: true
icon: "dashboard"
label: qsTr("Dashboard")
status: Config.dashboard.enabled ? qsTr("Enabled") : qsTr("Disabled")
target: 1
}
NavRow {
icon: "dock_to_bottom"
label: qsTr("Taskbar")
status: Config.bar.persistent ? qsTr("Always visible") : qsTr("Reveal on hover")
target: 2
}
NavRow {
icon: "apps"
label: qsTr("Launcher")
status: Config.launcher.enabled ? qsTr("Enabled") : qsTr("Disabled")
target: 3
}
NavRow {
last: true
icon: "dock_to_right"
label: qsTr("Sidebar")
status: Config.sidebar.enabled ? qsTr("Enabled") : qsTr("Disabled")
target: 4
}
}
component NavRow: ConnectedRect {
id: navRow
property alias icon: icon.text
property alias label: label.text
property alias status: status.text
property int target
Layout.fillWidth: true
implicitHeight: navLayout.implicitHeight + navLayout.anchors.topMargin + navLayout.anchors.bottomMargin
StateLayer {
onClicked: root.nState.openSubPage(navRow.target)
}
RowLayout {
id: navLayout
anchors.fill: parent
anchors.leftMargin: Tokens.padding.largeIncreased
anchors.rightMargin: Tokens.padding.largeIncreased
anchors.topMargin: Tokens.padding.medium
anchors.bottomMargin: Tokens.padding.medium
spacing: Tokens.spacing.medium
MaterialIcon {
id: icon
color: Colours.palette.m3onSurfaceVariant
font: Tokens.font.icon.medium
}
ColumnLayout {
Layout.fillWidth: true
spacing: 0
StyledText {
id: label
Layout.fillWidth: true
font: Tokens.font.body.small
elide: Text.ElideRight
}
StyledText {
id: status
Layout.fillWidth: true
color: Colours.palette.m3outline
font: Tokens.font.label.small
elide: Text.ElideRight
animate: true
}
}
MaterialIcon {
text: "chevron_right"
color: Colours.palette.m3onSurfaceVariant
font: Tokens.font.icon.medium
}
}
}
}

View file

@ -0,0 +1,146 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Caelestia.Config
import qs.components
import qs.modules.nexus.common
PageBase {
id: root
title: qsTr("Dashboard")
isSubPage: true
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
width: root.cappedWidth
spacing: Tokens.spacing.extraSmall / 2
// General
SectionHeader {
first: true
text: qsTr("General")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Enabled")
checked: Config.dashboard.enabled
onToggled: GlobalConfig.dashboard.enabled = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Show on hover")
subtext: qsTr("Reveal when the cursor reaches the screen edge")
checked: Config.dashboard.showOnHover
onToggled: GlobalConfig.dashboard.showOnHover = checked
}
// Tabs
SectionHeader {
text: qsTr("Tabs")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Dashboard")
checked: Config.dashboard.showDashboard
onToggled: GlobalConfig.dashboard.showDashboard = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Media")
checked: Config.dashboard.showMedia
onToggled: GlobalConfig.dashboard.showMedia = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Performance")
checked: Config.dashboard.showPerformance
onToggled: GlobalConfig.dashboard.showPerformance = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Weather")
checked: Config.dashboard.showWeather
onToggled: GlobalConfig.dashboard.showWeather = checked
}
// Performance widgets
SectionHeader {
text: qsTr("Performance widgets")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Battery")
checked: Config.dashboard.performance.showBattery
onToggled: GlobalConfig.dashboard.performance.showBattery = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("GPU")
checked: Config.dashboard.performance.showGpu
onToggled: GlobalConfig.dashboard.performance.showGpu = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("CPU")
checked: Config.dashboard.performance.showCpu
onToggled: GlobalConfig.dashboard.performance.showCpu = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Memory")
checked: Config.dashboard.performance.showMemory
onToggled: GlobalConfig.dashboard.performance.showMemory = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Storage")
checked: Config.dashboard.performance.showStorage
onToggled: GlobalConfig.dashboard.performance.showStorage = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Network")
checked: Config.dashboard.performance.showNetwork
onToggled: GlobalConfig.dashboard.performance.showNetwork = checked
}
// Behaviour
SectionHeader {
text: qsTr("Behaviour")
}
StepperRow {
Layout.fillWidth: true
first: true
last: true
label: qsTr("Drag threshold")
subtext: qsTr("Pixels dragged before the dashboard opens")
value: Config.dashboard.dragThreshold
from: 0
to: 200
stepSize: 5
onMoved: v => GlobalConfig.dashboard.dragThreshold = v
}
}
}

View file

@ -0,0 +1,147 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Caelestia.Config
import qs.components
import qs.modules.nexus.common
PageBase {
id: root
title: qsTr("Launcher")
isSubPage: true
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
width: root.cappedWidth
spacing: Tokens.spacing.extraSmall / 2
// General
SectionHeader {
first: true
text: qsTr("General")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Enabled")
checked: Config.launcher.enabled
onToggled: GlobalConfig.launcher.enabled = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Show on hover")
subtext: qsTr("Reveal when the cursor reaches the screen edge")
checked: Config.launcher.showOnHover
onToggled: GlobalConfig.launcher.showOnHover = checked
}
// Display
SectionHeader {
text: qsTr("Display")
}
StepperRow {
Layout.fillWidth: true
first: true
label: qsTr("Max items shown")
value: Config.launcher.maxShown
from: 1
to: 20
stepSize: 1
onMoved: v => GlobalConfig.launcher.maxShown = v
}
StepperRow {
Layout.fillWidth: true
label: qsTr("Max wallpapers")
value: Config.launcher.maxWallpapers
from: 1
to: 30
stepSize: 1
onMoved: v => GlobalConfig.launcher.maxWallpapers = v
}
StepperRow {
Layout.fillWidth: true
last: true
label: qsTr("Drag threshold")
subtext: qsTr("Pixels dragged before the launcher opens")
value: Config.launcher.dragThreshold
from: 0
to: 200
stepSize: 5
onMoved: v => GlobalConfig.launcher.dragThreshold = v
}
// Behaviour
SectionHeader {
text: qsTr("Behaviour")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Vim keybinds")
subtext: qsTr("Navigate results with Ctrl+hjkl")
checked: GlobalConfig.launcher.vimKeybinds
onToggled: GlobalConfig.launcher.vimKeybinds = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Enable dangerous actions")
subtext: qsTr("Allow actions that shut down or log out")
checked: GlobalConfig.launcher.enableDangerousActions
onToggled: GlobalConfig.launcher.enableDangerousActions = checked
}
// Fuzzy search
SectionHeader {
text: qsTr("Fuzzy search")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Apps")
checked: GlobalConfig.launcher.useFuzzy.apps
onToggled: GlobalConfig.launcher.useFuzzy.apps = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Actions")
checked: GlobalConfig.launcher.useFuzzy.actions
onToggled: GlobalConfig.launcher.useFuzzy.actions = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Schemes")
checked: GlobalConfig.launcher.useFuzzy.schemes
onToggled: GlobalConfig.launcher.useFuzzy.schemes = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Variants")
checked: GlobalConfig.launcher.useFuzzy.variants
onToggled: GlobalConfig.launcher.useFuzzy.variants = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Wallpapers")
checked: GlobalConfig.launcher.useFuzzy.wallpapers
onToggled: GlobalConfig.launcher.useFuzzy.wallpapers = checked
}
}
}

View file

@ -0,0 +1,46 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Caelestia.Config
import qs.components
import qs.modules.nexus.common
PageBase {
id: root
title: qsTr("Sidebar")
isSubPage: true
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
width: root.cappedWidth
spacing: Tokens.spacing.extraSmall / 2
SectionHeader {
first: true
text: qsTr("General")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Enabled")
checked: Config.sidebar.enabled
onToggled: GlobalConfig.sidebar.enabled = checked
}
StepperRow {
Layout.fillWidth: true
last: true
label: qsTr("Drag threshold")
subtext: qsTr("Pixels dragged before the sidebar opens")
value: Config.sidebar.dragThreshold
from: 0
to: 200
stepSize: 5
onMoved: v => GlobalConfig.sidebar.dragThreshold = v
}
}
}

View file

@ -0,0 +1,332 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Caelestia.Config
import qs.components
import qs.modules.nexus.common
PageBase {
id: root
title: qsTr("Taskbar")
isSubPage: true
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
width: root.cappedWidth
spacing: Tokens.spacing.extraSmall / 2
// Behaviour
SectionHeader {
first: true
text: qsTr("Behaviour")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Persistent")
subtext: qsTr("Keep the bar visible at all times")
checked: Config.bar.persistent
onToggled: GlobalConfig.bar.persistent = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Show on hover")
subtext: qsTr("Reveal the bar when the cursor reaches the screen edge")
checked: Config.bar.showOnHover
onToggled: GlobalConfig.bar.showOnHover = checked
}
StepperRow {
Layout.fillWidth: true
last: true
label: qsTr("Drag threshold")
subtext: qsTr("Pixels dragged before the bar reveals")
value: Config.bar.dragThreshold
from: 0
to: 200
stepSize: 5
onMoved: v => GlobalConfig.bar.dragThreshold = v
}
// Workspaces
SectionHeader {
text: qsTr("Workspaces")
}
StepperRow {
Layout.fillWidth: true
first: true
label: qsTr("Shown")
subtext: qsTr("Number of workspaces displayed")
value: Config.bar.workspaces.shown
from: 1
to: 20
stepSize: 1
onMoved: v => GlobalConfig.bar.workspaces.shown = v
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Active indicator")
checked: Config.bar.workspaces.activeIndicator
onToggled: GlobalConfig.bar.workspaces.activeIndicator = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Active trail")
checked: Config.bar.workspaces.activeTrail
onToggled: GlobalConfig.bar.workspaces.activeTrail = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Occupied background")
checked: Config.bar.workspaces.occupiedBg
onToggled: GlobalConfig.bar.workspaces.occupiedBg = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Show windows")
subtext: qsTr("Show icons of open windows on each workspace")
checked: Config.bar.workspaces.showWindows
onToggled: GlobalConfig.bar.workspaces.showWindows = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Windows on special workspaces")
checked: Config.bar.workspaces.showWindowsOnSpecialWorkspaces
onToggled: GlobalConfig.bar.workspaces.showWindowsOnSpecialWorkspaces = checked
}
StepperRow {
Layout.fillWidth: true
label: qsTr("Max window icons")
value: Config.bar.workspaces.maxWindowIcons
from: 0
to: 20
stepSize: 1
onMoved: v => GlobalConfig.bar.workspaces.maxWindowIcons = v
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Per-monitor workspaces")
subtext: qsTr("Show each monitor's workspaces independently")
checked: GlobalConfig.bar.workspaces.perMonitorWorkspaces
onToggled: GlobalConfig.bar.workspaces.perMonitorWorkspaces = checked
}
// Active window
SectionHeader {
text: qsTr("Active window")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Compact")
checked: Config.bar.activeWindow.compact
onToggled: GlobalConfig.bar.activeWindow.compact = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Inverted")
checked: Config.bar.activeWindow.inverted
onToggled: GlobalConfig.bar.activeWindow.inverted = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Show on hover")
checked: Config.bar.activeWindow.showOnHover
onToggled: GlobalConfig.bar.activeWindow.showOnHover = checked
}
// Tray
SectionHeader {
text: qsTr("Tray")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Background")
checked: Config.bar.tray.background
onToggled: GlobalConfig.bar.tray.background = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Recolour icons")
checked: Config.bar.tray.recolour
onToggled: GlobalConfig.bar.tray.recolour = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Compact")
checked: Config.bar.tray.compact
onToggled: GlobalConfig.bar.tray.compact = checked
}
// Status icons
SectionHeader {
text: qsTr("Status icons")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Speakers")
checked: Config.bar.status.showAudio
onToggled: GlobalConfig.bar.status.showAudio = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Microphone")
checked: Config.bar.status.showMicrophone
onToggled: GlobalConfig.bar.status.showMicrophone = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Keyboard layout")
checked: Config.bar.status.showKbLayout
onToggled: GlobalConfig.bar.status.showKbLayout = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Network")
checked: Config.bar.status.showNetwork
onToggled: GlobalConfig.bar.status.showNetwork = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Wi-Fi")
checked: Config.bar.status.showWifi
onToggled: GlobalConfig.bar.status.showWifi = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Bluetooth")
checked: Config.bar.status.showBluetooth
onToggled: GlobalConfig.bar.status.showBluetooth = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Battery")
checked: Config.bar.status.showBattery
onToggled: GlobalConfig.bar.status.showBattery = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Caps lock")
checked: Config.bar.status.showLockStatus
onToggled: GlobalConfig.bar.status.showLockStatus = checked
}
// Clock
SectionHeader {
text: qsTr("Clock")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Background")
checked: Config.bar.clock.background
onToggled: GlobalConfig.bar.clock.background = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Show date")
checked: Config.bar.clock.showDate
onToggled: GlobalConfig.bar.clock.showDate = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Show icon")
checked: Config.bar.clock.showIcon
onToggled: GlobalConfig.bar.clock.showIcon = checked
}
// Scroll actions
SectionHeader {
text: qsTr("Scroll actions")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Workspaces")
subtext: qsTr("Scroll over the bar to switch workspaces")
checked: Config.bar.scrollActions.workspaces
onToggled: GlobalConfig.bar.scrollActions.workspaces = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Volume")
checked: Config.bar.scrollActions.volume
onToggled: GlobalConfig.bar.scrollActions.volume = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Brightness")
checked: Config.bar.scrollActions.brightness
onToggled: GlobalConfig.bar.scrollActions.brightness = checked
}
// Popouts
SectionHeader {
text: qsTr("Popouts")
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Active window")
checked: Config.bar.popouts.activeWindow
onToggled: GlobalConfig.bar.popouts.activeWindow = checked
}
ToggleRow {
Layout.fillWidth: true
text: qsTr("Tray")
checked: Config.bar.popouts.tray
onToggled: GlobalConfig.bar.popouts.tray = checked
}
ToggleRow {
Layout.fillWidth: true
last: true
text: qsTr("Status icons")
checked: Config.bar.popouts.statusIcons
onToggled: GlobalConfig.bar.popouts.statusIcons = checked
}
}
}