Files
z-bar-qt/Modules/Settings/Controls/SettingBarEntryList.qml
T
zach 96afbdb30b
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 12s
Python / lint-format (pull_request) Successful in 25s
Python / test (pull_request) Successful in 53s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m52s
Settings UI for color scheme presets
2026-05-23 20:14:12 +02:00

242 lines
5.1 KiB
QML

pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import QtQuick.Layouts
import QtQml.Models
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
property bool dragActive: false
property real dragHeight: 0
property real dragStartX: 0
property real dragStartY: 0
property real dragX: 0
property real dragY: 0
property var draggedModelData: null
property string draggedUid: ""
property bool dropAnimating: false
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
required property var object
property var pendingCommitEntries: []
required property string setting
property bool shouldBeActive: true
property int uidCounter: 0
property var visualEntries: []
function ensureVisualEntries() {
if (!root.dragActive && !root.dropAnimating)
root.rebuildVisualEntries();
}
function iconForId(id) {
switch (id) {
case "workspaces":
return "dashboard";
case "audio":
return "volume_up";
case "media":
return "play_arrow";
case "resources":
return "monitoring";
case "updates":
return "system_update";
case "dash":
return "space_dashboard";
case "spacer":
return "horizontal_rule";
case "activeWindow":
return "web_asset";
case "tray":
return "widgets";
case "upower":
return "battery_full";
case "network":
return "wifi";
case "clock":
return "schedule";
case "notifBell":
return "notifications";
default:
return "drag_indicator";
}
}
function indexForUid(uid) {
for (let i = 0; i < root.visualEntries.length; i++) {
if (root.visualEntries[i].uid === uid)
return i;
}
return -1;
}
function labelForId(id) {
switch (id) {
case "workspaces":
return qsTr("Workspaces");
case "audio":
return qsTr("Audio");
case "media":
return qsTr("Media");
case "resources":
return qsTr("Resources");
case "updates":
return qsTr("Updates");
case "dash":
return qsTr("Dash");
case "spacer":
return qsTr("Spacer");
case "activeWindow":
return qsTr("Title");
case "tray":
return qsTr("Tray");
case "upower":
return qsTr("Power");
case "network":
return qsTr("Network");
case "clock":
return qsTr("Clock");
case "notifBell":
return qsTr("Notifs");
case "hyprsunset":
return qsTr("Night light");
default:
return id;
}
}
function rebuildVisualEntries() {
const entries = root.object[root.setting] ?? [];
const next = [];
for (let i = 0; i < entries.length; i++) {
const entry = entries[i];
let existing = null;
for (let j = 0; j < root.visualEntries.length; j++) {
if (root.visualEntries[j].entry === entry) {
existing = root.visualEntries[j];
break;
}
}
if (existing)
next.push(existing);
else
next.push({
uid: `entry-${root.uidCounter++}`,
entry
});
}
root.visualEntries = next;
}
function updateEntry(index, value) {
const list = [...root.object[root.setting]];
const entry = list[index];
entry.enabled = value;
list[index] = entry;
root.object[root.setting] = list;
Config.save();
}
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? layout.implicitHeight : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Component.onCompleted: root.rebuildVisualEntries()
CustomRect {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
z: -1
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout {
id: layout
anchors.fill: parent
// spacing: Appearance.spacing.smaller
DelegateModel {
id: visualModel
delegate: entryDelegate
model: ScriptModel {
objectProp: "uid"
values: root.visualEntries
}
}
Repeater {
delegate: entryDelegate
model: visualModel
}
}
Component {
id: entryDelegate
IconButton {
required property int index
required property var modelData
Layout.fillWidth: true
Layout.preferredWidth: implicitWidth + (stateLayer.pressed ? 18 : internalChecked ? 7 : 0)
checked: modelData.entry.enabled ?? true
font: Appearance.font.family.sans
// icon: root.iconForId(modelData.entry.id)
icon: root.labelForId(modelData.entry.id)
inactiveColour: DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, 2)
radius: stateLayer.pressed ? 6 / 2 : internalChecked ? 6 : 8
radiusAnim.duration: MaterialEasing.expressiveEffectsTime
radiusAnim.easing.bezierCurve: MaterialEasing.expressiveEffects
toggle: true
visible: !["spacer", "upower", "dash", "audio"].some(prefix => modelData.entry.id.startsWith(prefix))
Behavior on Layout.preferredWidth {
Anim {
duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: MaterialEasing.expressiveEffects
}
}
onClicked: root.updateEntry(index, internalChecked)
}
}
}