pragma ComponentBehavior: Bound import Quickshell import QtQuick import QtQuick.Layouts import ZShell.Config import qs.Components import qs.Modules.Bar.Components import qs.Modules.Bar.Popouts GridLayout { id: root required property bool fullscreen required property bool horizontal required property bool isHovered required property Wrapper popouts required property ClipWrapper popoutsWrapper required property ShellScreen screen required property ScreenState screenState readonly property int vPadding: 6 function axisCenterOf(item: Item): real { const c = item.mapToItem(root, item.implicitWidth / 2, item.implicitHeight / 2); return horizontal ? Math.floor(c.x) : Math.floor(c.y); } function checkPopout(pos: real): void { const ch = (horizontal ? childAt(pos, height / 2) : childAt(width / 2, pos)) as EntryWrapper; const id = ch?.entryId; if (!ch || id === undefined) { if (!popouts.currentName.startsWith("traymenu") || Config.bar.tray.showOnHover) popouts.hasCurrent = false; return; } if (screenState.sidebar || screenState.dashboard || screenState.resources || screenState.settings) return; if (id === "statusIcons" && Config.bar.popouts.statusIcons) { const items = (ch.item as StatusIcons).items; const icon = horizontal ? items.childAt(mapToItem(items, pos, 0).x, items.height / 2) : items.childAt(items.width / 2, mapToItem(items, 0, pos).y); if (icon) { popouts.currentName = icon.name; popouts.currentCenter = Qt.binding(() => axisCenterOf(icon)); popouts.hasCurrent = true; } } else if (id === "tray" && Config.bar.popouts.tray && Config.bar.tray.showOnHover) { const tray = ch.item as TrayIcons; const layout = tray.layout; const trayItem = horizontal ? layout.childAt(mapToItem(layout, pos, 0).x, layout.height / 2) : layout.childAt(tray.width / 2, mapToItem(layout, 0, pos).y); if (trayItem) { const idx = trayItem.index; popouts.currentName = `traymenu${idx}`; popouts.currentCenter = Qt.binding(() => axisCenterOf(trayItem)); popouts.hasCurrent = true; } if (!popouts.currentName.startsWith("traymenu")) popouts.hasCurrent = false; } if (id === "updates") { popouts.currentName = "updates"; popouts.currentCenter = Qt.binding(() => axisCenterOf(ch.item as Item)); popouts.hasCurrent = true; } } function entryAt(pos: real): string { const ch = (horizontal ? childAt(pos, height / 2) : childAt(width / 2, pos)) as EntryWrapper; return ch?.entryId ?? ""; } columnSpacing: Tokens.spacing.small columns: horizontal ? -1 : 1 rowSpacing: Tokens.spacing.small Repeater { id: repeater model: ScriptModel { values: Config.bar.entries.values.filter(e => e.enabled) } DelegateChooser { role: "id" DelegateChoice { roleValue: "nightlight" delegate: EntryWrapper { NightlightWidget { horizontal: root.horizontal visible: !root.fullscreen || root.isHovered } } } DelegateChoice { roleValue: "spacer" delegate: EntryWrapper { Layout.fillHeight: !root.horizontal Layout.fillWidth: root.horizontal } } DelegateChoice { roleValue: "workspaces" delegate: EntryWrapper { Workspaces { horizontal: root.horizontal screen: root.screen visible: !root.fullscreen || root.isHovered } } } DelegateChoice { roleValue: "tray" delegate: EntryWrapper { TrayIcons { horizontal: root.horizontal loader: root popouts: root.popouts visible: !root.fullscreen || root.isHovered } } } DelegateChoice { roleValue: "statusIcons" delegate: EntryWrapper { StatusIcons { horizontal: root.horizontal visible: !root.fullscreen || root.isHovered } } } DelegateChoice { roleValue: "resources" delegate: EntryWrapper { Resources { horizontal: root.horizontal screenState: root.screenState visible: !root.fullscreen || root.isHovered } } } DelegateChoice { roleValue: "updates" delegate: EntryWrapper { UpdatesWidget { horizontal: root.horizontal visible: !root.fullscreen || root.isHovered } } } DelegateChoice { roleValue: "notifBell" delegate: EntryWrapper { NotifBell { horizontal: root.horizontal popouts: root.popouts screenState: root.screenState visible: !root.fullscreen || root.isHovered } } } DelegateChoice { roleValue: "clock" delegate: EntryWrapper { Clock { horizontal: root.horizontal loader: root popouts: root.popouts screenState: root.screenState visible: !root.fullscreen || root.isHovered } } } DelegateChoice { roleValue: "activeWindow" delegate: EntryWrapper { WindowTitle { bar: root horizontal: root.horizontal visible: !root.fullscreen || root.isHovered } } } DelegateChoice { roleValue: "network" delegate: EntryWrapper { NetworkWidget {} } } DelegateChoice { roleValue: "media" delegate: EntryWrapper { MediaWidget { horizontal: root.horizontal visible: !root.fullscreen || root.isHovered } } } } } component EntryWrapper: Item { readonly property string entryId: modelData.id required property int index default property Item item required property var modelData Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter Layout.bottomMargin: !root.horizontal && index === repeater.count - 1 ? root.vPadding : 0 Layout.leftMargin: root.horizontal && index === 0 ? root.vPadding : (entryId === "statusIcons" && root.horizontal) ? -root.rowSpacing + Tokens.spacing.extraSmall : 0 Layout.rightMargin: root.horizontal && index === repeater.count - 1 ? root.vPadding : 0 Layout.topMargin: !root.horizontal && index === 0 ? root.vPadding : (entryId === "statusIcons" && !root.horizontal) ? -root.columnSpacing + Tokens.spacing.extraSmall : 0 children: item implicitHeight: item?.implicitHeight ?? 0 implicitWidth: item?.implicitWidth ?? 0 } }