Krolyxon
Commit fb9b856

Branches

Refs →

aurora.configquickshellauroraSettingsApp.qml

170 lines · 7.8 KB · QML

1import QtQuick
2import QtQuick.Layouts
3import Quickshell
4
5// The settings app: a normal Hyprland window (class org.quickshell, title "aurora settings"; floated + sized by a
6// window rule). Sidebar of sections, one Loader so only the shown section runs (net scans, bt discovery).
7// Esc closes, Ctrl+Tab / Ctrl+Shift+Tab (or Ctrl+J/K) cycle sections. Opened with the `settings [section]` IPC.
8FloatingWindow {
9 id: win
10 property bool opened: false
11 property string section: "network"
12 signal closeRequested()
13 signal sectionRequested(string name)
14 signal overlayRequested(string name)
15
16 visible: opened
17 title: "aurora settings"
18 implicitWidth: 960
19 implicitHeight: 680
20 color: Theme.bg
21 // closed by the compositor (killactive): keep shell state in sync
22 onVisibleChanged: if (!visible && opened) closeRequested()
23
24 readonly property var sections: [
25 { id: "network", icon: Theme.iWifi, name: "network", group: "connections" },
26 { id: "bluetooth", icon: Theme.iBt, name: "bluetooth", group: "connections" },
27 { id: "sound", icon: Theme.iVolHigh, name: "sound", group: "connections" },
28 { id: "appearance", icon: Theme.iPalette, name: "appearance", group: "look" },
29 { id: "shell", icon: Theme.iDock, name: "shell", group: "look" },
30 { id: "windows", icon: Theme.iWindow, name: "windows", group: "hyprland" },
31 { id: "input", icon: Theme.iMouse, name: "input", group: "hyprland" },
32 { id: "keybinds", icon: Theme.iKeyboard, name: "keybinds", group: "hyprland" },
33 { id: "display", icon: Theme.iMonitor, name: "display", group: "system" },
34 { id: "power", icon: Theme.iPower, name: "power", group: "system" },
35 { id: "about", icon: Theme.iArch, name: "about", group: "system" }
36 ]
37 readonly property int index: {
38 for (var i = 0; i < sections.length; i++) if (sections[i].id === section) return i
39 return 0
40 }
41 function cycle(d) { sectionRequested(sections[(index + d + sections.length) % sections.length].id) }
42
43 Item {
44 anchors.fill: parent
45 focus: true
46 Keys.onPressed: e => {
47 var ctrl = e.modifiers & Qt.ControlModifier
48 if (e.key === Qt.Key_Escape) { win.closeRequested(); e.accepted = true }
49 else if (ctrl && (e.key === Qt.Key_Tab || e.key === Qt.Key_J)) { win.cycle(1); e.accepted = true }
50 else if (ctrl && (e.key === Qt.Key_Backtab || e.key === Qt.Key_K)) { win.cycle(-1); e.accepted = true }
51 }
52
53 RowLayout {
54 anchors.fill: parent
55 spacing: 0
56
57 // sidebar
58 Rectangle {
59 Layout.fillHeight: true
60 Layout.preferredWidth: 200
61 color: Theme.surface
62 ColumnLayout {
63 anchors.fill: parent
64 anchors.margins: 10
65 spacing: 2
66 Text {
67 Layout.bottomMargin: 8
68 text: Theme.iCog + " aurora settings"
69 color: Theme.accent
70 font.family: Theme.font
71 font.pixelSize: Theme.fontSize + 1
72 font.bold: true
73 }
74 Repeater {
75 model: win.sections
76 delegate: ColumnLayout {
77 id: entry
78 required property var modelData
79 required property int index
80 readonly property bool current: win.section === modelData.id
81 readonly property bool firstOfGroup: index === 0 || win.sections[index - 1].group !== modelData.group
82 Layout.fillWidth: true
83 spacing: 2
84 Text {
85 visible: entry.firstOfGroup
86 Layout.topMargin: entry.index === 0 ? 0 : 8
87 text: entry.modelData.group.toUpperCase()
88 color: Theme.dim
89 font.family: Theme.font
90 font.pixelSize: Theme.fontSize - 3
91 font.letterSpacing: 1.5
92 }
93 Rectangle {
94 Layout.fillWidth: true
95 implicitHeight: 30
96 color: entry.current ? Theme.accent : (em.containsMouse ? Theme.surfaceHi : "transparent")
97 Text {
98 anchors.verticalCenter: parent.verticalCenter
99 x: 10
100 text: entry.modelData.icon + " " + entry.modelData.name
101 color: entry.current ? Theme.bg : Theme.fg
102 font.family: Theme.font
103 font.pixelSize: Theme.fontSize
104 font.bold: entry.current
105 }
106 MouseArea {
107 id: em
108 anchors.fill: parent
109 hoverEnabled: true
110 cursorShape: Qt.PointingHandCursor
111 onClicked: win.sectionRequested(entry.modelData.id)
112 }
113 }
114 }
115 }
116 Item { Layout.fillHeight: true }
117 }
118 }
119 Rectangle { Layout.fillHeight: true; Layout.preferredWidth: 1; color: Theme.line }
120
121 // content
122 ColumnLayout {
123 Layout.fillWidth: true
124 Layout.fillHeight: true
125 Layout.margins: 16
126 spacing: 12
127 Text {
128 text: win.sections[win.index].name.toUpperCase()
129 color: Theme.fg
130 font.family: Theme.font
131 font.pixelSize: Theme.fontSize + 4
132 font.bold: true
133 font.letterSpacing: 2
134 }
135 Loader {
136 Layout.fillWidth: true
137 Layout.fillHeight: true
138 active: win.opened
139 sourceComponent: {
140 switch (win.section) {
141 case "bluetooth": return btC
142 case "sound": return soundC
143 case "appearance": return appearanceC
144 case "shell": return shellC
145 case "windows": return windowsC
146 case "input": return inputC
147 case "keybinds": return keysC
148 case "display": return displayC
149 case "power": return powerC
150 case "about": return aboutC
151 default: return netC
152 }
153 }
154 }
155 }
156 }
157 }
158
159 Component { id: netC; NetPage { active: true } }
160 Component { id: btC; BtPage { active: true } }
161 Component { id: soundC; AudioPage {} }
162 Component { id: appearanceC; SetAppearance { onOverlayRequested: name => win.overlayRequested(name) } }
163 Component { id: shellC; SetShell {} }
164 Component { id: windowsC; SetWindows {} }
165 Component { id: inputC; SetInput {} }
166 Component { id: keysC; SetKeys {} }
167 Component { id: displayC; SetDisplay {} }
168 Component { id: powerC; SetPower {} }
169 Component { id: aboutC; SetAbout {} }
170}