diff options
Diffstat (limited to 'accounts/gkleen@sif/shell/quickshell/SystemTray.qml')
-rw-r--r-- | accounts/gkleen@sif/shell/quickshell/SystemTray.qml | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml new file mode 100644 index 00000000..55b1690e --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml | |||
@@ -0,0 +1,159 @@ | |||
1 | import QtQuick | ||
2 | import Quickshell | ||
3 | import Quickshell.Widgets | ||
4 | import Quickshell.Services.SystemTray | ||
5 | |||
6 | Item { | ||
7 | anchors.verticalCenter: parent.verticalCenter | ||
8 | width: systemTrayRow.childrenRect.width | ||
9 | height: parent.height | ||
10 | clip: true | ||
11 | |||
12 | Row { | ||
13 | id: systemTrayRow | ||
14 | anchors.centerIn: parent | ||
15 | width: childrenRect.width | ||
16 | height: parent.height | ||
17 | spacing: 0 | ||
18 | |||
19 | Repeater { | ||
20 | model: ScriptModel { | ||
21 | values: { | ||
22 | var trayItems = Array.from(SystemTray.items.values).filter(item => item.status !== Status.Passive); | ||
23 | trayItems.sort((a, b) => a.category !== b.category ? b.category - a.category : a.id.localeCompare(b.id)) | ||
24 | return trayItems; | ||
25 | } | ||
26 | } | ||
27 | |||
28 | delegate: Item { | ||
29 | id: trayItemWrapper | ||
30 | |||
31 | property var trayItem: modelData | ||
32 | property string iconSource: { | ||
33 | let icon = trayItem && trayItem.icon | ||
34 | if (typeof icon === 'string' || icon instanceof String) { | ||
35 | if (icon.includes("?path=")) { | ||
36 | const split = icon.split("?path=") | ||
37 | if (split.length !== 2) | ||
38 | return icon | ||
39 | const name = split[0] | ||
40 | const path = split[1] | ||
41 | const fileName = name.substring( | ||
42 | name.lastIndexOf("/") + 1) | ||
43 | return `file://${path}/${fileName}` | ||
44 | } | ||
45 | return icon | ||
46 | } | ||
47 | return "" | ||
48 | } | ||
49 | |||
50 | width: 16 | ||
51 | height: parent.height | ||
52 | anchors.verticalCenter: parent.verticalCenter | ||
53 | |||
54 | WrapperMouseArea { | ||
55 | id: trayItemArea | ||
56 | |||
57 | anchors.fill: parent | ||
58 | acceptedButtons: Qt.LeftButton | Qt.RightButton | ||
59 | hoverEnabled: true | ||
60 | cursorShape: trayItem.onlyMenu ? Qt.ArrowCursor : Qt.PointingHandCursor | ||
61 | onClicked: mouse => { | ||
62 | if (!trayItem) | ||
63 | return | ||
64 | |||
65 | if (mouse.button === Qt.LeftButton | ||
66 | && !trayItem.onlyMenu) { | ||
67 | trayItem.activate() | ||
68 | return | ||
69 | } | ||
70 | |||
71 | if (trayItem.hasMenu) { | ||
72 | var globalPos = mapToGlobal(0, 0) | ||
73 | var currentScreen = screen || Screen | ||
74 | var screenX = currentScreen.x || 0 | ||
75 | var relativeX = globalPos.x - screenX | ||
76 | menuAnchor.menu = trayItem.menu | ||
77 | menuAnchor.anchor.window = bar | ||
78 | menuAnchor.anchor.rect = Qt.rect( | ||
79 | relativeX, | ||
80 | 21, | ||
81 | parent.width, 1) | ||
82 | menuAnchor.open() | ||
83 | } | ||
84 | } | ||
85 | |||
86 | IconImage { | ||
87 | anchors.centerIn: parent | ||
88 | width: parent.width | ||
89 | height: parent.width | ||
90 | source: trayItemWrapper.iconSource | ||
91 | asynchronous: true | ||
92 | smooth: true | ||
93 | mipmap: true | ||
94 | } | ||
95 | } | ||
96 | |||
97 | PopupWindow { | ||
98 | id: tooltip | ||
99 | |||
100 | property bool nextVisible: (trayItem.tooltipTitle || trayItem.tooltipDescription) && (trayItemArea.containsMouse || tooltipMouseArea.containsMouse) && !menuAnchor.visible | ||
101 | |||
102 | anchor { | ||
103 | item: trayItemArea | ||
104 | edges: Edges.Bottom | ||
105 | } | ||
106 | |||
107 | visible: false | ||
108 | onNextVisibleChanged: hangTimer.restart() | ||
109 | |||
110 | Timer { | ||
111 | id: hangTimer | ||
112 | interval: 100 | ||
113 | onTriggered: tooltip.visible = tooltip.nextVisible | ||
114 | } | ||
115 | |||
116 | color: "black" | ||
117 | |||
118 | implicitWidth: Math.max(tooltipTitle.contentWidth, tooltipDescription.contentWidth) + 16 | ||
119 | implicitHeight: tooltipTitle.contentHeight + tooltipDescription.contentHeight + 16 | ||
120 | |||
121 | WrapperMouseArea { | ||
122 | id: tooltipMouseArea | ||
123 | |||
124 | hoverEnabled: true | ||
125 | enabled: true | ||
126 | |||
127 | margin: 8 | ||
128 | |||
129 | Column { | ||
130 | Text { | ||
131 | id: tooltipTitle | ||
132 | |||
133 | font.pointSize: 10 | ||
134 | font.family: "Fira Sans" | ||
135 | font.bold: true | ||
136 | color: "white" | ||
137 | |||
138 | text: trayItem.tooltipTitle | ||
139 | } | ||
140 | |||
141 | Text { | ||
142 | id: tooltipDescription | ||
143 | |||
144 | font.pointSize: 10 | ||
145 | font.family: "Fira Sans" | ||
146 | color: "white" | ||
147 | |||
148 | text: trayItem.tooltipDescription | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | QsMenuAnchor { | ||
157 | id: menuAnchor | ||
158 | } | ||
159 | } | ||