diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-29 11:56:15 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-29 11:56:15 +0200 |
| commit | 2d7b18d52ee7e7f1aac132180b7eb3b951735668 (patch) | |
| tree | 735e3a35be639b987800c9ab5e6646504ae3b0cf /appearance/StepsWindow.qml | |
| parent | 9b83656e3e3d164fc75bbf679cf32357375660c4 (diff) | |
| download | quickshell-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.qml | 197 |
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) + } + } + } + } + } +} |
