C++ / fmt (pull_request) Successful in 4s
JS/TS / lint (pull_request) Successful in 19s
JS/TS / fmt (pull_request) Successful in 21s
Python / fmt (pull_request) Successful in 30s
Python / lint (pull_request) Successful in 31s
Python / test (pull_request) Successful in 1m2s
Python / typecheck (pull_request) Failing after 1m5s
Rust / fmt (pull_request) Successful in 43s
C++ / build (pull_request) Successful in 2m25s
Rust / build (pull_request) Successful in 1m42s
Python / buildcheck (pull_request) Successful in 2m27s
Rust / clippy (pull_request) Successful in 1m29s
C++ / clang-tidy (pull_request) Successful in 3m56s
240 lines
5.3 KiB
QML
240 lines
5.3 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import Quickshell
|
|
import Quickshell.Widgets
|
|
import QtQuick
|
|
import QtQuick.Layouts
|
|
import QtQuick.Controls
|
|
import QtQuick.Effects
|
|
import qs.Components
|
|
import qs.Modules
|
|
import ZShell.Config
|
|
import qs.Services
|
|
|
|
StackView {
|
|
id: root
|
|
|
|
readonly property int itemHeight: 30
|
|
readonly property int panelRadius: ((itemHeight / 2) + Tokens.padding.small) * Tokens.rounding.scale
|
|
required property PopoutState popouts
|
|
property int rootWidth: 0
|
|
required property QsMenuHandle trayItem
|
|
|
|
implicitHeight: currentItem.isSubMenu ? currentItem.implicitHeight : currentItem.implicitHeight - currentItem.spacing
|
|
implicitWidth: currentItem.implicitWidth
|
|
|
|
initialItem: SubMenu {
|
|
handle: root.trayItem
|
|
}
|
|
popEnter: NoAnim {
|
|
}
|
|
popExit: NoAnim {
|
|
}
|
|
pushEnter: NoAnim {
|
|
}
|
|
pushExit: NoAnim {
|
|
}
|
|
|
|
Component {
|
|
id: subMenuComp
|
|
|
|
SubMenu {
|
|
}
|
|
}
|
|
|
|
component NoAnim: Transition {
|
|
NumberAnimation {
|
|
duration: 0
|
|
}
|
|
}
|
|
component SubMenu: ColumnLayout {
|
|
id: menu
|
|
|
|
required property QsMenuHandle handle
|
|
property bool isSubMenu
|
|
property bool shown
|
|
|
|
opacity: shown ? 1 : 0
|
|
scale: shown ? 1 : 0.8
|
|
spacing: Tokens.spacing.extraSmall
|
|
|
|
Behavior on opacity {
|
|
Anim {
|
|
}
|
|
}
|
|
Behavior on scale {
|
|
Anim {
|
|
}
|
|
}
|
|
|
|
Component.onCompleted: shown = true
|
|
StackView.onActivating: shown = true
|
|
StackView.onDeactivating: shown = false
|
|
StackView.onRemoved: destroy()
|
|
|
|
QsMenuOpener {
|
|
id: menuOpener
|
|
|
|
menu: menu.handle
|
|
}
|
|
|
|
Repeater {
|
|
model: menuOpener.children
|
|
|
|
CustomRect {
|
|
id: item
|
|
|
|
required property int index
|
|
required property QsMenuEntry modelData
|
|
|
|
Layout.fillWidth: true
|
|
Layout.leftMargin: modelData.isSeparator ? Tokens.padding.normal : 0
|
|
Layout.rightMargin: modelData.isSeparator ? Tokens.padding.normal : 0
|
|
color: modelData.isSeparator ? Colors.palette.m3outlineVariant : "transparent"
|
|
implicitHeight: modelData.isSeparator ? (visible ? 1 : 0) : childrenLoader.item.implicitHeight
|
|
implicitWidth: childrenLoader.item?.implicitWidth ?? 0
|
|
radius: Tokens.rounding.full
|
|
visible: index !== (menuOpener.children.values.length - 1) ? true : (modelData.isSeparator ? false : true)
|
|
|
|
Loader {
|
|
id: childrenLoader
|
|
|
|
active: !item.modelData.isSeparator
|
|
anchors.fill: parent
|
|
asynchronous: true
|
|
|
|
sourceComponent: Item {
|
|
property int iconWidth: icon.active ? icon.width + Tokens.spacing.normal + icon.anchors.rightMargin : 0
|
|
|
|
implicitHeight: root.itemHeight
|
|
implicitWidth: label.width + label.anchors.leftMargin * 2 + iconWidth + (expand.item?.width ?? 0)
|
|
|
|
StateLayer {
|
|
enabled: item.modelData.enabled
|
|
radius: item.radius
|
|
|
|
onClicked: {
|
|
const entry = item.modelData;
|
|
if (entry.hasChildren) {
|
|
root.push(subMenuComp.createObject(null, {
|
|
handle: entry,
|
|
isSubMenu: true
|
|
}));
|
|
} else {
|
|
item.modelData.triggered();
|
|
root.popouts.hasCurrent = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
id: icon
|
|
|
|
active: item.modelData.icon !== ""
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: 10
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
asynchronous: true
|
|
|
|
sourceComponent: Item {
|
|
implicitHeight: label.implicitHeight
|
|
implicitWidth: label.implicitHeight
|
|
|
|
IconImage {
|
|
id: iconImage
|
|
|
|
implicitSize: parent.implicitHeight
|
|
source: item.modelData.icon
|
|
visible: false
|
|
}
|
|
|
|
MultiEffect {
|
|
anchors.fill: iconImage
|
|
colorization: 1.0
|
|
colorizationColor: item.modelData.enabled ? Colors.palette.m3onSurface : Colors.palette.m3outline
|
|
source: iconImage
|
|
}
|
|
}
|
|
}
|
|
|
|
CustomText {
|
|
id: label
|
|
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: 10
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
color: item.modelData.enabled ? Colors.palette.m3onSurface : Colors.palette.m3outline
|
|
text: item.modelData.text
|
|
}
|
|
|
|
Loader {
|
|
id: expand
|
|
|
|
active: item.modelData.hasChildren
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
asynchronous: true
|
|
|
|
sourceComponent: MaterialIcon {
|
|
color: item.modelData.enabled ? Colors.palette.m3onSurface : Colors.palette.m3outline
|
|
text: "chevron_right"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
id: loader
|
|
|
|
Layout.fillWidth: true
|
|
Layout.maximumHeight: active ? implicitHeight : 0
|
|
active: menu.isSubMenu
|
|
asynchronous: true
|
|
|
|
sourceComponent: Item {
|
|
implicitHeight: 30
|
|
|
|
Item {
|
|
anchors.fill: parent
|
|
implicitHeight: 30
|
|
|
|
CustomRect {
|
|
anchors.fill: parent
|
|
color: Colors.palette.m3secondaryContainer
|
|
radius: Tokens.rounding.full
|
|
|
|
StateLayer {
|
|
color: Colors.palette.m3onSecondaryContainer
|
|
radius: parent.radius
|
|
|
|
onClicked: {
|
|
root.pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
Row {
|
|
id: back
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
MaterialIcon {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
color: Colors.palette.m3onSecondaryContainer
|
|
text: "chevron_left"
|
|
}
|
|
|
|
CustomText {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
color: Colors.palette.m3onSecondaryContainer
|
|
text: qsTr("Back")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|