From e5c03448c2b68c1b1f80af11afcf13398493a529 Mon Sep 17 00:00:00 2001 From: zach Date: Tue, 7 Apr 2026 00:06:21 +0200 Subject: [PATCH] test new systray --- Modules/AudioWidget.qml | 96 -------------- Modules/Bar/Bar.qml | 39 +++--- Modules/Bar/BarLoader.qml | 3 +- Modules/Content.qml | 2 +- Modules/Resource.qml | 5 + Modules/{ => SysTray/Popouts}/AudioPopup.qml | 0 .../{ => SysTray/Popouts}/TrayMenuPopout.qml | 0 .../Popouts}/UPowerPopout.qml | 0 Modules/{ => SysTray}/TrayItem.qml | 0 Modules/SysTray/TrayWidget.qml | 122 ++++++++++++++++++ Modules/SysTray/Widgets/AudioWidget.qml | 31 +++++ Modules/SysTray/Widgets/UPowerWidget.qml | 35 +++++ Modules/TrayWidget.qml | 48 ------- Modules/UPower/UPowerWidget.qml | 51 -------- 14 files changed, 216 insertions(+), 216 deletions(-) delete mode 100644 Modules/AudioWidget.qml rename Modules/{ => SysTray/Popouts}/AudioPopup.qml (100%) rename Modules/{ => SysTray/Popouts}/TrayMenuPopout.qml (100%) rename Modules/{UPower => SysTray/Popouts}/UPowerPopout.qml (100%) rename Modules/{ => SysTray}/TrayItem.qml (100%) create mode 100644 Modules/SysTray/TrayWidget.qml create mode 100644 Modules/SysTray/Widgets/AudioWidget.qml create mode 100644 Modules/SysTray/Widgets/UPowerWidget.qml delete mode 100644 Modules/TrayWidget.qml delete mode 100644 Modules/UPower/UPowerWidget.qml diff --git a/Modules/AudioWidget.qml b/Modules/AudioWidget.qml deleted file mode 100644 index 2a99d5f..0000000 --- a/Modules/AudioWidget.qml +++ /dev/null @@ -1,96 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import Quickshell.Io -import Quickshell.Services.Pipewire -import qs.Daemons -import qs.Modules -import qs.Config -import qs.Components - -CustomRect { - id: root - - property color barColor: DynamicColors.palette.m3primary - property color textColor: DynamicColors.palette.m3onSurface - - color: DynamicColors.tPalette.m3surfaceContainer - implicitHeight: Config.barConfig.height + Appearance.padding.smallest * 2 - implicitWidth: 150 - radius: Appearance.rounding.full - - Behavior on implicitWidth { - NumberAnimation { - duration: 300 - easing.type: Easing.OutCubic - } - } - - Component.onCompleted: console.log(root.height, root.implicitHeight) - - RowLayout { - id: layout - - anchors.left: parent.left - anchors.leftMargin: Appearance.padding.small - anchors.verticalCenter: parent.verticalCenter - width: root.implicitWidth - Appearance.padding.small * 3 - - MaterialIcon { - Layout.alignment: Qt.AlignVCenter - animate: true - color: Audio.muted ? DynamicColors.palette.m3error : root.textColor - font.pointSize: Appearance.font.size.larger - text: Audio.muted ? "volume_off" : "volume_up" - } - - CustomRect { - Layout.fillWidth: true - color: DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHigh, 2) - implicitHeight: 4 - radius: 20 - - CustomRect { - id: sinkVolumeBar - - color: Audio.muted ? DynamicColors.palette.m3error : root.barColor - implicitWidth: parent.width * (Audio.volume ?? 0) - radius: parent.radius - - anchors { - bottom: parent.bottom - left: parent.left - top: parent.top - } - } - } - - MaterialIcon { - Layout.alignment: Qt.AlignVCenter - animate: true - color: (Audio.sourceMuted ?? false) ? DynamicColors.palette.m3error : root.textColor - font.pointSize: Appearance.font.size.larger - text: Audio.sourceMuted ? "mic_off" : "mic" - } - - CustomRect { - Layout.fillWidth: true - color: DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHigh, 2) - implicitHeight: 4 - radius: 20 - - CustomRect { - id: sourceVolumeBar - - color: (Audio.sourceMuted ?? false) ? DynamicColors.palette.m3error : root.barColor - implicitWidth: parent.width * (Audio.sourceVolume ?? 0) - radius: parent.radius - - anchors { - bottom: parent.bottom - left: parent.left - top: parent.top - } - } - } - } -} diff --git a/Modules/Bar/Bar.qml b/Modules/Bar/Bar.qml index 8115e8e..74459f4 100644 --- a/Modules/Bar/Bar.qml +++ b/Modules/Bar/Bar.qml @@ -7,7 +7,8 @@ import qs.Components import qs.Modules import qs.Config import qs.Helpers -import qs.Modules.UPower +import qs.Modules.SysTray +import qs.Modules.SysTray.Widgets import qs.Modules.Network import qs.Modules.Updates @@ -31,6 +32,24 @@ RowLayout { if (visibilities.sidebar || visibilities.dashboard || visibilities.resources || visibilities.settings) return; + if (ch.id === "tray") { + const tray = ch.item; + const localPos = tray.mapFromItem(root, x, height / 2); + const sub = tray.getHoveredSubItem(localPos.x, localPos.y); + if (sub) { + popouts.currentName = sub.id; + popouts.currentCenter = Qt.binding(() => { + const centerX = sub.item.mapToItem(root, sub.item.width / 2, 0).x; + return centerX; + }); + popouts.hasCurrent = true; + return; + } + + if (!popouts.currentName.startsWith("traymenu")) + popouts.hasCurrent = false; + } + const id = ch.id; const top = ch.x; const item = ch.item; @@ -93,15 +112,6 @@ RowLayout { } } - DelegateChoice { - roleValue: "audio" - - delegate: WrappedLoader { - sourceComponent: AudioWidget { - } - } - } - DelegateChoice { roleValue: "tray" @@ -165,15 +175,6 @@ RowLayout { } } - DelegateChoice { - roleValue: "upower" - - delegate: WrappedLoader { - sourceComponent: UPowerWidget { - } - } - } - DelegateChoice { roleValue: "network" diff --git a/Modules/Bar/BarLoader.qml b/Modules/Bar/BarLoader.qml index 0e4863f..6c16698 100644 --- a/Modules/Bar/BarLoader.qml +++ b/Modules/Bar/BarLoader.qml @@ -8,7 +8,8 @@ import qs.Components import qs.Modules import qs.Config import qs.Helpers -import qs.Modules.UPower +import qs.Modules.SysTray +import qs.Modules.SysTray.Widgets import qs.Modules.Network Item { diff --git a/Modules/Content.qml b/Modules/Content.qml index 0040b7a..f52280b 100644 --- a/Modules/Content.qml +++ b/Modules/Content.qml @@ -7,7 +7,7 @@ import qs.Config import qs.Components import qs.Modules.WSOverview import qs.Modules.Network -import qs.Modules.UPower +import qs.Modules.SysTray.Popouts import qs.Modules.Updates Item { diff --git a/Modules/Resource.qml b/Modules/Resource.qml index f927712..ac48314 100644 --- a/Modules/Resource.qml +++ b/Modules/Resource.qml @@ -57,6 +57,11 @@ RowLayout { anchors.right: parent.right color: root.mainColor implicitHeight: Math.ceil(root.percentage * parent.height) + + Behavior on implicitHeight { + Anim { + } + } } } } diff --git a/Modules/AudioPopup.qml b/Modules/SysTray/Popouts/AudioPopup.qml similarity index 100% rename from Modules/AudioPopup.qml rename to Modules/SysTray/Popouts/AudioPopup.qml diff --git a/Modules/TrayMenuPopout.qml b/Modules/SysTray/Popouts/TrayMenuPopout.qml similarity index 100% rename from Modules/TrayMenuPopout.qml rename to Modules/SysTray/Popouts/TrayMenuPopout.qml diff --git a/Modules/UPower/UPowerPopout.qml b/Modules/SysTray/Popouts/UPowerPopout.qml similarity index 100% rename from Modules/UPower/UPowerPopout.qml rename to Modules/SysTray/Popouts/UPowerPopout.qml diff --git a/Modules/TrayItem.qml b/Modules/SysTray/TrayItem.qml similarity index 100% rename from Modules/TrayItem.qml rename to Modules/SysTray/TrayItem.qml diff --git a/Modules/SysTray/TrayWidget.qml b/Modules/SysTray/TrayWidget.qml new file mode 100644 index 0000000..c368a26 --- /dev/null +++ b/Modules/SysTray/TrayWidget.qml @@ -0,0 +1,122 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Services.SystemTray +import qs.Components +import qs.Config +import qs.Modules.SysTray.Widgets +import qs.Modules.SysTray.Popouts +import qs.Modules + +RowLayout { + id: root + + readonly property alias items: repeater + required property RowLayout loader + required property Wrapper popouts + + function getHoveredSubItem(localX, localY) { + let modPos = mapToItem(sysTrayMod, localX, localY); + if (sysTrayMod.contains(Qt.point(modPos.x, modPos.y))) { + let modRowPos = sysTrayMod.mapToItem(sysModRow, modPos.x, modPos.y); + let child = sysModRow.childAt(modRowPos.x, modRowPos.y); + if (child) { + if (child.objectName === "audioWidget") + return { + id: "audio", + item: child + }; + if (child.objectName === "upowerWidget") + return { + id: "upower", + item: child + }; + } + } + + let trayPos = mapToItem(sysTray, localX, localY); + if (sysTray.contains(Qt.point(trayPos.x, trayPos.y))) { + let trayRowPos = sysTray.mapToItem(sysRow, trayPos.x, trayPos.y); + let child = sysRow.childAt(trayRowPos.x, trayRowPos.y); + if (child && child.hasOwnProperty("popoutId")) { + return { + id: child.popoutId, + item: child + }; + } + } + + return null; + } + + height: Config.barConfig.height + Appearance.padding.smallest * 2 + spacing: Appearance.padding.small + width: sysTray.implicitWidth + sysTrayMod.implicitWidth + Appearance.padding.small + + CustomClippingRect { + id: sysTray + + Layout.fillHeight: true + bottomRightRadius: Appearance.rounding.smallest / 2 + color: DynamicColors.tPalette.m3surfaceContainer + implicitWidth: sysRow.width + Appearance.padding.small * 2 + radius: Appearance.rounding.full + topRightRadius: Appearance.rounding.smallest / 2 + + Row { + id: sysRow + + anchors.centerIn: parent + spacing: 0 + + Repeater { + id: repeater + + model: SystemTray.items + + TrayItem { + id: trayItem + + required property int index + required property SystemTrayItem modelData + + implicitHeight: 34 + implicitWidth: 34 + ind: index + item: modelData + loader: root.loader + popouts: root.popouts + } + } + } + } + + CustomClippingRect { + id: sysTrayMod + + Layout.fillHeight: true + bottomLeftRadius: Appearance.rounding.smallest / 2 + color: DynamicColors.tPalette.m3surfaceContainer + implicitWidth: sysModRow.width + Appearance.padding.smaller * 2 + radius: Appearance.rounding.full + topLeftRadius: Appearance.rounding.smallest / 2 + + Row { + id: sysModRow + + anchors.centerIn: parent + spacing: Appearance.padding.small + + AudioWidget { + objectName: "audioWidget" + } + + UPowerWidget { + height: parent.height + objectName: "upowerWidget" + } + } + } +} diff --git a/Modules/SysTray/Widgets/AudioWidget.qml b/Modules/SysTray/Widgets/AudioWidget.qml new file mode 100644 index 0000000..9d1d38f --- /dev/null +++ b/Modules/SysTray/Widgets/AudioWidget.qml @@ -0,0 +1,31 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell.Io +import Quickshell.Services.Pipewire +import qs.Daemons +import qs.Modules +import qs.Config +import qs.Components + +RowLayout { + id: root + + property color barColor: DynamicColors.palette.m3primary + property color textColor: DynamicColors.palette.m3onSurface + + MaterialIcon { + Layout.alignment: Qt.AlignVCenter + animate: true + color: (Audio.sourceMuted ?? false) ? DynamicColors.palette.m3error : root.textColor + font.pointSize: Appearance.font.size.larger + text: Audio.sourceMuted ? "mic_off" : "mic" + } + + MaterialIcon { + Layout.alignment: Qt.AlignVCenter + animate: true + color: Audio.muted ? DynamicColors.palette.m3error : root.textColor + font.pointSize: Appearance.font.size.larger + text: Audio.muted ? "volume_off" : "volume_up" + } +} diff --git a/Modules/SysTray/Widgets/UPowerWidget.qml b/Modules/SysTray/Widgets/UPowerWidget.qml new file mode 100644 index 0000000..e7810e5 --- /dev/null +++ b/Modules/SysTray/Widgets/UPowerWidget.qml @@ -0,0 +1,35 @@ +import Quickshell.Services.UPower +import QtQuick +import QtQuick.Layouts +import qs.Components +import qs.Config +import qs.Helpers as Helpers + +RowLayout { + id: root + + MaterialIcon { + Layout.alignment: Qt.AlignVCenter + animate: true + color: !Helpers.UPower.onBattery || UPower.displayDevice.percentage > 0.2 ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3error + fill: 1 + text: { + if (!Helpers.UPower.displayDevice.isLaptopBattery) { + if (PowerProfiles.profile === PowerProfile.PowerSaver) + return "nest_eco_leaf"; + if (PowerProfiles.profile === PowerProfile.Performance) + return "bolt"; + return "power_settings_new"; + } + + const perc = Helpers.UPower.displayDevice.percentage; + const charging = [UPowerDeviceState.Charging, UPowerDeviceState.FullyCharged, UPowerDeviceState.PendingCharge].includes(Helpers.UPower.displayDevice.state); + if (perc === 1) + return charging ? "battery_charging_full" : "battery_full"; + let level = Math.floor(perc * 7); + if (charging && (level === 4 || level === 1)) + level--; + return charging ? `battery_charging_${(level + 3) * 10}` : `battery_${level}_bar`; + } + } +} diff --git a/Modules/TrayWidget.qml b/Modules/TrayWidget.qml deleted file mode 100644 index 9f1cb5b..0000000 --- a/Modules/TrayWidget.qml +++ /dev/null @@ -1,48 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Services.SystemTray -import qs.Components -import qs.Config - -CustomClippingRect { - id: root - - readonly property alias items: repeater - required property RowLayout loader - required property Wrapper popouts - - color: DynamicColors.tPalette.m3surfaceContainer - implicitHeight: Config.barConfig.height + Appearance.padding.smallest * 2 - implicitWidth: row.width + Appearance.padding.small * 2 - radius: height / 2 - - Row { - id: row - - anchors.centerIn: parent - spacing: 0 - - Repeater { - id: repeater - - model: SystemTray.items - - TrayItem { - id: trayItem - - required property int index - required property SystemTrayItem modelData - - implicitHeight: 34 - implicitWidth: 34 - ind: index - item: modelData - loader: root.loader - popouts: root.popouts - } - } - } -} diff --git a/Modules/UPower/UPowerWidget.qml b/Modules/UPower/UPowerWidget.qml deleted file mode 100644 index d93a956..0000000 --- a/Modules/UPower/UPowerWidget.qml +++ /dev/null @@ -1,51 +0,0 @@ -import Quickshell.Services.UPower -import QtQuick -import QtQuick.Layouts -import qs.Components -import qs.Config -import qs.Helpers as Helpers - -CustomRect { - id: root - - color: DynamicColors.tPalette.m3surfaceContainer - implicitHeight: Config.barConfig.height + Appearance.padding.smallest * 2 - implicitWidth: layout.implicitWidth + Appearance.padding.normal * 2 - radius: Appearance.rounding.full - - RowLayout { - id: layout - - anchors.centerIn: parent - - MaterialIcon { - Layout.alignment: Qt.AlignVCenter - animate: true - color: !Helpers.UPower.onBattery || UPower.displayDevice.percentage > 0.2 ? DynamicColors.palette.m3secondary : DynamicColors.palette.m3error - fill: 1 - text: { - if (!Helpers.UPower.displayDevice.isLaptopBattery) { - if (PowerProfiles.profile === PowerProfile.PowerSaver) - return "nest_eco_leaf"; - if (PowerProfiles.profile === PowerProfile.Performance) - return "bolt"; - return "power_settings_new"; - } - - const perc = Helpers.UPower.displayDevice.percentage; - const charging = [UPowerDeviceState.Charging, UPowerDeviceState.FullyCharged, UPowerDeviceState.PendingCharge].includes(Helpers.UPower.displayDevice.state); - if (perc === 1) - return charging ? "battery_charging_full" : "battery_full"; - let level = Math.floor(perc * 7); - if (charging && (level === 4 || level === 1)) - level--; - return charging ? `battery_charging_${(level + 3) * 10}` : `battery_${level}_bar`; - } - } - - CustomText { - Layout.alignment: Qt.AlignVCenter - text: Helpers.UPower.displayDevice.isLaptopBattery ? qsTr("%1%").arg(Math.round(UPower.displayDevice.percentage * 100)) : (PowerProfiles.profile === PowerProfile.PowerSaver ? qsTr("Pwr Sav") : PowerProfiles.profile === PowerProfile.Performance ? qsTr("Perf") : qsTr("Bal")) - } - } -}