Files
quickdots/bar/modules/Tray.qml
2026-04-24 02:14:35 +00:00

162 lines
5.7 KiB
QML

import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Wayland
import Quickshell.Services.SystemTray
import Quickshell.Widgets
import "../../config" as Cfg
Item {
id: root
property real panelRadius: Cfg.Config.radius / 2
property int borderWidth: Cfg.Config.panelBorderWidth
property bool isTop: true
property var targetScreen: null
property string barSide: "right"
readonly property var t: Cfg.Config.theme
property bool expanded: false
property bool manuallyExpanded: false
property var menuWindow: null
implicitWidth: bgRect.width
implicitHeight: bgRect.height
Rectangle {
id: bgRect
anchors.verticalCenter: parent.verticalCenter
height: Cfg.Config.trayHeight
width: mainRow.width
radius: root.panelRadius
color: bgHover.hovered ? root.t.trayBgHover : root.t.trayBg
border.color: bgHover.hovered ? root.t.trayBorderHover : root.t.trayBorder
border.width: root.borderWidth
Behavior on color { ColorAnimation { duration: 150 } }
Behavior on border.color { ColorAnimation { duration: 150 } }
HoverHandler {
id: bgHover
onHoveredChanged: {
if (!root.manuallyExpanded) {
root.expanded = hovered;
}
}
}
Row {
id: mainRow
anchors.verticalCenter: parent.verticalCenter
leftPadding: root.expanded && root.barSide === "right" ? 8 : 0
rightPadding: root.expanded && root.barSide === "left" ? 8 : 0
Behavior on leftPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
Behavior on rightPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
layoutDirection: root.barSide === "left" ? Qt.LeftToRight : Qt.RightToLeft
spacing: root.expanded ? 4 : 0
Behavior on spacing { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } }
Item {
id: toggleArea
width: Cfg.Config.trayHeight
height: Cfg.Config.trayHeight
z: 10
TapHandler {
onTapped: {
root.manuallyExpanded = !root.manuallyExpanded;
root.expanded = root.manuallyExpanded;
}
}
Text {
anchors.centerIn: parent
text: root.expanded
? (root.barSide === "left" ? "󰅁" : "󰅂")
: (root.barSide === "left" ? "󰅂" : "󰅁")
color: root.t.trayIcon
font.pixelSize: Cfg.Config.trayHeight * 0.55
}
}
Row {
id: iconsRow
spacing: 6
clip: true
anchors.verticalCenter: parent.verticalCenter
width: root.expanded ? implicitWidth : 0
opacity: root.expanded ? 1 : 0
Behavior on width { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
Behavior on opacity { NumberAnimation { duration: 150 } }
Repeater {
model: SystemTray.items
delegate: MouseArea {
id: iconDelegate
required property SystemTrayItem modelData
property alias item: iconDelegate.modelData
implicitWidth: Cfg.Config.trayIconSize
implicitHeight: Cfg.Config.trayIconSize
width: Cfg.Config.trayIconSize
height: Cfg.Config.trayIconSize
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
hoverEnabled: true
onClicked: function(mouse) {
if (mouse.button === Qt.LeftButton) {
item.activate()
} else if (mouse.button === Qt.MiddleButton) {
item.secondaryActivate()
} else if (mouse.button === Qt.RightButton) {
menuAnchor.open()
}
}
onWheel: function(wheel) {
wheel.accepted = true
item.scroll(wheel.angleDelta.y / 120, false)
}
IconImage {
anchors.fill: parent
source: item.icon
}
QsMenuAnchor {
id: menuAnchor
menu: item.menu
anchor.window: root.menuWindow
anchor.adjustment: PopupAdjustment.Flip
anchor.onAnchoring: {
if (!root.menuWindow) return
const global = iconDelegate.mapToGlobal(0, iconDelegate.height)
const local = root.menuWindow.contentItem.mapFromGlobal(
global.x, global.y
)
menuAnchor.anchor.rect = Qt.rect(
local.x, local.y,
iconDelegate.width, 0
)
}
}
}
}
}
}
}
}