125 lines
3.4 KiB
QML
125 lines
3.4 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
import qs.Constants
|
|
import qs.Noctalia
|
|
import qs.Services
|
|
import qs.Utils
|
|
|
|
Popup {
|
|
id: root
|
|
|
|
property alias model: listView.model
|
|
property real itemHeight: 36
|
|
property real itemPadding: Style.marginM
|
|
|
|
signal triggered(string action)
|
|
|
|
// Helper function to open at mouse position
|
|
function openAt(x, y) {
|
|
root.x = x;
|
|
root.y = y;
|
|
root.open();
|
|
}
|
|
|
|
// Helper function to open at item
|
|
function openAtItem(item, mouseX, mouseY) {
|
|
var pos = item.mapToItem(root.parent, mouseX || 0, mouseY || 0);
|
|
openAt(pos.x, pos.y);
|
|
}
|
|
|
|
width: 180
|
|
padding: Style.marginS
|
|
onOpened: PanelService.willOpenPopup(root)
|
|
onClosed: PanelService.willClosePopup(root)
|
|
|
|
background: Rectangle {
|
|
color: Color.mSurfaceVariant
|
|
border.color: Color.mOutline
|
|
border.width: Math.max(1, Style.borderS)
|
|
radius: Style.radiusM
|
|
}
|
|
|
|
contentItem: NListView {
|
|
id: listView
|
|
|
|
implicitHeight: contentHeight
|
|
spacing: Style.marginXXS
|
|
interactive: contentHeight > root.height
|
|
|
|
delegate: ItemDelegate {
|
|
id: menuItem
|
|
|
|
// Store reference to the popup
|
|
property var popup: root
|
|
|
|
width: listView.width
|
|
height: modelData.visible !== false ? root.itemHeight : 0
|
|
visible: modelData.visible !== false
|
|
opacity: modelData.enabled !== false ? 1 : 0.5
|
|
enabled: modelData.enabled !== false
|
|
onClicked: {
|
|
if (enabled) {
|
|
popup.triggered(modelData.action || modelData.key || index.toString());
|
|
popup.close();
|
|
}
|
|
}
|
|
|
|
background: Rectangle {
|
|
color: menuItem.hovered && menuItem.enabled ? Color.mTertiary : Color.transparent
|
|
radius: Style.radiusS
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Style.animationFast
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
contentItem: RowLayout {
|
|
spacing: Style.marginS
|
|
|
|
// Optional icon
|
|
NIcon {
|
|
visible: modelData.icon !== undefined
|
|
icon: modelData.icon || ""
|
|
pointSize: Style.fontSizeM
|
|
color: menuItem.hovered && menuItem.enabled ? Color.mOnTertiary : Color.mOnSurface
|
|
Layout.leftMargin: root.itemPadding
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Style.animationFast
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NText {
|
|
text: modelData.label || modelData.text || ""
|
|
pointSize: Style.fontSizeM
|
|
color: menuItem.hovered && menuItem.enabled ? Color.mOnTertiary : Color.mOnSurface
|
|
verticalAlignment: Text.AlignVCenter
|
|
Layout.fillWidth: true
|
|
Layout.leftMargin: modelData.icon === undefined ? root.itemPadding : 0
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Style.animationFast
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|