start of refactor

This commit is contained in:
Zacharias-Brohn
2026-03-09 22:17:34 +01:00
parent fb15c2421b
commit 88d795a73f
12 changed files with 329 additions and 221 deletions
+9
View File
@@ -0,0 +1,9 @@
import Quickshell
import Quickshell.Wayland
PanelWindow {
required property string name
WlrLayershell.namespace: `ZShell-${name}`
color: "transparent"
}
+2
View File
@@ -2,6 +2,7 @@ import Quickshell.Io
JsonObject {
property bool autoHide: false
property int border: 8
property list<var> entries: [
{
id: "workspaces",
@@ -60,6 +61,7 @@ JsonObject {
enabled: true
},
]
property int height: 34
property Popouts popouts: Popouts {
}
property int rounding: 8
+2
View File
@@ -81,6 +81,8 @@ Singleton {
return {
autoHide: barConfig.autoHide,
rounding: barConfig.rounding,
border: barConfig.border,
height: barConfig.height,
popouts: {
tray: barConfig.popouts.tray,
audio: barConfig.popouts.audio,
+1 -1
View File
@@ -22,7 +22,7 @@ Shape {
required property PersistentProperties visibilities
anchors.fill: parent
// anchors.margins: 8
anchors.margins: Config.barConfig.border
anchors.topMargin: Config.barConfig.autoHide && !visibilities.bar ? 0 : bar.implicitHeight
preferredRendererType: Shape.CurveRenderer
+3 -15
View File
@@ -56,21 +56,9 @@ Variants {
y: Config.barConfig.autoHide && !visibilities.bar ? 4 : backgroundRect.height
}
PanelWindow {
id: exclusionZone
WlrLayershell.exclusionMode: Config.barConfig.autoHide ? ExclusionMode.Ignore : ExclusionMode.Auto
WlrLayershell.layer: WlrLayer.Bottom
WlrLayershell.namespace: "ZShell-Bar-Exclusion"
color: "transparent"
implicitHeight: backgroundRect.height
screen: bar.screen
anchors {
left: true
right: true
top: true
}
Exclusions {
bar: barLoader
screen: scope.modelData
}
anchors {
+41
View File
@@ -0,0 +1,41 @@
pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import qs.Config
import qs.Components
Scope {
id: root
required property Item bar
required property ShellScreen screen
ExclusionZone {
anchors.top: true
exclusiveZone: root.bar.exclusiveZone
}
ExclusionZone {
anchors.left: true
}
ExclusionZone {
anchors.right: true
}
ExclusionZone {
anchors.bottom: true
}
component ExclusionZone: CustomWindow {
exclusiveZone: Config.barConfig.border
implicitHeight: 1
implicitWidth: 1
name: "Bar-Exclusion"
screen: root.screen
mask: Region {
}
}
}
+1 -1
View File
@@ -34,7 +34,7 @@ Item {
required property PersistentProperties visibilities
anchors.fill: parent
// anchors.margins: 8
anchors.margins: Config.barConfig.border
anchors.topMargin: Config.barConfig.autoHide && !visibilities.bar ? 0 : bar.implicitHeight
Behavior on anchors.topMargin {
+215
View File
@@ -0,0 +1,215 @@
pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Modules
import qs.Config
import qs.Helpers
import qs.Modules.UPower
import qs.Modules.Network
RowLayout {
id: root
required property Wrapper popouts
required property ShellScreen screen
readonly property int vPadding: 6
required property PersistentProperties visibilities
function checkPopout(x: real): void {
const ch = childAt(x, 2) as WrappedLoader;
if (!ch || ch?.id === "spacer") {
if (!popouts.currentName.startsWith("traymenu"))
popouts.hasCurrent = false;
return;
}
if (visibilities.sidebar || visibilities.dashboard || visibilities.resources)
return;
const id = ch.id;
const top = ch.x;
const item = ch.item;
const itemWidth = item.implicitWidth;
if (id === "audio" && Config.barConfig.popouts.audio) {
popouts.currentName = "audio";
popouts.currentCenter = Qt.binding(() => item.mapToItem(root, itemWidth / 2, 0).x);
popouts.hasCurrent = true;
} else if (id === "network" && Config.barConfig.popouts.network) {
popouts.currentName = "network";
popouts.currentCenter = Qt.binding(() => item.mapToItem(root, itemWidth / 2, 0).x);
popouts.hasCurrent = true;
} else if (id === "upower" && Config.barConfig.popouts.upower) {
popouts.currentName = "upower";
popouts.currentCenter = Qt.binding(() => item.mapToItem(root, itemWidth / 2, 0).x);
popouts.hasCurrent = true;
}
}
spacing: Appearance.spacing.small
Repeater {
id: repeater
// model: Config.barConfig.entries.filted(n => n.index > 50).sort(n => n.index)
model: Config.barConfig.entries
DelegateChooser {
role: "id"
DelegateChoice {
roleValue: "spacer"
delegate: WrappedLoader {
Layout.fillWidth: true
}
}
DelegateChoice {
roleValue: "workspaces"
delegate: WrappedLoader {
sourceComponent: Workspaces {
screen: root.screen
}
}
}
DelegateChoice {
roleValue: "audio"
delegate: WrappedLoader {
sourceComponent: AudioWidget {
}
}
}
DelegateChoice {
roleValue: "tray"
delegate: WrappedLoader {
sourceComponent: TrayWidget {
bar: root.bar
loader: root
popouts: root.popouts
}
}
}
DelegateChoice {
roleValue: "resources"
delegate: WrappedLoader {
sourceComponent: Resources {
visibilities: root.visibilities
}
}
}
DelegateChoice {
roleValue: "updates"
delegate: WrappedLoader {
sourceComponent: UpdatesWidget {
}
}
}
DelegateChoice {
roleValue: "notifBell"
delegate: WrappedLoader {
sourceComponent: NotifBell {
popouts: root.popouts
visibilities: root.visibilities
}
}
}
DelegateChoice {
roleValue: "clock"
delegate: WrappedLoader {
sourceComponent: Clock {
loader: root
popouts: root.popouts
visibilities: root.visibilities
}
}
}
DelegateChoice {
roleValue: "activeWindow"
delegate: WrappedLoader {
sourceComponent: WindowTitle {
bar: root
}
}
}
DelegateChoice {
roleValue: "upower"
delegate: WrappedLoader {
sourceComponent: UPowerWidget {
}
}
}
DelegateChoice {
roleValue: "network"
delegate: WrappedLoader {
sourceComponent: NetworkWidget {
}
}
}
DelegateChoice {
roleValue: "media"
delegate: WrappedLoader {
sourceComponent: MediaWidget {
}
}
}
}
}
component WrappedLoader: Loader {
required property bool enabled
required property string id
required property int index
function findFirstEnabled(): Item {
const count = repeater.count;
for (let i = 0; i < count; i++) {
const item = repeater.itemAt(i);
if (item?.enabled)
return item;
}
return null;
}
function findLastEnabled(): Item {
for (let i = repeater.count - 1; i >= 0; i--) {
const item = repeater.itemAt(i);
if (item?.enabled)
return item;
}
return null;
}
Layout.alignment: Qt.AlignVCenter
Layout.fillHeight: true
Layout.leftMargin: findFirstEnabled() === this ? root.vPadding : 0
Layout.rightMargin: findLastEnabled() === this ? root.vPadding : 0
active: enabled
visible: enabled
}
}
+42 -193
View File
@@ -11,223 +11,72 @@ import qs.Helpers
import qs.Modules.UPower
import qs.Modules.Network
RowLayout {
Item {
id: root
required property PanelWindow bar
readonly property int contentHeight: Config.barConfig.height + padding * 2
readonly property int exclusiveZone: Config.barConfig.autoHide ? Config.barConfig.border : contentHeight
property bool isHovered
readonly property int padding: Math.max(Appearance.padding.smaller, Config.barConfig.border)
required property Wrapper popouts
required property ShellScreen screen
readonly property bool shouldBeVisible: (!Config.barConfig.autoHide || visibilities.bar)
readonly property int vPadding: 6
required property PersistentProperties visibilities
function checkPopout(x: real): void {
const ch = childAt(x, 2) as WrappedLoader;
if (!ch || ch?.id === "spacer") {
if (!popouts.currentName.startsWith("traymenu"))
popouts.hasCurrent = false;
return;
content.item?.checkPopout(x);
}
if (visibilities.sidebar || visibilities.dashboard || visibilities.resources)
return;
implicitHeight: Config.barConfig.border
visible: width > Config.barConfig.border
const id = ch.id;
const top = ch.x;
const item = ch.item;
const itemWidth = item.implicitWidth;
states: State {
name: "visible"
when: root.shouldBeVisible
if (id === "audio" && Config.barConfig.popouts.audio) {
popouts.currentName = "audio";
popouts.currentCenter = Qt.binding(() => item.mapToItem(root, itemWidth / 2, 0).x);
popouts.hasCurrent = true;
} else if (id === "network" && Config.barConfig.popouts.network) {
popouts.currentName = "network";
popouts.currentCenter = Qt.binding(() => item.mapToItem(root, itemWidth / 2, 0).x);
popouts.hasCurrent = true;
} else if (id === "upower" && Config.barConfig.popouts.upower) {
popouts.currentName = "upower";
popouts.currentCenter = Qt.binding(() => item.mapToItem(root, itemWidth / 2, 0).x);
popouts.hasCurrent = true;
PropertyChanges {
root.implicitHeight: root.contentHeight
}
}
transitions: [
Transition {
from: ""
to: "visible"
implicitHeight: 34
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
property: "implicitHeight"
target: root
}
},
Transition {
from: "visible"
to: ""
CustomShortcut {
name: "toggle-overview"
onPressed: {
Hyprland.refreshWorkspaces();
Hyprland.refreshMonitors();
if (root.popouts.hasCurrent && root.popouts.currentName === "overview") {
root.popouts.hasCurrent = false;
} else {
root.popouts.currentName = "overview";
root.popouts.currentCenter = root.width / 2;
root.popouts.hasCurrent = true;
}
Anim {
easing.bezierCurve: Appearance.anim.curves.emphasized
property: "implicitHeight"
target: root
}
}
]
Repeater {
id: repeater
Loader {
id: content
// model: Config.barConfig.entries.filted(n => n.index > 50).sort(n => n.index)
model: Config.barConfig.entries
active: root.shouldBeVisible || root.visible
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
DelegateChooser {
role: "id"
DelegateChoice {
roleValue: "spacer"
delegate: WrappedLoader {
Layout.fillWidth: true
}
}
DelegateChoice {
roleValue: "workspaces"
delegate: WrappedLoader {
sourceComponent: Workspaces {
bar: root.bar
}
}
}
DelegateChoice {
roleValue: "audio"
delegate: WrappedLoader {
sourceComponent: AudioWidget {
}
}
}
DelegateChoice {
roleValue: "tray"
delegate: WrappedLoader {
sourceComponent: TrayWidget {
bar: root.bar
loader: root
sourceComponent: Bar {
height: root.contentHeight
popouts: root.popouts
}
}
}
DelegateChoice {
roleValue: "resources"
delegate: WrappedLoader {
sourceComponent: Resources {
screen: root.screen
visibilities: root.visibilities
}
}
}
DelegateChoice {
roleValue: "updates"
delegate: WrappedLoader {
sourceComponent: UpdatesWidget {
}
}
}
DelegateChoice {
roleValue: "notifBell"
delegate: WrappedLoader {
sourceComponent: NotifBell {
popouts: root.popouts
visibilities: root.visibilities
}
}
}
DelegateChoice {
roleValue: "clock"
delegate: WrappedLoader {
sourceComponent: Clock {
loader: root
popouts: root.popouts
visibilities: root.visibilities
}
}
}
DelegateChoice {
roleValue: "activeWindow"
delegate: WrappedLoader {
sourceComponent: WindowTitle {
bar: root
}
}
}
DelegateChoice {
roleValue: "upower"
delegate: WrappedLoader {
sourceComponent: UPowerWidget {
}
}
}
DelegateChoice {
roleValue: "network"
delegate: WrappedLoader {
sourceComponent: NetworkWidget {
}
}
}
DelegateChoice {
roleValue: "media"
delegate: WrappedLoader {
sourceComponent: MediaWidget {
}
}
}
}
}
component WrappedLoader: Loader {
required property bool enabled
required property string id
required property int index
function findFirstEnabled(): Item {
const count = repeater.count;
for (let i = 0; i < count; i++) {
const item = repeater.itemAt(i);
if (item?.enabled)
return item;
}
return null;
}
function findLastEnabled(): Item {
for (let i = repeater.count - 1; i >= 0; i--) {
const item = repeater.itemAt(i);
if (item?.enabled)
return item;
}
return null;
}
Layout.alignment: Qt.AlignVCenter
Layout.fillHeight: true
Layout.leftMargin: findFirstEnabled() === this ? root.vPadding : 0
Layout.rightMargin: findLastEnabled() === this ? root.vPadding : 0
active: enabled
visible: enabled
}
}
+4 -2
View File
@@ -38,9 +38,11 @@ Item {
Rectangle {
anchors.fill: parent
anchors.margins: Config.barConfig.border
anchors.topMargin: Config.barConfig.autoHide && !root.visibilities.bar ? 4 : root.bar.implicitHeight
topLeftRadius: 8
topRightRadius: 8
radius: Config.barConfig.border > 0 ? Config.barConfig.rounding : 0
topLeftRadius: Config.barConfig.rounding
topRightRadius: Config.barConfig.rounding
Behavior on anchors.topMargin {
Anim {
+5 -5
View File
@@ -16,11 +16,6 @@ Item {
readonly property bool shouldBeActive: visibilities.isDrawing
required property var visibilities
function show(): void {
visibilities.isDrawing = true;
timer.restart();
}
implicitHeight: content.implicitHeight
implicitWidth: 0
visible: width > 0
@@ -102,6 +97,11 @@ Item {
}
]
onVisibleChanged: {
if (!visible)
root.expanded = true;
}
Loader {
id: icon
+2 -2
View File
@@ -12,9 +12,9 @@ Item {
id: root
property real activeWorkspaceMargin: Math.ceil(Appearance.padding.small / 2)
required property PanelWindow bar
readonly property int effectiveActiveWorkspaceId: monitor?.activeWorkspace?.id ?? 1
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.bar.screen)
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.screen)
required property ShellScreen screen
property int workspaceButtonWidth: bgRect.implicitHeight - root.activeWorkspaceMargin * 2
property int workspaceIndexInGroup: (effectiveActiveWorkspaceId - 1) % root.workspacesShown
readonly property list<var> workspaces: Hyprland.workspaces.values.filter(w => w.monitor === root.monitor)