102 lines
3.3 KiB
QML
102 lines
3.3 KiB
QML
// A tray item's DBus menu, drawn natively so it inherits the shell's theme.
|
|
//
|
|
// Submenus drill down in place rather than flying out sideways — a popover with
|
|
// a back row, the way GNOME's menus behave, and far less fiddly than chasing a
|
|
// cascade of popup windows with the mouse.
|
|
|
|
import Quickshell
|
|
import Quickshell.Services.SystemTray
|
|
import QtQuick
|
|
import qs.config
|
|
import qs.widgets
|
|
|
|
Popover {
|
|
id: root
|
|
|
|
required property SystemTrayItem trayItem
|
|
|
|
// Popover's container is a plain Item and does not size itself from its
|
|
// children, so the window dimensions come from the column's implicit size.
|
|
// Rows take their *actual* width from the window in the other direction —
|
|
// the two chains are independent, so there is no binding loop.
|
|
implicitWidth: Math.max(body.implicitWidth + contentPadding * 2, 200)
|
|
implicitHeight: body.implicitHeight + contentPadding * 2
|
|
|
|
// Stack of submenu handles; empty means we are at the top level.
|
|
property var menuStack: []
|
|
|
|
onVisibleChanged: if (!visible)
|
|
root.menuStack = []
|
|
|
|
QsMenuOpener {
|
|
id: opener
|
|
menu: root.menuStack.length > 0 ? root.menuStack[root.menuStack.length - 1] : root.trayItem.menu
|
|
}
|
|
|
|
Column {
|
|
id: body
|
|
width: parent.width
|
|
spacing: 2
|
|
|
|
// Back row, only while inside a submenu.
|
|
TrayMenuRow {
|
|
width: parent.width
|
|
visible: root.menuStack.length > 0
|
|
label: "\u{F0141} Back" // md-chevron_left
|
|
onActivated: root.menuStack = root.menuStack.slice(0, -1)
|
|
}
|
|
|
|
Repeater {
|
|
model: opener.children
|
|
|
|
delegate: Loader {
|
|
id: entryLoader
|
|
|
|
required property var modelData
|
|
|
|
width: body.width
|
|
sourceComponent: entryLoader.modelData.isSeparator ? separator : row
|
|
|
|
Component {
|
|
id: separator
|
|
|
|
Item {
|
|
implicitHeight: 7
|
|
|
|
Rectangle {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: parent.width
|
|
height: 1
|
|
color: Theme.alpha(Theme.fg, 0.1)
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: row
|
|
|
|
TrayMenuRow {
|
|
// QsMenuEntry calls it `text`, not `label`.
|
|
label: entryLoader.modelData.text
|
|
icon: entryLoader.modelData.icon
|
|
rowEnabled: entryLoader.modelData.enabled
|
|
buttonType: entryLoader.modelData.buttonType
|
|
checkState: entryLoader.modelData.checkState
|
|
submenu: entryLoader.modelData.hasChildren
|
|
|
|
onActivated: {
|
|
if (entryLoader.modelData.hasChildren) {
|
|
root.menuStack = root.menuStack.concat([entryLoader.modelData]);
|
|
return;
|
|
}
|
|
|
|
entryLoader.modelData.triggered();
|
|
root.visible = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|