Customtray #3
@@ -16,6 +16,7 @@ Scope {
|
|||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: bar
|
id: bar
|
||||||
required property var modelData
|
required property var modelData
|
||||||
|
property bool trayMenuVisible: false
|
||||||
screen: modelData
|
screen: modelData
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
|
||||||
|
PopupWindow {
|
||||||
|
id: root
|
||||||
|
required property QsMenuHandle menu
|
||||||
|
property int height: entryCount * ( entryHeight + 3 )
|
||||||
|
property int entryHeight: 30
|
||||||
|
property int entryCount: 0
|
||||||
|
implicitWidth: 300
|
||||||
|
implicitHeight: height
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
QsMenuOpener {
|
||||||
|
id: menuOpener
|
||||||
|
menu: root.menu
|
||||||
|
}
|
||||||
|
|
||||||
|
HyprlandFocusGrab {
|
||||||
|
id: grab
|
||||||
|
windows: [ root ]
|
||||||
|
onCleared: {
|
||||||
|
root.visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
grab.active = root.visible;
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
id: menuRect
|
||||||
|
anchors.fill: parent
|
||||||
|
color: "#90000000"
|
||||||
|
radius: 8
|
||||||
|
border.color: "#10FFFFFF"
|
||||||
|
ColumnLayout {
|
||||||
|
id: columnLayout
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 5
|
||||||
|
spacing: 2
|
||||||
|
Repeater {
|
||||||
|
id: repeater
|
||||||
|
model: menuOpener.children
|
||||||
|
Rectangle {
|
||||||
|
id: menuItem
|
||||||
|
width: root.implicitWidth
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
Layout.fillHeight: true
|
||||||
|
height: root.entryHeight
|
||||||
|
color: mouseArea.containsMouse && !modelData.isSeparator ? "#15FFFFFF" : "transparent"
|
||||||
|
radius: 4
|
||||||
|
visible: modelData.isSeparator ? false : true
|
||||||
|
required property QsMenuEntry modelData
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if ( !modelData.isSeparator ) {
|
||||||
|
root.entryCount += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
preventStealing: true
|
||||||
|
propagateComposedEvents: true
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
onClicked: {
|
||||||
|
if ( !menuItem.modelData.hasChildren ) {
|
||||||
|
menuItem.modelData.triggered();
|
||||||
|
root.visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
text: menuItem.modelData.text
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
-16
@@ -6,27 +6,22 @@ import QtQuick.Effects
|
|||||||
import Caelestia
|
import Caelestia
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Widgets
|
import Quickshell.Widgets
|
||||||
|
import Quickshell.Hyprland
|
||||||
import Quickshell.Services.SystemTray
|
import Quickshell.Services.SystemTray
|
||||||
|
import qs.Modules
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property SystemTrayItem item
|
required property SystemTrayItem item
|
||||||
|
property var menuHandle
|
||||||
|
|
||||||
implicitWidth: 22
|
implicitWidth: 22
|
||||||
implicitHeight: 22
|
implicitHeight: 22
|
||||||
|
|
||||||
|
hoverEnabled: true
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
onClicked: event => {
|
|
||||||
switch (event.button) {
|
|
||||||
case Qt.LeftButton: root.item.activate(); break;
|
|
||||||
case Qt.RightButton:
|
|
||||||
if (root.item.hasMenu) {
|
|
||||||
menuAnchor.open();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IconImage {
|
IconImage {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
@@ -47,17 +42,40 @@ MouseArea {
|
|||||||
|
|
||||||
mipmap: false
|
mipmap: false
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
|
||||||
ImageAnalyser {
|
ImageAnalyser {
|
||||||
id: analyser
|
id: analyser
|
||||||
sourceItem: icon
|
sourceItem: icon
|
||||||
|
rescaleSize: 20
|
||||||
}
|
}
|
||||||
}
|
|
||||||
QsMenuAnchor {
|
TrayMenu {
|
||||||
id: menuAnchor
|
id: trayMenu
|
||||||
menu: root.item.menu
|
menu: root.item.menu
|
||||||
anchor.item: root
|
anchor.item: root
|
||||||
anchor.edges: Edges.Bottom | Edges.Left
|
anchor.edges: Edges.Bottom
|
||||||
anchor.margins.top: 23
|
onVisibleChanged: {
|
||||||
anchor.adjustment: PopupAdjustment.SlideX
|
if ( grab.active && !visible ) {
|
||||||
|
grab.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HyprlandFocusGrab {
|
||||||
|
id: grab
|
||||||
|
windows: [ trayMenu ]
|
||||||
|
onCleared: {
|
||||||
|
trayMenu.visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if ( mouse.button === Qt.LeftButton ) {
|
||||||
|
root.item.activate();
|
||||||
|
} else if ( mouse.button === Qt.RightButton ) {
|
||||||
|
trayMenu.visible = !trayMenu.visible;
|
||||||
|
grab.active = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Qt5Compat.GraphicalEffects
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
|
||||||
|
PopupWindow {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
signal menuActionTriggered()
|
||||||
|
required property QsMenuHandle menu
|
||||||
|
property int height: {
|
||||||
|
let count = 0;
|
||||||
|
for (let i = 0; i < repeater.count; i++) {
|
||||||
|
if (!repeater.itemAt(i).modelData.isSeparator) count++;
|
||||||
|
}
|
||||||
|
return count * (entryHeight + 3);
|
||||||
|
}
|
||||||
|
property int entryHeight: 30
|
||||||
|
property int maxWidth: 100
|
||||||
|
implicitWidth: Math.max(100, maxWidth + 20)
|
||||||
|
implicitHeight: height
|
||||||
|
color: "transparent"
|
||||||
|
anchor.margins {
|
||||||
|
left: -implicitWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
QsMenuOpener {
|
||||||
|
id: menuOpener
|
||||||
|
menu: root.menu
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: menuRect
|
||||||
|
anchors.fill: parent
|
||||||
|
color: "#90000000"
|
||||||
|
radius: 8
|
||||||
|
border.color: "#10FFFFFF"
|
||||||
|
ColumnLayout {
|
||||||
|
id: columnLayout
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 5
|
||||||
|
spacing: 2
|
||||||
|
Repeater {
|
||||||
|
id: repeater
|
||||||
|
model: menuOpener.children
|
||||||
|
Rectangle {
|
||||||
|
id: menuItem
|
||||||
|
property bool containsMouseAndEnabled: mouseArea.containsMouse && menuItem.modelData.enabled
|
||||||
|
property bool containsMouseAndNotEnabled: mouseArea.containsMouse && !menuItem.modelData.enabled
|
||||||
|
width: root.implicitWidth
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
Layout.fillHeight: true
|
||||||
|
height: root.entryHeight
|
||||||
|
color: modelData.isSeparator ? "transparent" : containsMouseAndEnabled ? "#15FFFFFF" : containsMouseAndNotEnabled ? "#08FFFFFF" : "transparent"
|
||||||
|
radius: 4
|
||||||
|
visible: modelData.isSeparator ? false : true
|
||||||
|
required property QsMenuEntry modelData
|
||||||
|
|
||||||
|
TextMetrics {
|
||||||
|
id: textMetrics
|
||||||
|
font: menuText.font
|
||||||
|
text: menuItem.modelData.text
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
// Measure text width to determine maximumWidth
|
||||||
|
var textWidth = textMetrics.width + 20 + (iconImage.source ? iconImage.width + 10 : 0);
|
||||||
|
if ( textWidth > 0 && textWidth > root.maxWidth ) {
|
||||||
|
root.maxWidth = textWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
preventStealing: true
|
||||||
|
propagateComposedEvents: true
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
onClicked: {
|
||||||
|
if ( !menuItem.modelData.hasChildren ) {
|
||||||
|
if ( menuItem.modelData.enabled ) {
|
||||||
|
menuItem.modelData.triggered();
|
||||||
|
root.menuActionTriggered();
|
||||||
|
root.visible = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
subMenuComponent.createObject( null, {
|
||||||
|
menu: menuItem.modelData,
|
||||||
|
anchor: {
|
||||||
|
item: menuItem,
|
||||||
|
edges: Edges.Right
|
||||||
|
},
|
||||||
|
visible: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
Text {
|
||||||
|
id: menuText
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||||
|
Layout.leftMargin: 10
|
||||||
|
text: menuItem.modelData.text
|
||||||
|
color: menuItem.modelData.enabled ? "white" : "gray"
|
||||||
|
}
|
||||||
|
Image {
|
||||||
|
id: iconImage
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||||
|
Layout.rightMargin: 10
|
||||||
|
Layout.maximumWidth: 20
|
||||||
|
Layout.maximumHeight: 20
|
||||||
|
source: menuItem.modelData.icon
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
layer.enabled: true
|
||||||
|
layer.effect: ColorOverlay {
|
||||||
|
color: menuItem.modelData.enabled ? "white" : "gray"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component {
|
||||||
|
id: subMenuComponent
|
||||||
|
SubMenu {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.SystemTray
|
import Quickshell.Services.SystemTray
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
id: root
|
||||||
required property PanelWindow bar
|
required property PanelWindow bar
|
||||||
implicitHeight: parent.height
|
implicitHeight: parent.height
|
||||||
implicitWidth: rowL.implicitWidth + 20
|
implicitWidth: rowL.implicitWidth + 20
|
||||||
@@ -14,6 +17,7 @@ Rectangle {
|
|||||||
id: rowL
|
id: rowL
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
Repeater {
|
Repeater {
|
||||||
|
id: repeater
|
||||||
model: SystemTray.items
|
model: SystemTray.items
|
||||||
TrayItem {
|
TrayItem {
|
||||||
required property SystemTrayItem modelData
|
required property SystemTrayItem modelData
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell.Wayland
|
||||||
|
|
||||||
|
Scope {
|
||||||
|
Variants {
|
||||||
|
model: Quickshell.screens
|
||||||
|
PanelWindow {
|
||||||
|
id: root
|
||||||
|
required property var modelData
|
||||||
|
screen: modelData
|
||||||
|
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
||||||
|
WlrLayershell.layer: WlrLayer.Bottom
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
top: true
|
||||||
|
left: true
|
||||||
|
right: true
|
||||||
|
bottom: true
|
||||||
|
}
|
||||||
|
Image {
|
||||||
|
id: wallpaperImage
|
||||||
|
anchors.fill: parent
|
||||||
|
source: "/mnt/IronWolf/SDImages/SWWW_Wals/ComfyUI_00037_.png"
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user