Krolyxon
Commit 53e4da3

Branches

Refs →

aurora53e4da3

aurora: add settings tab persisted to ~/.config/aurora/settings.json

Theme knobs, accent, desktop widgets, visualizer bars and OSD timeout are
now live-editable. Also adds a `tab <name>` IPC alias since the qs CLI
swallows `show`.
Author
krolyxon
Date
2026-10-17 15:06 +0530
Parent
a5716dc
Commit
53e4da3a7b02326b2f2e0e974be7281dcca056c6

+229 −16

9 files changed

  1. M .config/quickshell/aurora/Cava.qml +2 −2
  2. M .config/quickshell/aurora/ControlPanel.qml +3 −1
  3. M .config/quickshell/aurora/Desktop.qml +2 −2
  4. M .config/quickshell/aurora/Osd.qml +1 −1
  5. A .config/quickshell/aurora/Settings.qml +72 −0
  6. A .config/quickshell/aurora/SettingsPage.qml +134 −0
  7. M .config/quickshell/aurora/Theme.qml +10 −8
  8. M .config/quickshell/aurora/Wall.qml +2 −1
  9. M .config/quickshell/aurora/shell.qml +3 −1
M .config/quickshell/aurora/Cava.qml View
@@ -8,8 +8,8 @@ import Quickshell.Services.Mpris
88 // playing and something wants it (`wanted`), so it costs nothing when idle. Hidden if cava is missing.
99 Singleton {
1010 id: root
11− property int bars: 64
12− property bool wanted: true // desktop visualizer enabled
11+ readonly property int bars: Math.max(8, Settings.vizBars)
12+ readonly property bool wanted: Settings.desktopViz
1313 property bool available: false
1414 property var values: [] // 0..1 per bar
1515
M .config/quickshell/aurora/ControlPanel.qml View
@@ -36,7 +36,8 @@ PanelWindow {
3636 { icon: Theme.iWifi, name: "net" },
3737 { icon: Theme.iBt, name: "bt" },
3838 { icon: Theme.iChip, name: "system" },
39− { icon: Theme.iBell, name: "notifs" }
39+ { icon: Theme.iBell, name: "notifs" },
40+ { icon: Theme.iCog, name: "settings" }
4041 ]
4142
4243 Rectangle {
@@ -113,6 +114,7 @@ PanelWindow {
113114 BtPage { active: win.opened && win.tab === 3 }
114115 SysPage {}
115116 NotifPage {}
117+ SettingsPage {}
116118 }
117119 }
118120 }
M .config/quickshell/aurora/Desktop.qml View
@@ -9,8 +9,8 @@ PanelWindow {
99 id: win
1010 required property var modelData
1111 screen: modelData
12− property bool showClock: true
13− property bool showViz: true
12+ readonly property bool showClock: Settings.desktopClock
13+ readonly property bool showViz: Settings.desktopViz
1414
1515 anchors { top: true; bottom: true; left: true; right: true }
1616 exclusionMode: ExclusionMode.Ignore
M .config/quickshell/aurora/Osd.qml View
@@ -36,7 +36,7 @@ PanelWindow {
3636 WlrLayershell.namespace: "aurora-osd"
3737 WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
3838
39− Timer { id: hide; interval: 1500; onTriggered: win.shown = false }
39+ Timer { id: hide; interval: Settings.osdTimeout; onTriggered: win.shown = false }
4040
4141 // ---- pipewire watchers ----
4242 // ignore the burst of change signals on startup and when the default device switches
A .config/quickshell/aurora/Settings.qml View
@@ -0,0 +1,72 @@
1+pragma Singleton
2+import QtQuick
3+import Quickshell
4+import Quickshell.Io
5+
6+// User knobs persisted to ~/.config/aurora/settings.json (outside the shell dir, so syncing the
7+// config never clobbers it). Written on every change, re-read when edited by hand.
8+Singleton {
9+ id: root
10+ readonly property string file: Quickshell.env("HOME") + "/.config/aurora/settings.json"
11+
12+ // defaults live here; reset() puts them back
13+ readonly property var defaults: ({
14+ fontSize: 12, wsFontSize: 11, barHeight: 22, barAlpha: 1.0, panelAlpha: 0.88, accentIndex: 14,
15+ osdTimeout: 1500, desktopClock: true, desktopViz: true, vizBars: 64,
16+ dock: true, dockPinned: ["foot", "librewolf", "pcmanfm", "obsidian"], wallFolder: "dusky-dark"
17+ })
18+
19+ property alias fontSize: a.fontSize
20+ property alias wsFontSize: a.wsFontSize
21+ property alias barHeight: a.barHeight
22+ property alias barAlpha: a.barAlpha
23+ property alias panelAlpha: a.panelAlpha
24+ property alias accentIndex: a.accentIndex
25+ property alias osdTimeout: a.osdTimeout
26+ property alias desktopClock: a.desktopClock
27+ property alias desktopViz: a.desktopViz
28+ property alias vizBars: a.vizBars
29+ property alias dock: a.dock
30+ property alias dockPinned: a.dockPinned
31+ property alias wallFolder: a.wallFolder
32+
33+ function reset() {
34+ for (var k in defaults) a[k] = defaults[k]
35+ }
36+ function togglePin(id) {
37+ var l = dockPinned.slice(), i = l.indexOf(id)
38+ if (i >= 0) l.splice(i, 1); else l.push(id)
39+ dockPinned = l
40+ }
41+
42+ FileView {
43+ id: fv
44+ path: root.file
45+ watchChanges: true
46+ onFileChanged: reload()
47+ onAdapterUpdated: writeAdapter()
48+ onLoadFailed: err => {
49+ if (err === FileViewError.FileNotFound)
50+ Quickshell.execDetached(["sh", "-c", 'mkdir -p "${1%/*}"', "sh", root.file])
51+ writeLater.start()
52+ }
53+ adapter: JsonAdapter {
54+ id: a
55+ property int fontSize: 12
56+ property int wsFontSize: 11
57+ property int barHeight: 22
58+ property real barAlpha: 1.0
59+ property real panelAlpha: 0.88
60+ property int accentIndex: 14
61+ property int osdTimeout: 1500
62+ property bool desktopClock: true
63+ property bool desktopViz: true
64+ property int vizBars: 64
65+ property bool dock: true
66+ property list<string> dockPinned: ["foot", "librewolf", "pcmanfm", "obsidian"]
67+ property string wallFolder: "dusky-dark"
68+ }
69+ }
70+ // first run: create the file once the directory exists
71+ Timer { id: writeLater; interval: 300; onTriggered: fv.writeAdapter() }
72+}
A .config/quickshell/aurora/SettingsPage.qml View
@@ -0,0 +1,134 @@
1+import QtQuick
2+import QtQuick.Layouts
3+
4+// Theme / shell knobs. Everything writes straight to Settings (persisted, applied live).
5+ColumnLayout {
6+ id: page
7+ spacing: 10
8+
9+ // label + slider + value, for an integer or real setting
10+ component Knob: RowLayout {
11+ id: k
12+ property string label: ""
13+ property real value: 0
14+ property real from: 0
15+ property real to: 1
16+ property int decimals: 0
17+ signal moved(real v)
18+ Layout.fillWidth: true
19+ spacing: 8
20+ Text {
21+ Layout.preferredWidth: 96
22+ text: k.label
23+ color: Theme.fg
24+ font.family: Theme.font
25+ font.pixelSize: Theme.fontSize
26+ }
27+ BarSlider {
28+ Layout.fillWidth: true
29+ from: k.from
30+ to: k.to
31+ step: 1 / Math.max(1, (k.to - k.from) * (k.decimals ? 100 : 1))
32+ value: k.value
33+ onMoved: v => k.moved(k.decimals ? Math.round(v * 100) / 100 : Math.round(v))
34+ }
35+ Text {
36+ Layout.preferredWidth: 40
37+ horizontalAlignment: Text.AlignRight
38+ text: k.decimals ? k.value.toFixed(2) : String(k.value)
39+ color: Theme.fg
40+ font.family: Theme.font
41+ font.pixelSize: Theme.fontSize
42+ }
43+ }
44+
45+ SectionLabel { text: "appearance" }
46+
47+ Knob { label: "font size"; from: 9; to: 18; value: Settings.fontSize; onMoved: v => Settings.fontSize = v }
48+ Knob { label: "ws icons"; from: 8; to: 18; value: Settings.wsFontSize; onMoved: v => Settings.wsFontSize = v }
49+ Knob { label: "bar height"; from: 18; to: 36; value: Settings.barHeight; onMoved: v => Settings.barHeight = v }
50+ Knob { label: "bar alpha"; from: 0.3; to: 1; decimals: 2; value: Settings.barAlpha; onMoved: v => Settings.barAlpha = v }
51+ Knob { label: "panel alpha"; from: 0.3; to: 1; decimals: 2; value: Settings.panelAlpha; onMoved: v => Settings.panelAlpha = v }
52+
53+ SectionLabel { text: "accent" }
54+
55+ GridLayout {
56+ Layout.fillWidth: true
57+ columns: 9
58+ columnSpacing: 4
59+ rowSpacing: 4
60+ Repeater {
61+ model: 17 // "auto" + color0..color15
62+ delegate: Rectangle {
63+ id: sw
64+ required property int index
65+ readonly property int ci: index - 1 // -1 = auto
66+ readonly property bool current: Settings.accentIndex === ci
67+ Layout.fillWidth: true
68+ Layout.preferredHeight: 26
69+ color: ci < 0 ? Theme.surface : Theme.pal[ci]
70+ border.width: current ? 2 : 1
71+ border.color: current ? Theme.fg : Theme.line
72+ Text {
73+ anchors.centerIn: parent
74+ visible: sw.ci < 0 || sw.current
75+ text: sw.ci < 0 ? "auto" : Theme.iCheck
76+ color: sw.ci < 0 ? Theme.fg : Theme.bg
77+ font.family: Theme.font
78+ font.pixelSize: Theme.fontSize - 2
79+ font.bold: true
80+ }
81+ MouseArea {
82+ anchors.fill: parent
83+ cursorShape: Qt.PointingHandCursor
84+ onClicked: Settings.accentIndex = sw.ci
85+ }
86+ }
87+ }
88+ }
89+
90+ SectionLabel { text: "desktop" }
91+
92+ RowLayout {
93+ Layout.fillWidth: true
94+ spacing: 6
95+ IconBtn {
96+ Layout.fillWidth: true
97+ icon: Theme.iClock
98+ label: "clock"
99+ active: Settings.desktopClock
100+ onClicked: Settings.desktopClock = !Settings.desktopClock
101+ }
102+ IconBtn {
103+ Layout.fillWidth: true
104+ icon: Theme.iMusic
105+ label: "visualizer"
106+ active: Settings.desktopViz
107+ onClicked: Settings.desktopViz = !Settings.desktopViz
108+ }
109+ IconBtn {
110+ Layout.fillWidth: true
111+ icon: Theme.iDock
112+ label: "dock"
113+ active: Settings.dock
114+ onClicked: Settings.dock = !Settings.dock
115+ }
116+ }
117+ Knob { label: "viz bars"; from: 16; to: 128; value: Settings.vizBars; onMoved: v => Settings.vizBars = v }
118+ Knob { label: "osd ms"; from: 500; to: 4000; value: Settings.osdTimeout; onMoved: v => Settings.osdTimeout = Math.round(v / 100) * 100 }
119+
120+ Item { Layout.fillHeight: true }
121+
122+ RowLayout {
123+ Layout.fillWidth: true
124+ Text {
125+ Layout.fillWidth: true
126+ text: "~/.config/aurora/settings.json"
127+ elide: Text.ElideLeft
128+ color: Theme.dim
129+ font.family: Theme.font
130+ font.pixelSize: Theme.fontSize - 2
131+ }
132+ IconBtn { icon: Theme.iRefresh; label: "reset"; onClicked: Settings.reset() }
133+ }
134+}
M .config/quickshell/aurora/Theme.qml View
@@ -7,16 +7,16 @@ import Quickshell.Io
77 Singleton {
88 id: root
99
10− // ---- knobs --------------------------------------------------------
10+ // ---- knobs (persisted in ~/.config/aurora/settings.json, edited in the Settings tab) ----
1111 property string font: "JetBrainsMono Nerd Font" // any Nerd Font mono
12− property int fontSize: 12
13− property int wsFontSize: 11 // workspace icons only; everything else uses fontSize
14− property real panelAlpha: 0.88
12+ readonly property int fontSize: Settings.fontSize
13+ readonly property int wsFontSize: Settings.wsFontSize // workspace icons only; everything else uses fontSize
14+ readonly property real panelAlpha: Settings.panelAlpha
1515 // your waybar uses @color14 for underlines/active workspace, so that is the default.
16− // set -1 to auto-pick the most vivid of color1..color6 instead
17− property int accentIndex: 14
18− property int barHeight: 22
19− property real barAlpha: 1.0
16+ // -1 auto-picks the most vivid of color1..color6 instead
17+ readonly property int accentIndex: Settings.accentIndex
18+ readonly property int barHeight: Settings.barHeight
19+ readonly property real barAlpha: Settings.barAlpha
2020
2121 readonly property string walFile: Quickshell.env("HOME") + "/.cache/wal/colors.json"
2222
@@ -156,6 +156,8 @@ Singleton {
156156 readonly property string iPicker: cp(0xF020A)
157157 readonly property string iRec: cp(0xF044A)
158158 readonly property string iStop: cp(0xF04DB)
159+ readonly property string iDock: cp(0xF10A9)
160+ readonly property string iCog: cp(0xF0493)
159161
160162 // workspace icons: the exact Font Awesome glyphs from your waybar config.
161163 // 1 browser, 2 code, 3 book, 4 cog, 5 chat, 6 file, 7 folder, 8 terminal, 9 flask, 10 image
M .config/quickshell/aurora/Wall.qml View
@@ -10,7 +10,7 @@ Singleton {
1010
1111 readonly property string home: Quickshell.env("HOME")
1212 property string rootDir: home + "/pix/wallpapers"
13− property string folder: "dusky-dark" // same default as setwall's WALL_DIR
13+ property string folder: Settings.wallFolder // default dusky-dark, same as setwall's WALL_DIR
1414 readonly property string setwall: home + "/.local/bin/setwall"
1515 readonly property string thumbDir: home + "/.cache/aurora/thumbs"
1616
@@ -29,6 +29,7 @@ Singleton {
2929 }
3030 function listFolder(name) {
3131 folder = name
32+ Settings.wallFolder = name
3233 thumbProc.running = false
3334 listProc.running = false
3435 loading = true
M .config/quickshell/aurora/shell.qml View
@@ -18,7 +18,7 @@ ShellRoot {
1818 // centered overlay windows (wallpaper picker, clipboard, ...): one at a time, on the focused monitor
1919 property string overlay: ""
2020 property var overlayScreen: focusedScreen()
21− readonly property var tabNames: ["home", "audio", "net", "bt", "sys", "notif"]
21+ readonly property var tabNames: ["home", "audio", "net", "bt", "sys", "notif", "settings"]
2222
2323 // screen of the monitor that currently has focus (falls back to the first screen)
2424 function focusedScreen() {
@@ -137,6 +137,8 @@ ShellRoot {
137137 function open(): void { root.openTab(root.tabNames[root.tab]) }
138138 function close(): void { root.close() }
139139 function show(name: string): void { root.openTab(name) }
140+ // `qs ipc call shell show x` is swallowed by the qs CLI (it has its own `show`), so use this
141+ function tab(name: string): void { root.openTab(name) }
140142 function dnd(): void { Notifs.dnd = !Notifs.dnd }
141143 function shot(mode: string): void { root.close(); Shot.take(mode) } // region | window | output | ocr
142144 function shotsave(): void { Shot.save = !Shot.save }