fix: better width + height calculations for tray menu popouts

This commit is contained in:
2026-07-03 15:02:00 +02:00
parent 562770595f
commit cdf66bff23
+17 -32
View File
@@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
import Quickshell import Quickshell
import Quickshell.Widgets import Quickshell.Widgets
import QtQuick import QtQuick
import QtQuick.Layouts
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Effects import QtQuick.Effects
import qs.Components import qs.Components
@@ -12,14 +13,13 @@ import qs.Config
StackView { StackView {
id: root id: root
property int biggestWidth: 0
readonly property int itemHeight: 30 readonly property int itemHeight: 30
readonly property int panelRadius: ((itemHeight / 2) + Appearance.padding.small) * Appearance.rounding.scale readonly property int panelRadius: ((itemHeight / 2) + Appearance.padding.small) * Appearance.rounding.scale
required property PopoutState popouts required property PopoutState popouts
property int rootWidth: 0 property int rootWidth: 0
required property QsMenuHandle trayItem required property QsMenuHandle trayItem
implicitHeight: currentItem.implicitHeight implicitHeight: currentItem.isSubMenu ? currentItem.implicitHeight : currentItem.implicitHeight - currentItem.spacing
implicitWidth: currentItem.implicitWidth implicitWidth: currentItem.implicitWidth
initialItem: SubMenu { initialItem: SubMenu {
@@ -46,7 +46,7 @@ StackView {
duration: 0 duration: 0
} }
} }
component SubMenu: Column { component SubMenu: ColumnLayout {
id: menu id: menu
required property QsMenuHandle handle required property QsMenuHandle handle
@@ -54,9 +54,8 @@ StackView {
property bool shown property bool shown
opacity: shown ? 1 : 0 opacity: shown ? 1 : 0
padding: 0
scale: shown ? 1 : 0.8 scale: shown ? 1 : 0.8
spacing: 4 spacing: Appearance.spacing.extraSmall
Behavior on opacity { Behavior on opacity {
Anim { Anim {
@@ -87,22 +86,27 @@ StackView {
required property int index required property int index
required property QsMenuEntry modelData required property QsMenuEntry modelData
Layout.fillWidth: true
Layout.leftMargin: modelData.isSeparator ? Appearance.padding.normal : 0
Layout.rightMargin: modelData.isSeparator ? Appearance.padding.normal : 0
color: modelData.isSeparator ? DynamicColors.palette.m3outlineVariant : "transparent" color: modelData.isSeparator ? DynamicColors.palette.m3outlineVariant : "transparent"
implicitHeight: modelData.isSeparator ? 1 : children.implicitHeight implicitHeight: modelData.isSeparator ? (visible ? 1 : 0) : childrenLoader.item.implicitHeight
implicitWidth: root.biggestWidth implicitWidth: childrenLoader.item?.implicitWidth ?? 0
radius: Appearance.rounding.full radius: Appearance.rounding.full
visible: index !== (menuOpener.children.values.length - 1) ? true : (modelData.isSeparator ? false : true) visible: index !== (menuOpener.children.values.length - 1) ? true : (modelData.isSeparator ? false : true)
Loader { Loader {
id: children id: childrenLoader
active: !item.modelData.isSeparator active: !item.modelData.isSeparator
anchors.left: parent.left anchors.fill: parent
anchors.right: parent.right
asynchronous: true asynchronous: true
sourceComponent: Item { sourceComponent: Item {
property int iconWidth: icon.active ? icon.width + Appearance.spacing.normal + icon.anchors.rightMargin : 0
implicitHeight: root.itemHeight implicitHeight: root.itemHeight
implicitWidth: label.width + label.anchors.leftMargin * 2 + iconWidth
StateLayer { StateLayer {
enabled: item.modelData.enabled enabled: item.modelData.enabled
@@ -111,8 +115,6 @@ StackView {
onClicked: { onClicked: {
const entry = item.modelData; const entry = item.modelData;
if (entry.hasChildren) { if (entry.hasChildren) {
root.rootWidth = root.biggestWidth;
root.biggestWidth = 0;
root.push(subMenuComp.createObject(null, { root.push(subMenuComp.createObject(null, {
handle: entry, handle: entry,
isSubMenu: true isSubMenu: true
@@ -161,23 +163,7 @@ StackView {
anchors.leftMargin: 10 anchors.leftMargin: 10
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: item.modelData.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3outline color: item.modelData.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3outline
text: labelMetrics.elidedText
}
TextMetrics {
id: labelMetrics
font.family: label.font.family
font.pointSize: label.font.pointSize
text: item.modelData.text text: item.modelData.text
Component.onCompleted: {
var biggestWidth = root.biggestWidth;
var currentWidth = labelMetrics.width + (item.modelData.icon ?? "" ? 30 : 0) + (item.modelData.hasChildren ? 30 : 0) + 20;
if (currentWidth > biggestWidth) {
root.biggestWidth = currentWidth;
}
}
} }
Loader { Loader {
@@ -201,17 +187,17 @@ StackView {
Loader { Loader {
id: loader id: loader
Layout.fillWidth: true
Layout.maximumHeight: active ? implicitHeight : 0
active: menu.isSubMenu active: menu.isSubMenu
asynchronous: true asynchronous: true
sourceComponent: Item { sourceComponent: Item {
implicitHeight: 30 implicitHeight: 30
implicitWidth: back.implicitWidth
Item { Item {
anchors.bottom: parent.bottom anchors.fill: parent
implicitHeight: 30 implicitHeight: 30
implicitWidth: root.biggestWidth
CustomRect { CustomRect {
anchors.fill: parent anchors.fill: parent
@@ -224,7 +210,6 @@ StackView {
onClicked: { onClicked: {
root.pop(); root.pop();
root.biggestWidth = root.rootWidth;
} }
} }
} }