@@ -11,52 +11,105 @@ Singleton {
1111 // Configuration ready flag
1212 property bool ready: false
1313
14- // Configuration file path
15- readonly property string configPath: Quickshell .env (" XDG_CONFIG_HOME" ) + " /hypercube/shell.json"
14+ // Configuration file path - fallback to ~/.config if XDG_CONFIG_HOME is not set
15+ readonly property string configDir: {
16+ const xdg = Quickshell .env (" XDG_CONFIG_HOME" )
17+ if (xdg && xdg !== " " ) return xdg + " /hypercube"
18+ const home = Quickshell .env (" HOME" )
19+ return home + " /.config/hypercube"
20+ }
21+ readonly property string configPath: configDir + " /shell.json"
1622 readonly property string defaultConfigPath: Qt .resolvedUrl (" ../../defaults/config.json" )
1723
24+ // Default values (used for comparison when saving)
25+ readonly property var defaults: ({
26+ appearance: {
27+ darkMode: true ,
28+ accentColor: " blue" ,
29+ wallpaperTheming: false ,
30+ panelOpacity: 0.85
31+ },
32+ fonts: {
33+ family: " JetBrains Mono" ,
34+ mono: " JetBrains Mono" ,
35+ size: 14
36+ },
37+ bar: {
38+ showWeather: true ,
39+ showBattery: true ,
40+ showNetwork: true ,
41+ showTray: true ,
42+ showClock: true ,
43+ use24Hour: true
44+ },
45+ notifications: {
46+ timeout: 5000 ,
47+ sounds: true ,
48+ dndSchedule: false ,
49+ dndStart: " 22:00" ,
50+ dndEnd: " 08:00"
51+ },
52+ sidebar: {
53+ animations: true ,
54+ width: 380
55+ },
56+ osd: {
57+ timeout: 1500 ,
58+ showValue: true
59+ },
60+ weather: {
61+ location: " " ,
62+ units: " metric" ,
63+ updateInterval: 900000
64+ },
65+ launcher: {
66+ maxResults: 50 ,
67+ showCategories: true
68+ }
69+ })
70+
1871 // Appearance settings
19- property bool darkMode: true
20- property string accentColor: " blue " // blue, green, purple, orange, red, cyan
21- property bool wallpaperTheming: false
22- property real panelOpacity: 0.85
72+ property bool darkMode: defaults . appearance . darkMode
73+ property string accentColor: defaults . appearance . accentColor
74+ property bool wallpaperTheming: defaults . appearance . wallpaperTheming
75+ property real panelOpacity: defaults . appearance . panelOpacity
2376
2477 // Font settings
25- property string fontFamily: " JetBrains Mono "
26- property string monoFontFamily: " JetBrains Mono "
27- property int fontSize: 14
78+ property string fontFamily: defaults . fonts . family
79+ property string monoFontFamily: defaults . fonts . mono
80+ property int fontSize: defaults . fonts . size
2881
2982 // Bar settings
30- property bool showWeather: true
31- property bool showBattery: true
32- property bool showNetwork: true
33- property bool showTray: true
34- property bool showClock: true
35- property bool use24Hour: true
83+ property bool showWeather: defaults . bar . showWeather
84+ property bool showBattery: defaults . bar . showBattery
85+ property bool showNetwork: defaults . bar . showNetwork
86+ property bool showTray: defaults . bar . showTray
87+ property bool showClock: defaults . bar . showClock
88+ property bool use24Hour: defaults . bar . use24Hour
3689
3790 // Notification settings
38- property int notificationTimeout: 5000
39- property bool notificationSounds: true
40- property bool doNotDisturbSchedule: false
41- property string doNotDisturbStart: " 22:00 "
42- property string doNotDisturbEnd: " 08:00 "
91+ property int notificationTimeout: defaults . notifications . timeout
92+ property bool notificationSounds: defaults . notifications . sounds
93+ property bool doNotDisturbSchedule: defaults . notifications . dndSchedule
94+ property string doNotDisturbStart: defaults . notifications . dndStart
95+ property string doNotDisturbEnd: defaults . notifications . dndEnd
4396
4497 // Sidebar settings
45- property bool sidebarAnimations: true
46- property int sidebarWidth: 380
98+ property bool sidebarAnimations: defaults . sidebar . animations
99+ property int sidebarWidth: defaults . sidebar . width
47100
48101 // OSD settings
49- property int osdTimeout: 1500
50- property bool osdShowValue: true
102+ property int osdTimeout: defaults . osd . timeout
103+ property bool osdShowValue: defaults . osd . showValue
51104
52105 // Weather settings
53- property string weatherLocation: " " // Empty = auto-detect
54- property string weatherUnits: " metric " // metric, imperial
55- property int weatherUpdateInterval: 900000 // 15 minutes
106+ property string weatherLocation: defaults . weather . location
107+ property string weatherUnits: defaults . weather . units
108+ property int weatherUpdateInterval: defaults . weather . updateInterval
56109
57110 // Launcher settings
58- property int launcherMaxResults: 50
59- property bool launcherShowCategories: true
111+ property int launcherMaxResults: defaults . launcher . maxResults
112+ property bool launcherShowCategories: defaults . launcher . showCategories
60113
61114 // Check if config file exists and create if needed
62115 Process {
@@ -173,55 +226,80 @@ Singleton {
173226 }
174227 }
175228
176- // Save configuration to file
229+ // Process to write config file
230+ Process {
231+ id: saveProcess
232+ running: false
233+
234+ onExited: {
235+ console .log (" Config: Saved to" , root .configPath )
236+ }
237+ }
238+
239+ // Helper to add non-default value to config object
240+ function addIfChanged (obj , section , key , currentValue , defaultValue ) {
241+ if (currentValue !== defaultValue) {
242+ if (! obj[section]) obj[section] = {}
243+ obj[section][key] = currentValue
244+ }
245+ }
246+
247+ // Save configuration to file - only writes values that differ from defaults
177248 function save () {
178- const config = {
179- appearance: {
180- darkMode: darkMode,
181- accentColor: accentColor,
182- wallpaperTheming: wallpaperTheming,
183- panelOpacity: panelOpacity
184- },
185- fonts: {
186- family: fontFamily,
187- mono: monoFontFamily,
188- size: fontSize
189- },
190- bar: {
191- showWeather: showWeather,
192- showBattery: showBattery,
193- showNetwork: showNetwork,
194- showTray: showTray,
195- showClock: showClock,
196- use24Hour: use24Hour
197- },
198- notifications: {
199- timeout: notificationTimeout,
200- sounds: notificationSounds,
201- dndSchedule: doNotDisturbSchedule,
202- dndStart: doNotDisturbStart,
203- dndEnd: doNotDisturbEnd
204- },
205- sidebar: {
206- animations: sidebarAnimations,
207- width: sidebarWidth
208- },
209- osd: {
210- timeout: osdTimeout,
211- showValue: osdShowValue
212- },
213- weather: {
214- location: weatherLocation,
215- units: weatherUnits,
216- updateInterval: weatherUpdateInterval
217- },
218- launcher: {
219- maxResults: launcherMaxResults,
220- showCategories: launcherShowCategories
221- }
249+ const config = {}
250+
251+ // Appearance
252+ addIfChanged (config, " appearance" , " darkMode" , darkMode, defaults .appearance .darkMode )
253+ addIfChanged (config, " appearance" , " accentColor" , accentColor, defaults .appearance .accentColor )
254+ addIfChanged (config, " appearance" , " wallpaperTheming" , wallpaperTheming, defaults .appearance .wallpaperTheming )
255+ addIfChanged (config, " appearance" , " panelOpacity" , panelOpacity, defaults .appearance .panelOpacity )
256+
257+ // Fonts
258+ addIfChanged (config, " fonts" , " family" , fontFamily, defaults .fonts .family )
259+ addIfChanged (config, " fonts" , " mono" , monoFontFamily, defaults .fonts .mono )
260+ addIfChanged (config, " fonts" , " size" , fontSize, defaults .fonts .size )
261+
262+ // Bar
263+ addIfChanged (config, " bar" , " showWeather" , showWeather, defaults .bar .showWeather )
264+ addIfChanged (config, " bar" , " showBattery" , showBattery, defaults .bar .showBattery )
265+ addIfChanged (config, " bar" , " showNetwork" , showNetwork, defaults .bar .showNetwork )
266+ addIfChanged (config, " bar" , " showTray" , showTray, defaults .bar .showTray )
267+ addIfChanged (config, " bar" , " showClock" , showClock, defaults .bar .showClock )
268+ addIfChanged (config, " bar" , " use24Hour" , use24Hour, defaults .bar .use24Hour )
269+
270+ // Notifications
271+ addIfChanged (config, " notifications" , " timeout" , notificationTimeout, defaults .notifications .timeout )
272+ addIfChanged (config, " notifications" , " sounds" , notificationSounds, defaults .notifications .sounds )
273+ addIfChanged (config, " notifications" , " dndSchedule" , doNotDisturbSchedule, defaults .notifications .dndSchedule )
274+ addIfChanged (config, " notifications" , " dndStart" , doNotDisturbStart, defaults .notifications .dndStart )
275+ addIfChanged (config, " notifications" , " dndEnd" , doNotDisturbEnd, defaults .notifications .dndEnd )
276+
277+ // Sidebar
278+ addIfChanged (config, " sidebar" , " animations" , sidebarAnimations, defaults .sidebar .animations )
279+ addIfChanged (config, " sidebar" , " width" , sidebarWidth, defaults .sidebar .width )
280+
281+ // OSD
282+ addIfChanged (config, " osd" , " timeout" , osdTimeout, defaults .osd .timeout )
283+ addIfChanged (config, " osd" , " showValue" , osdShowValue, defaults .osd .showValue )
284+
285+ // Weather
286+ addIfChanged (config, " weather" , " location" , weatherLocation, defaults .weather .location )
287+ addIfChanged (config, " weather" , " units" , weatherUnits, defaults .weather .units )
288+ addIfChanged (config, " weather" , " updateInterval" , weatherUpdateInterval, defaults .weather .updateInterval )
289+
290+ // Launcher
291+ addIfChanged (config, " launcher" , " maxResults" , launcherMaxResults, defaults .launcher .maxResults )
292+ addIfChanged (config, " launcher" , " showCategories" , launcherShowCategories, defaults .launcher .showCategories )
293+
294+ // Only write if there are changes
295+ if (Object .keys (config).length === 0 ) {
296+ console .log (" Config: No changes from defaults, skipping save" )
297+ return
222298 }
223299
224- configFile .setText (JSON .stringify (config, null , 2 ))
300+ const jsonContent = JSON .stringify (config, null , 2 )
301+ saveProcess .command = [" sh" , " -c" , " mkdir -p '" + root .configDir + " ' && cat > '" + root .configPath + " ' << 'EOFCONFIG'\n " + jsonContent + " \n EOFCONFIG" ]
302+ saveProcess .running = true
225303 }
226304
227305 // Load configuration
0 commit comments