Merge pull request #88 from theupriser/feature/gnome-relogin
Sync git.upriser.nl mirror / sync (push) Skipped
Single-file build / bundle (push) Successful in 15s

App: Restart GNOME after the theme, desktop scale, row and switch clicks
This commit is contained in:
theupriser authored and GitHub committed 2026-10-15 20:50:43 +02:00
commit ba501ff213
8 files changed
+58 -9

No files matched your search

+4 -2
View File
@@ -18,6 +18,7 @@ Item {
property var steps: ({}) // id -> "wait"|"run"|"ok"|"fail"
property var failed: []
property bool restartNeeded: false
property bool reloginNeeded: false // GNOME loads the new theme's extensions at the next login
// Review & apply only when something would change; "Re-apply what's on"
// is for when nothing did.
readonly property bool canApply: computePlan().length > 0
@@ -123,7 +124,7 @@ Item {
}
// --- Password and apply ---
function resetRun() { steps = {}; failed = []; restartNeeded = false; runError = ""; doneCount = 0; logModel.clear(); }
function resetRun() { steps = {}; failed = []; restartNeeded = false; reloginNeeded = false; runError = ""; doneCount = 0; logModel.clear(); }
function startApply(password) {
resetRun();
var s = {};
@@ -203,7 +204,7 @@ Item {
// A successful BIOS check ends with bios-ready instead, keeping
// the password for the flash.
app.sessionPassword = "";
app.failed = ev.failed || []; app.restartNeeded = !!ev.restart;
app.failed = ev.failed || []; app.restartNeeded = !!ev.restart; app.reloginNeeded = !!ev.relogin;
app.runError = app.errorText(ev.error);
app.screen = "done";
}
@@ -249,6 +250,7 @@ Item {
else if (a === "release") { holding = false; if (holdProgress < 1) holdProgress = 0; }
} else if (screen === "done") {
if (a === "accept" && restartNeeded) backend.restart();
else if (a === "accept" && reloginNeeded) backend.restartGnome();
else if (a === "back" || a === "accept") backToMenu();
}
}
+4 -2
View File
@@ -9,7 +9,8 @@ Item {
readonly property bool problem: app.failed.length > 0 || app.runError !== ""
readonly property string message: {
if (app.runError) return app.runError;
if (!app.biosRun) return app.plan.length + (app.plan.length === 1 ? " change" : " changes") + " applied." + (app.restartNeeded ? " Some take effect after a restart." : "");
if (!app.biosRun) return app.plan.length + (app.plan.length === 1 ? " change" : " changes") + " applied." + (app.restartNeeded ? " Some take effect after a restart." : "")
+ (app.reloginNeeded && !app.restartNeeded ? " GNOME shows the dock, extensions and Settings panel after you log in again: Restart GNOME does that." : "");
if (app.failed.length) return "The BIOS was not changed.";
return (app.bios && app.bios.dryRun ? "Dry run: nothing was flashed. " : "BIOS " + (app.biosInfo.newest || "") + " is staged and is written during the restart. ")
+ "Keep the power on and don't touch the machine until it has fully started again, even if the screen stays black.";
@@ -33,6 +34,7 @@ Item {
delegate: Text { required property string line; width: details.width - 12; text: line; color: "#aab5c4"; font.family: Theme.mono; font.pixelSize: 13; wrapMode: Text.WrapAnywhere } } }
Row { anchors.horizontalCenter: parent.horizontalCenter; spacing: 14; topPadding: 8
Btn { k: Input.g.back; text: "Back to the menu"; height: 52; onClicked: app.act("back") }
Btn { visible: app.restartNeeded; k: Input.g.ok; text: "Restart now"; primary: true; height: 52; onClicked: app.backend.restart() } }
Btn { visible: app.restartNeeded; k: Input.g.ok; text: "Restart now"; primary: true; height: 52; onClicked: app.backend.restart() }
Btn { visible: app.reloginNeeded && !app.restartNeeded; k: Input.g.ok; text: "Restart GNOME"; primary: true; height: 52; onClicked: app.backend.restartGnome() } }
}
}
+5 -1
View File
@@ -36,7 +36,11 @@ ApplicationWindow {
// own shape, so the bars reach the edges and the content fills it.
Item {
id: stage
readonly property real k: Math.min(win.width / 1280, win.height / 720)
// On a desktop (a window, however large) the UI keeps the desktop's own scale: 1 here is one logical pixel, which Qt
// multiplies by the scale of GNOME or KDE, like any other app (a 1440p or ultrawide monitor would otherwise show
// everything twice as big). Only a window smaller than the layout shrinks it. The TV mode (--fullscreen, gamescope)
// scales to the screen: it is read from the couch.
readonly property real k: Math.min(win.width / 1280, win.height / 720, win.fullscreen ? Infinity : 1)
width: win.width / k; height: win.height / k
transformOrigin: Item.TopLeft
scale: k
+9 -3
View File
@@ -31,7 +31,9 @@ Item {
color: row.selected ? Theme.cardSel : Theme.card
border.width: row.selected ? 2 : 0; border.color: Theme.accent
MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor
onClicked: { Input.type = "keyboard"; if (row.selected) app.act("accept"); else app.sel = row.rowIndex; } }
// A click on the row only selects it; the switch, the Gaming/Desktop buttons and the BIOS button act on their own
// click (below), selecting the row too.
onClicked: { Input.type = "keyboard"; app.sel = row.rowIndex; } }
Text { visible: !!row.it.parent; x: 20; anchors.verticalCenter: parent.verticalCenter; text: "└"; color: "#56627a"; font.pixelSize: 18 }
Column {
@@ -67,14 +69,18 @@ Item {
Rectangle { id: sw; visible: row.it.kind === "toggle"; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter
width: 46; height: 26; radius: 13; color: row.on ? Theme.accent : "#343f50"
Behavior on color { ColorAnimation { duration: 120 } }
Rectangle { width: 20; height: 20; radius: 10; color: "#f4f7fb"; y: 3; x: row.on ? 23 : 3; Behavior on x { NumberAnimation { duration: 120 } } } }
Rectangle { width: 20; height: 20; radius: 10; color: "#f4f7fb"; y: 3; x: row.on ? 23 : 3; Behavior on x { NumberAnimation { duration: 120 } } }
MouseArea { anchors.fill: parent; anchors.margins: -6; cursorShape: Qt.PointingHandCursor
onClicked: { Input.type = "keyboard"; app.sel = row.rowIndex; app.act("accept"); } } }
Text { visible: row.it.kind === "toggle"; anchors.right: sw.left; anchors.rightMargin: 12; anchors.verticalCenter: parent.verticalCenter
text: row.it.on ? "now on" : "now off"; color: row.it.on ? Theme.good : Theme.faint; font.family: Theme.mono; font.pixelSize: 12 }
// action (Update BIOS)
Rectangle { visible: row.it.kind === "action"; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter
width: at.implicitWidth + 24; height: 30; radius: 8; color: Theme.warnBg
Text { id: at; anchors.centerIn: parent; color: Theme.warn; font.family: Theme.body; font.pixelSize: 13; font.weight: Font.DemiBold
text: app.biosChecking ? "Checking…" : app.bios && app.bios.selectable ? "Update…" : (app.bios && app.bios.newest ? "Up to date" : "Unavailable") } }
text: app.biosChecking ? "Checking…" : app.bios && app.bios.selectable ? "Update…" : (app.bios && app.bios.newest ? "Up to date" : "Unavailable") }
MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor
onClicked: { Input.type = "keyboard"; app.sel = row.rowIndex; app.act("accept"); } } }
}
}
}
+10
View File
@@ -345,6 +345,16 @@ class Backend(QObject):
def restart(self):
QProcess.startDetached("systemctl", ["reboot"])
@Slot()
def restartGnome(self):
# GNOME Shell on Wayland can't restart in place: end the session. With GDM autologin (the SteamOS conversion)
# Steamify's helper logs the user straight back in; else a plain logout.
import subprocess
helper = "/usr/local/libexec/steamify-gdm-relogin"
if os.access(helper, os.X_OK) and subprocess.run(["sudo", "-n", helper], capture_output=True).returncode == 0:
return
QProcess.startDetached("gnome-session-quit", ["--logout", "--no-prompt"])
def shutdown(self):
if self._proc and self._proc.state() != QProcess.NotRunning:
self._proc.kill()