Files
z-bar-qt/Modules/Bar/Bar.qml
T

296 lines
7.1 KiB
QML

pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import QtQuick.Layouts
import ZShell.Config
import ZShell.Components
import qs.Components
import qs.Modules.Bar.Components
import qs.Modules.Bar.Popouts
SnapLayout {
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 ?? "";
}
readonly property var sectionRects: {
const count = repeater.count; // dependency: re-run when items are added/removed
const names = ["start", "middle", "end"]; // constant ids by position
const bounds = [null];
let spacers = 0;
for (let i = 0; i < count; i++) {
const it = repeater.itemAt(i) as EntryWrapper;
if (!it)
continue;
if (it.entryId === "spacer") {
bounds.push(null);
spacers++;
continue;
}
const l = it.x, t = it.y, r = it.x + it.width, b = it.y + it.height;
const cur = bounds[spacers];
bounds[spacers] = cur ? {
l: Math.min(cur.l, l),
t: Math.min(cur.t, t),
r: Math.max(cur.r, r),
b: Math.max(cur.b, b)
} : {
l,
t,
r,
b
};
}
return bounds.map((c, n) => ({
id: names[n] ?? `section${n}`,
rect: c ? Qt.rect(c.l, c.t, c.r - c.l, c.b - c.t) : Qt.rect(0, 0, 0, 0)
}));
}
spacing: Tokens.spacing.small
orientation: horizontal ? Qt.Horizontal : Qt.Vertical
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 int section: {
let n = 0;
for (let i = 0; i < index; i++) {
if (repeater.model.values[i].id === "spacer")
n++;
}
return n;
}
readonly property string entryId: modelData.id
required property int index
required property var modelData
default property Item item
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.spacing + 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.spacing + Tokens.spacing.extraSmall : 0
children: item
implicitHeight: item?.implicitHeight ?? 0
implicitWidth: item?.implicitWidth ?? 0
}
}