aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-19 10:01:49 +0200
committerDanilo M. <danix@danix.xyz>2026-10-19 10:01:49 +0200
commitd9c9c30865330b24349438e4e20579fd76dafbd5 (patch)
tree6dd01b16f51a1bda83e0a2f066c3bbd9218a4f69 /desktop/modules
parent26653d3cb8d2a9b19133a8c2bc981a669a3f81bd (diff)
downloadquickshell-d9c9c30865330b24349438e4e20579fd76dafbd5.tar.gz
quickshell-d9c9c30865330b24349438e4e20579fd76dafbd5.zip
desktop: report save results in the SaveBar, not at the page's foot
A save's outcome sat at the bottom of the page, out of sight on a long one, while "unsaved changes" was already in the header. SaveBar gains notice, shown once the page is clean, and error, shown in red over the unsaved mark, since a refused or failed write leaves the draft dirty. Wired for notifications, HyprIdle, Sunset, Wallpaper and the four Mail pages, with their longer messages shortened to fit the header. Messages that are not save results stay in their pages: the icon theme's immediate apply, Sunset's location detection, the assistant restart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/modules')
-rw-r--r--desktop/modules/appearance/Hyprsunset.qml13
-rw-r--r--desktop/modules/appearance/IdleModule.qml1
-rw-r--r--desktop/modules/appearance/IdleTab.qml9
-rw-r--r--desktop/modules/appearance/SunsetModule.qml1
-rw-r--r--desktop/modules/appearance/SunsetTab.qml2
-rw-r--r--desktop/modules/appearance/WallpaperModule.qml13
-rw-r--r--desktop/modules/appearance/WallpaperTab.qml11
-rw-r--r--desktop/modules/notifications/NotificationsModule.qml14
-rw-r--r--desktop/modules/notifications/NotificationsPage.qml8
-rw-r--r--desktop/modules/qtmaildir/MailAccountsModule.qml2
-rw-r--r--desktop/modules/qtmaildir/MailComposeModule.qml2
-rw-r--r--desktop/modules/qtmaildir/MailGeneralModule.qml2
-rw-r--r--desktop/modules/qtmaildir/MailTagsKeysModule.qml2
-rw-r--r--desktop/modules/qtmaildir/Note.qml11
-rw-r--r--desktop/modules/qtmaildir/Qtm.qml4
15 files changed, 40 insertions, 55 deletions
diff --git a/desktop/modules/appearance/Hyprsunset.qml b/desktop/modules/appearance/Hyprsunset.qml
index 4befcb5..daf07b0 100644
--- a/desktop/modules/appearance/Hyprsunset.qml
+++ b/desktop/modules/appearance/Hyprsunset.qml
@@ -35,6 +35,9 @@ Singleton {
property string cachePathRaw: "~/.config/hyprsunset-qt/sun.json"
property string cachePath: `${home}/.config/hyprsunset-qt/sun.json`
property string notice: ""
+ // The last save's outcome, for the SaveBar: notice is location detection.
+ property string saveNotice: ""
+ property string saveError: ""
property string sunSummary: ""
property bool busy: false
property bool confLoaded: false
@@ -160,6 +163,7 @@ profile {
}
function refresh() {
+ root.saveError = "";
confProc.running = false;
confProc.running = true;
appProc.running = false;
@@ -241,13 +245,13 @@ profile {
function save() {
if (!root.confLoaded || !root.appLoaded) return;
for (const p of root.profiles) {
- if (!root.validTime(p.time)) { root.notice = `invalid time: ${p.time}`; return; }
+ if (!root.validTime(p.time)) { root.saveError = `invalid time: ${p.time}`; return; }
if (p.temperature !== null && p.temperature !== undefined &&
!root.validTemperature(p.temperature)) {
- root.notice = `invalid temperature: ${p.temperature}`; return;
+ root.saveError = `invalid temperature: ${p.temperature}`; return;
}
if (p.gamma !== null && p.gamma !== undefined && !root.validGamma(p.gamma)) {
- root.notice = `invalid gamma: ${p.gamma}`; return;
+ root.saveError = `invalid gamma: ${p.gamma}`; return;
}
}
root.savedConf = root.serializeProfiles(root.profiles);
@@ -255,7 +259,8 @@ profile {
confFile.setText(root.savedConf);
root.saveSettings();
root.restart();
- root.notice = "saved + restarted";
+ root.saveError = "";
+ root.saveNotice = "saved + restarted";
}
// Live preview via the daemon's IPC. Identity wins, then temperature, then
diff --git a/desktop/modules/appearance/IdleModule.qml b/desktop/modules/appearance/IdleModule.qml
index 2e4f32a..fb911b5 100644
--- a/desktop/modules/appearance/IdleModule.qml
+++ b/desktop/modules/appearance/IdleModule.qml
@@ -31,6 +31,7 @@ Module {
title: "HyprIdle"
actions: Component {
SaveBar { saveText: "Save + Restart"; dirty: Hypridle.dirty
+ notice: Hypridle.notice
onSave: Hypridle.save(); onDiscard: Hypridle.refresh() }
}
IdleTab { width: parent.width }
diff --git a/desktop/modules/appearance/IdleTab.qml b/desktop/modules/appearance/IdleTab.qml
index fdb39ec..f3f2907 100644
--- a/desktop/modules/appearance/IdleTab.qml
+++ b/desktop/modules/appearance/IdleTab.qml
@@ -83,14 +83,5 @@ Item {
}
// Save + Restart is in the page header, with every settings page's.
-
- Text {
- width: parent.width
- wrapMode: Text.Wrap
- visible: Hypridle.notice !== ""
- text: Hypridle.notice
- color: Theme.green
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 }
- }
}
}
diff --git a/desktop/modules/appearance/SunsetModule.qml b/desktop/modules/appearance/SunsetModule.qml
index d55d874..2450944 100644
--- a/desktop/modules/appearance/SunsetModule.qml
+++ b/desktop/modules/appearance/SunsetModule.qml
@@ -31,6 +31,7 @@ Module {
title: "HyprSunset"
actions: Component {
SaveBar { saveText: "Save + Restart"; dirty: Hyprsunset.dirty
+ notice: Hyprsunset.saveNotice; error: Hyprsunset.saveError
onSave: Hyprsunset.save(); onDiscard: Hyprsunset.refresh() }
}
SunsetTab { width: parent.width }
diff --git a/desktop/modules/appearance/SunsetTab.qml b/desktop/modules/appearance/SunsetTab.qml
index 26ec264..4f7dfa5 100644
--- a/desktop/modules/appearance/SunsetTab.qml
+++ b/desktop/modules/appearance/SunsetTab.qml
@@ -158,7 +158,7 @@ Item {
wrapMode: Text.Wrap
visible: Hyprsunset.notice !== ""
text: Hyprsunset.notice
- color: Hyprsunset.notice.indexOf("invalid") === 0 ? Theme.red : Theme.green
+ color: Hyprsunset.notice.indexOf("failed") >= 0 ? Theme.red : Theme.green
font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 }
}
}
diff --git a/desktop/modules/appearance/WallpaperModule.qml b/desktop/modules/appearance/WallpaperModule.qml
index cbc7158..fda7e97 100644
--- a/desktop/modules/appearance/WallpaperModule.qml
+++ b/desktop/modules/appearance/WallpaperModule.qml
@@ -31,8 +31,17 @@ Module {
id: pg
title: "Wallpaper"
actions: Component {
- SaveBar { saveText: "Apply"; discardText: "Reset"; dirty: Wallpapers.dirty; busy: Wallpapers.applying
- onSave: Wallpapers.apply(); onDiscard: Wallpapers.clearPending() }
+ SaveBar {
+ id: bar
+ saveText: "Apply"; discardText: "Reset"; dirty: Wallpapers.dirty; busy: Wallpapers.applying
+ onSave: { bar.error = ""; Wallpapers.apply(); }
+ onDiscard: { bar.error = ""; Wallpapers.clearPending(); }
+ // A success closes the window, so only a failure is reported.
+ Connections {
+ target: Wallpapers
+ function onApplied(ok, message) { bar.error = ok ? "" : `wallpaper failed: ${message}`; }
+ }
+ }
}
WallpaperTab { width: parent.width; height: pg.viewHeight; onDismiss: pg.dismiss() }
}
diff --git a/desktop/modules/appearance/WallpaperTab.qml b/desktop/modules/appearance/WallpaperTab.qml
index 3931fcb..a3b3c55 100644
--- a/desktop/modules/appearance/WallpaperTab.qml
+++ b/desktop/modules/appearance/WallpaperTab.qml
@@ -23,7 +23,6 @@ Column {
// What the mock screens show. Hovering a thumbnail previews it on the
// targeted screen; the other keeps whatever is currently set.
property string hovering: ""
- property string notice: ""
// Close the window: after a wallpaper is set, so the desk shows, and when
// wallhaven-dl opens.
signal dismiss
@@ -70,7 +69,6 @@ Column {
Connections {
target: Wallpapers
function onApplied(ok, message) {
- tab.notice = ok ? "" : `wallpaper failed: ${message}`;
if (ok) tab.dismiss();
}
}
@@ -173,15 +171,6 @@ Column {
height: parent.height - mockPane.height - parent.spacing
spacing: 12
- Text {
- visible: tab.notice !== ""
- width: parent.width
- wrapMode: Text.Wrap
- text: tab.notice
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 }
- color: Theme.red
- }
-
Row {
spacing: 8
Text {
diff --git a/desktop/modules/notifications/NotificationsModule.qml b/desktop/modules/notifications/NotificationsModule.qml
index 7a113df..df52949 100644
--- a/desktop/modules/notifications/NotificationsModule.qml
+++ b/desktop/modules/notifications/NotificationsModule.qml
@@ -27,6 +27,7 @@ Module {
property var draft: Notify.config
property string notice: ""
+ property string error: ""
// The installed sound themes (directories with an index.theme), and the
// system theme as gsettings has it, "" when unreadable. Both reread on
// every refresh, so a change made outside the page shows.
@@ -45,7 +46,7 @@ Module {
nm.themeLister.running = false; nm.themeLister.running = true;
nm.gsGet.running = false; nm.gsGet.running = true;
}
- function discard() { nm.follow(); nm.notice = ""; }
+ function discard() { nm.follow(); nm.notice = ""; nm.error = ""; }
function edit(patch) { nm.draft = Object.assign({}, nm.draft, patch); }
// Unknown keys in the file survive, including inside timeouts and
@@ -56,6 +57,7 @@ Module {
// the sequence notes' bodyWriter uses (NotesModule.qml).
function save() {
nm.notice = "";
+ nm.error = "";
const raw = Notify.rawConfig;
const obj = v => v && typeof v === "object" && !Array.isArray(v) ? v : {};
const out = Object.assign({}, raw, nm.draft, {
@@ -82,10 +84,10 @@ Module {
nm.saver.stdinEnabled = false;
}
onExited: code => {
- nm.notice = code === 0 ? "saved"
- : code === 2 ? "saved; notifyd not reachable, it reads the file at its next start"
- : code === 3 ? "saved; the system sound theme could not be set"
- : "could not write " + Notify.configPath;
+ if (code === 1) nm.error = "could not write config.json";
+ else nm.notice = code === 0 ? "saved"
+ : code === 2 ? "saved; notifyd not running, it reads it at start"
+ : "saved; system sound theme not set";
nm.gsGet.running = false; nm.gsGet.running = true;
}
}
@@ -110,6 +112,8 @@ Module {
title: "Notifications"
actions: Component {
SaveBar { dirty: nm.dirty; valid: nm.valid; note: "caps are 1 to 100"; busy: nm.saver.running
+ notice: nm.notice; noticeColor: nm.notice === "saved" ? Theme.green : Theme.yellow
+ error: nm.error
onSave: nm.save(); onDiscard: nm.discard() }
}
NotificationsPage { width: parent.width; mod: nm }
diff --git a/desktop/modules/notifications/NotificationsPage.qml b/desktop/modules/notifications/NotificationsPage.qml
index ce09a9d..612fb83 100644
--- a/desktop/modules/notifications/NotificationsPage.qml
+++ b/desktop/modules/notifications/NotificationsPage.qml
@@ -286,12 +286,4 @@ Column {
value = "";
}
}
-
- Text {
- width: pg.width; wrapMode: Text.Wrap
- visible: pg.mod.notice !== ""
- text: pg.mod.notice
- color: pg.mod.notice === "saved" ? Theme.green : Theme.yellow
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 }
- }
}
diff --git a/desktop/modules/qtmaildir/MailAccountsModule.qml b/desktop/modules/qtmaildir/MailAccountsModule.qml
index a77dbac..11cfecb 100644
--- a/desktop/modules/qtmaildir/MailAccountsModule.qml
+++ b/desktop/modules/qtmaildir/MailAccountsModule.qml
@@ -32,7 +32,7 @@ Module {
title: "Accounts"
// One draft behind all four Mail pages: Save writes them all.
actions: Component {
- SaveBar { dirty: Qtm.dirty; valid: Qtm.valid; onSave: Qtm.save(); onDiscard: Qtm.discard() }
+ SaveBar { dirty: Qtm.dirty; valid: Qtm.valid; error: Qtm.error; onSave: Qtm.save(); onDiscard: Qtm.discard() }
}
AccountsPage { width: parent.width }
}
diff --git a/desktop/modules/qtmaildir/MailComposeModule.qml b/desktop/modules/qtmaildir/MailComposeModule.qml
index 6a9a198..f97f9ef 100644
--- a/desktop/modules/qtmaildir/MailComposeModule.qml
+++ b/desktop/modules/qtmaildir/MailComposeModule.qml
@@ -33,7 +33,7 @@ Module {
title: "Compose"
// One draft behind all four Mail pages: Save writes them all.
actions: Component {
- SaveBar { dirty: Qtm.dirty; valid: Qtm.valid; onSave: Qtm.save(); onDiscard: Qtm.discard() }
+ SaveBar { dirty: Qtm.dirty; valid: Qtm.valid; error: Qtm.error; onSave: Qtm.save(); onDiscard: Qtm.discard() }
}
ComposePage { width: parent.width }
}
diff --git a/desktop/modules/qtmaildir/MailGeneralModule.qml b/desktop/modules/qtmaildir/MailGeneralModule.qml
index 02ecd5a..87ebeb9 100644
--- a/desktop/modules/qtmaildir/MailGeneralModule.qml
+++ b/desktop/modules/qtmaildir/MailGeneralModule.qml
@@ -43,7 +43,7 @@ Module {
title: "Mail"
// One draft behind all four Mail pages: Save writes them all.
actions: Component {
- SaveBar { dirty: Qtm.dirty; valid: Qtm.valid; onSave: Qtm.save(); onDiscard: Qtm.discard() }
+ SaveBar { dirty: Qtm.dirty; valid: Qtm.valid; error: Qtm.error; onSave: Qtm.save(); onDiscard: Qtm.discard() }
}
GeneralPage { width: parent.width }
}
diff --git a/desktop/modules/qtmaildir/MailTagsKeysModule.qml b/desktop/modules/qtmaildir/MailTagsKeysModule.qml
index 0c1eade..c414a71 100644
--- a/desktop/modules/qtmaildir/MailTagsKeysModule.qml
+++ b/desktop/modules/qtmaildir/MailTagsKeysModule.qml
@@ -31,7 +31,7 @@ Module {
title: "Tags & shortcuts"
// One draft behind all four Mail pages: Save writes them all.
actions: Component {
- SaveBar { dirty: Qtm.dirty; valid: Qtm.valid; onSave: Qtm.save(); onDiscard: Qtm.discard() }
+ SaveBar { dirty: Qtm.dirty; valid: Qtm.valid; error: Qtm.error; onSave: Qtm.save(); onDiscard: Qtm.discard() }
}
TagsKeysPage { width: parent.width }
}
diff --git a/desktop/modules/qtmaildir/Note.qml b/desktop/modules/qtmaildir/Note.qml
index 56b8208..94213c1 100644
--- a/desktop/modules/qtmaildir/Note.qml
+++ b/desktop/modules/qtmaildir/Note.qml
@@ -12,7 +12,8 @@
import QtQuick
import "../.."
-// The top of every Mail page: when changes apply, and any write error.
+// The top of every Mail page: when changes apply. A refused or failed
+// write is reported in the SaveBar.
Column {
width: parent ? parent.width : 0
spacing: 4
@@ -24,12 +25,4 @@ Column {
color: Qtm.running ? Theme.yellow : Theme.subtext
font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 }
}
- Text {
- width: parent.width
- visible: Qtm.error !== ""
- wrapMode: Text.Wrap
- text: Qtm.error
- color: Theme.red
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 }
- }
}
diff --git a/desktop/modules/qtmaildir/Qtm.qml b/desktop/modules/qtmaildir/Qtm.qml
index 3f6175b..554841b 100644
--- a/desktop/modules/qtmaildir/Qtm.qml
+++ b/desktop/modules/qtmaildir/Qtm.qml
@@ -82,7 +82,7 @@ Singleton {
// here (AGENTS.md: it writes nothing for empty text on an unloaded path).
function save() {
if (root.text !== root.base) {
- root.error = "qtmaildir.conf changed on disk since these edits began. Discard to load it, then redo them.";
+ root.error = "changed on disk: Discard to load it, then redo";
return;
}
root.error = "";
@@ -119,7 +119,7 @@ Singleton {
if (!root.dirty) { root.base = root.text; root.draft = root.text; }
}
onLoadFailed: if (!root.dirty) { root.text = ""; root.base = ""; root.draft = ""; }
- onSaveFailed: err => root.error = "Cannot write " + root.path + ": " + FileViewError.toString(err)
+ onSaveFailed: err => root.error = "cannot write: " + FileViewError.toString(err)
}
Process {