86 lines
3.1 KiB
QML
86 lines
3.1 KiB
QML
import Quickshell
|
|
import Quickshell.Services.SystemTray
|
|
import Quickshell.Widgets
|
|
import QtQuick
|
|
import "../components"
|
|
|
|
Item {
|
|
id: root
|
|
required property var barWindow
|
|
implicitWidth: trayRow.width
|
|
implicitHeight: 24
|
|
|
|
Row {
|
|
id: trayRow
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: 3
|
|
|
|
Repeater {
|
|
model: SystemTray.items
|
|
|
|
delegate: Item {
|
|
id: trayDelegate
|
|
required property var modelData
|
|
|
|
width: 24
|
|
height: 24
|
|
|
|
// Hover highlight
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: Theme.radius
|
|
color: hoverArea.containsMouse ? Qt.rgba(1,1,1,0.08) : "transparent"
|
|
Behavior on color { ColorAnimation { duration: 80 } }
|
|
}
|
|
|
|
IconImage {
|
|
id: iconImg
|
|
anchors.centerIn: parent
|
|
implicitSize: 16
|
|
visible: status === Image.Ready
|
|
source: {
|
|
const icon = trayDelegate.modelData.icon
|
|
if (!icon || icon === "") return ""
|
|
if (icon.startsWith("/") || icon.startsWith("file://") || icon.startsWith("image://")) return icon
|
|
const path = Quickshell.iconPath(icon, "")
|
|
if (path !== "") return "file://" + path
|
|
return "image://icon/" + icon
|
|
}
|
|
mipmap: true
|
|
}
|
|
|
|
// Letter fallback when icon fails to load
|
|
Text {
|
|
anchors.centerIn: parent
|
|
visible: iconImg.status !== Image.Ready
|
|
text: (trayDelegate.modelData.title ?? trayDelegate.modelData.id ?? "?").charAt(0).toUpperCase()
|
|
color: Theme.textDim
|
|
font.pixelSize: 11
|
|
font.bold: true
|
|
}
|
|
|
|
MouseArea {
|
|
id: hoverArea
|
|
anchors.fill: parent
|
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
|
|
onClicked: mouse => {
|
|
const item = trayDelegate.modelData
|
|
const wantsMenu = mouse.button === Qt.RightButton || item.onlyMenu
|
|
if (wantsMenu && item.hasMenu) {
|
|
// display() needs the quickshell PanelWindow (not QQuickWindow).
|
|
// mapToItem(null) gives scene/window-local coordinates.
|
|
const pos = trayDelegate.mapToItem(null, 0, trayDelegate.height)
|
|
item.display(root.barWindow, Math.round(pos.x), Math.round(pos.y))
|
|
} else if (!item.onlyMenu) {
|
|
item.activate()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|