From 9d9e67a14967fe756c357b0ece3d9f339f8afa17 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Thu, 22 Oct 2026 17:25:15 +0200 Subject: settings: a Theme status page for unified-desktop-theme Shows the live scheme, accent and both wallpapers, the scheme and wallpapers linking to their own pages, then every udt consumer in a software and a hardware list, each with a Re-apply button running `install.sh `, and Re-apply all in the header. The list comes from `install.sh --list`, so a consumer added in unified-desktop-theme shows up here with no edit. One run at a time, and none during a scheme switch. QML's JS engine has no Object.fromEntries either: it threw a TypeError that only reached the log and left the page without its list. Noted in AGENTS.md beside String.matchAll. Co-Authored-By: Claude Opus 5.5 --- desktop/modules/appearance/UdtTab.qml | 166 ++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 desktop/modules/appearance/UdtTab.qml (limited to 'desktop/modules/appearance/UdtTab.qml') diff --git a/desktop/modules/appearance/UdtTab.qml b/desktop/modules/appearance/UdtTab.qml new file mode 100644 index 0000000..b4d14b7 --- /dev/null +++ b/desktop/modules/appearance/UdtTab.qml @@ -0,0 +1,166 @@ +// Copyright (C) 2026 Danilo M. +// +// 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 QtQuick +import "../.." + +// The live scheme, accent and both wallpapers, then every consumer install.sh +// knows, each with a button that re-applies the theme to it alone. +Column { + id: tab + spacing: 10 + + // A value set on another settings page links to it. + signal go(string name) + + Component.onCompleted: Udt.refreshStatus() + + Repeater { + model: [ + { label: "Theme", value: Udt.current, page: "theme" }, + { label: "Accent", value: String(Theme.accent), swatch: true }, + { label: "Wallpaper H", value: Wallpapers.basename(Wallpapers.currentH), page: "wallpaper" }, + { label: "Wallpaper V", value: Wallpapers.basename(Wallpapers.currentV), page: "wallpaper" }, + ] + + Row { + required property var modelData + spacing: 8 + + Text { + width: 100 + text: modelData.label + color: Theme.overlay + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 } + } + Rectangle { + anchors.verticalCenter: parent.verticalCenter + visible: modelData.swatch ?? false + width: 16; height: 16; radius: 4 + color: Theme.accent + border.width: 1 + border.color: Qt.alpha(Theme.text, 0.1) + } + Text { + id: value + width: Math.min(implicitWidth, tab.width - 140) + elide: Text.ElideMiddle + text: modelData.value || "-" + color: modelData.page && link.containsMouse ? Theme.accent : Theme.text + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3; bold: !!modelData.page } + + MouseArea { + id: link + anchors.fill: parent + enabled: !!modelData.page + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: tab.go(modelData.page) + } + } + Text { + anchors.verticalCenter: parent.verticalCenter + visible: !!modelData.page + // nf-fa-chevron_right + text: "\uf054" + color: link.containsMouse ? Theme.accent : Theme.overlay + font { family: Theme.iconFamily; pixelSize: Theme.fontSize - 6 } + } + } + } + + Text { + width: tab.width + wrapMode: Text.Wrap + text: "Re-applying runs install.sh for that consumer alone; Re-apply all in the header runs it for every one. A failure's output lands in the steps window." + color: Theme.overlay + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } + } + + // Apps and devices, in install.sh's order. + Repeater { + model: [{ kind: "software", label: "Software" }, { kind: "hardware", label: "Hardware" }] + + Column { + id: section + required property var modelData + readonly property string kind: modelData.kind + width: tab.width + spacing: 6 + + Text { + topPadding: 6 + text: section.modelData.label + color: Theme.subtext + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2; bold: true } + } + + Repeater { + model: Array.from(Udt.consumers).filter(n => Udt.consumerKind[n] === section.kind) + + Rectangle { + required property string modelData + // What a search hit scrolls to (UdtModule's searchItems key). + objectName: modelData + readonly property var result: Udt.reapplied[modelData] + + width: section.width + implicitHeight: 46 + radius: 8 + color: Qt.alpha(Theme.surface, 0.4) + + Column { + anchors.verticalCenter: parent.verticalCenter + x: 12 + Text { + text: modelData + color: Theme.text + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } + } + Text { + text: Udt.consumerInfo[modelData] ?? "" + visible: text !== "" + color: Theme.overlay + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 5 } + } + } + + Row { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 8 + spacing: 10 + + Text { + anchors.verticalCenter: parent.verticalCenter + visible: Udt.isReapplying(modelData) || result !== undefined + text: Udt.isReapplying(modelData) ? "applying…" + : result ? "" : "" + color: Udt.isReapplying(modelData) ? Theme.overlay + : result ? Theme.green : Theme.red + font { + family: Udt.isReapplying(modelData) ? Theme.fontFamily : Theme.iconFamily + pixelSize: Theme.fontSize - 3 + } + } + Button { + // nf-fa-refresh + icon: "" + text: "Re-apply" + enabled: Udt.reapplying === "" && !Udt.applying + onClicked: Udt.reapply(modelData) + } + } + } + } + } + } +} -- cgit v1.2.3