aboutsummaryrefslogtreecommitdiffstats
path: root/appearance/StepsWindow.qml
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-29 11:56:15 +0200
committerDanilo M. <danix@danix.xyz>2026-09-29 11:56:15 +0200
commit2d7b18d52ee7e7f1aac132180b7eb3b951735668 (patch)
tree735e3a35be639b987800c9ab5e6646504ae3b0cf /appearance/StepsWindow.qml
parent9b83656e3e3d164fc75bbf679cf32357375660c4 (diff)
downloadquickshell-2d7b18d52ee7e7f1aac132180b7eb3b951735668.tar.gz
quickshell-2d7b18d52ee7e7f1aac132180b7eb3b951735668.zip
feat(appearance): steps window, icon regen, cursor out of hypr-theme
StepsWindow shows unified-desktop-theme's pending manual steps, one tab per consumer, centred on DP-3 on the top layer with on-demand focus so it can stay open while commands are pasted elsewhere. udt-steps writes the files and calls the new `steps` IPC verb; indented lines become command blocks with a copy button. The Theme tab pipes install.sh's output into it. The icon switch now also reruns udt-accent (SDDM power icons) and waybar-theme-udt's install.sh (taskbar theme, module icons), chained after the gsettings write both read. Cursor changes write ~/.config/udt/cursor.lua instead of editing hypr-theme's tracked environment.lua. The theme notice and the Udt.qml comment claimed install.sh reloads nothing; it reloads Hyprland, waybar, kitty and conky now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'appearance/StepsWindow.qml')
-rw-r--r--appearance/StepsWindow.qml197
1 files changed, 197 insertions, 0 deletions
diff --git a/appearance/StepsWindow.qml b/appearance/StepsWindow.qml
new file mode 100644
index 0000000..fef1d89
--- /dev/null
+++ b/appearance/StepsWindow.qml
@@ -0,0 +1,197 @@
+// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+import Quickshell
+import Quickshell.Wayland
+import QtQuick
+
+// One tab per consumer with manual steps pending. Centred on the vertical
+// screen and kept open on purpose: the commands are pasted into a root shell
+// elsewhere, so the window takes keyboard focus only when clicked and stays
+// until closed. Done deletes a tab's file; the producer also clears it once
+// the consumer is up to date.
+Scope {
+ id: root
+
+ property string monitor: "DP-3"
+ property bool open: false
+ property string tab: ""
+
+ readonly property var screenObj:
+ Quickshell.screens.find(s => s.name === root.monitor) ?? Quickshell.screens[0]
+ readonly property var current: Steps.tabs.find(t => t.name === root.tab) ?? Steps.tabs[0] ?? null
+
+ // A poke from udt-steps: reload, and open when something is pending.
+ // Also what a keybind calls to bring the window back after closing it.
+ function poke() {
+ root.opening = true;
+ Steps.refresh();
+ }
+ property bool opening: false
+
+ Connections {
+ target: Steps
+ function onLoaded() {
+ if (Steps.tabs.length === 0) root.open = false;
+ else if (root.opening) root.open = true;
+ root.opening = false;
+ }
+ }
+
+ LazyLoader {
+ active: root.open
+
+ PanelWindow {
+ id: win
+ screen: root.screenObj
+ // No anchors: a layer surface anchored nowhere is centred.
+ implicitWidth: 960
+ implicitHeight: body.implicitHeight + 40
+ color: "transparent"
+ exclusionMode: ExclusionMode.Ignore
+ WlrLayershell.layer: WlrLayer.Top
+ WlrLayershell.namespace: "quickshell-steps"
+ WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
+
+ Rectangle {
+ anchors.fill: parent
+ radius: 14
+ color: Qt.alpha(Theme.base, 0.92)
+ border.width: 1
+ border.color: Qt.alpha(Theme.text, 0.12)
+
+ Item {
+ anchors.fill: parent
+ focus: true
+ Keys.onEscapePressed: root.open = false
+ }
+
+ Column {
+ id: body
+ anchors { top: parent.top; left: parent.left; right: parent.right; margins: 20 }
+ spacing: 16
+
+ Item {
+ width: parent.width
+ height: tabBar.implicitHeight
+
+ Row {
+ id: tabBar
+ spacing: 8
+ Repeater {
+ model: Steps.tabs
+ Tab {
+ required property var modelData
+ text: modelData.name
+ selected: root.current !== null && root.current.name === modelData.name
+ onClicked: root.tab = modelData.name
+ }
+ }
+ }
+
+ Tab {
+ anchors.right: parent.right
+ text: "Close"
+ onClicked: root.open = false
+ }
+ }
+
+ Flickable {
+ width: parent.width
+ // Sized from the screen, never from the window: the
+ // window's height comes from this, and a binding back
+ // to it collapsed the whole thing to its margins.
+ height: Math.min(content.implicitHeight,
+ win.screen.height - 240 - tabBar.implicitHeight - actions.implicitHeight - 32)
+ contentHeight: content.implicitHeight
+ clip: true
+
+ Column {
+ id: content
+ width: parent.width
+ spacing: 12
+
+ Repeater {
+ model: root.current ? root.current.blocks : []
+
+ Loader {
+ required property var modelData
+ width: content.width
+ sourceComponent: modelData.cmd ? cmdBlock : prose
+ property var block: modelData
+ }
+ }
+ }
+ }
+
+ Row {
+ id: actions
+ spacing: 8
+ anchors.right: parent.right
+ Tab {
+ text: "Copy all commands"
+ enabled: root.current !== null && Steps.commands(root.current) !== ""
+ onClicked: Steps.copy(Steps.commands(root.current))
+ }
+ Tab {
+ text: "Done"
+ enabled: root.current !== null
+ onClicked: Steps.dismiss(root.current.name)
+ }
+ }
+ }
+ }
+
+ Component {
+ id: prose
+ Text {
+ text: block.text
+ wrapMode: Text.Wrap
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 1 }
+ color: Theme.text
+ }
+ }
+
+ Component {
+ id: cmdBlock
+ Rectangle {
+ implicitHeight: Math.max(code.implicitHeight, copyBtn.implicitHeight) + 24
+ radius: 8
+ color: Qt.alpha(Theme.crust, 0.8)
+ border.width: 1
+ border.color: Qt.alpha(Theme.accent, 0.3)
+
+ // Selectable as well as copyable: sometimes one line of a
+ // block is what is wanted.
+ TextEdit {
+ id: code
+ anchors { left: parent.left; right: copyBtn.left; verticalCenter: parent.verticalCenter; margins: 12 }
+ text: block.text
+ readOnly: true
+ selectByMouse: true
+ wrapMode: TextEdit.WrapAnywhere
+ font { family: "Inconsolata Nerd Font Mono"; pixelSize: Theme.fontSize - 1 }
+ color: Theme.text
+ selectionColor: Qt.alpha(Theme.accent, 0.4)
+ selectedTextColor: Theme.text
+ }
+
+ Tab {
+ id: copyBtn
+ anchors { right: parent.right; rightMargin: 8; verticalCenter: parent.verticalCenter }
+ text: "Copy"
+ onClicked: Steps.copy(block.text)
+ }
+ }
+ }
+ }
+ }
+}