summaryrefslogtreecommitdiff
path: root/accounts/gkleen@sif/shell/quickshell/Bar.qml
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/gkleen@sif/shell/quickshell/Bar.qml')
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Bar.qml327
1 files changed, 13 insertions, 314 deletions
diff --git a/accounts/gkleen@sif/shell/quickshell/Bar.qml b/accounts/gkleen@sif/shell/quickshell/Bar.qml
index 52f875da..aab1607f 100644
--- a/accounts/gkleen@sif/shell/quickshell/Bar.qml
+++ b/accounts/gkleen@sif/shell/quickshell/Bar.qml
@@ -1,16 +1,13 @@
1import Quickshell 1import Quickshell
2import Quickshell.Io
3import Quickshell.Services.SystemTray
4import Quickshell.Widgets
5import Custom as Custom
6import QtQuick 2import QtQuick
7import qs.Services
8 3
9 4
10PanelWindow { 5PanelWindow {
11 id: bar 6 id: bar
12 7
13 property var modelData 8 required property var screen
9
10 property var calendarMouseArea: clock.calendarMouseArea
14 11
15 anchors { 12 anchors {
16 top: true 13 top: true
@@ -22,12 +19,11 @@ PanelWindow {
22 right: 26 + 8 19 right: 26 + 8
23 } 20 }
24 21
25 screen: modelData
26 implicitHeight: 21 22 implicitHeight: 21
27 color: "transparent" 23 color: "transparent"
28 24
29 Rectangle { 25 Rectangle {
30 color: Qt.rgba(0, 0, 0, 0.66) 26 color: Qt.rgba(0, 0, 0, 0.75)
31 anchors.fill: parent 27 anchors.fill: parent
32 // bottomLeftRadius: 8 28 // bottomLeftRadius: 8
33 // bottomRightRadius: 8 29 // bottomRightRadius: 8
@@ -43,74 +39,7 @@ PanelWindow {
43 anchors.verticalCenter: parent.verticalCenter 39 anchors.verticalCenter: parent.verticalCenter
44 spacing: 8 40 spacing: 8
45 41
46 Row { 42 WorkspaceSwitcher {}
47 id: workspaces
48
49 property var ignoreWorkspaces: @ignore_workspaces@
50
51 height: parent.height
52 anchors.verticalCenter: parent.verticalCenter
53 spacing: 0
54
55 Repeater {
56 model: {
57 let currWorkspaces = NiriService.workspaces;
58 const ignoreWorkspaces = Array.from(workspaces.ignoreWorkspaces);
59 currWorkspaces = currWorkspaces.filter(ws => ws.is_active || ignoreWorkspaces.every(iws => iws !== ws.name));
60 currWorkspaces.sort((a, b) => {
61 if (NiriService.outputs?.[a.output]?.logical?.x !== NiriService.outputs?.[b.output]?.logical?.x)
62 return NiriService.outputs?.[a.output]?.logical?.x - NiriService.outputs?.[b.output]?.logical?.x
63 if (NiriService.outputs?.[a.output]?.logical?.y !== NiriService.outputs?.[b.output]?.logical?.y)
64 return NiriService.outputs?.[a.output]?.logical?.y - NiriService.outputs?.[b.output]?.logical?.y
65 return a.idx - b.idx;
66 });
67 return currWorkspaces;
68 }
69
70 Rectangle {
71 property var workspaceData: modelData
72
73 width: wsLabel.contentWidth + 8
74 color: {
75 if (mouseArea.containsMouse) {
76 return "#33808080";
77 }
78 return "transparent";
79 }
80 height: parent.height
81 anchors.verticalCenter: parent.verticalCenter
82
83 MouseArea {
84 id: mouseArea
85
86 anchors.fill: parent
87 hoverEnabled: true
88 cursorShape: Qt.PointingHandCursor
89 enabled: true
90 onClicked: {
91 NiriService.sendCommand({ "Action": { "FocusWorkspace": { "reference": { "Id": workspaceData.id } } } }, _ => {})
92 }
93 }
94
95 Text {
96 id: wsLabel
97
98 font.pointSize: 10
99 font.family: "Fira Sans"
100 color: {
101 if (workspaceData.is_active)
102 return "#23fd00";
103 if (workspaceData.active_window_id === null)
104 return "#555";
105 return "white";
106 }
107 anchors.centerIn: parent
108
109 text: workspaceData.name ? workspaceData.name : workspaceData.idx
110 }
111 }
112 }
113 }
114 } 43 }
115 44
116 Row { 45 Row {
@@ -121,91 +50,9 @@ PanelWindow {
121 anchors.centerIn: parent 50 anchors.centerIn: parent
122 spacing: 5 51 spacing: 5
123 52
124 Item { 53 ActiveWindowDisplay {
125 id: activeWindowDisplay 54 screen: bar.screen
126 55 maxWidth: bar.width - 2*Math.max(left.width, right.width) - 2*8
127 property var activeWindow: {
128 let currWindowId = Array.from(NiriService.workspaces).find(ws => {
129 return ws.output === bar.screen.name && ws.is_active;
130 })?.active_window_id;
131
132 return currWindowId ? Array.from(NiriService.windows).find(win => win.id == currWindowId) : null;
133 }
134 property var windowEntry: activeWindow ? DesktopEntries.heuristicLookup(activeWindow.app_id) : null
135
136 anchors.verticalCenter: parent.verticalCenter
137 width: activeWindowDisplayContent.width
138 height: parent.height
139
140 Row {
141 id: activeWindowDisplayContent
142
143 width: childrenRect.width
144 height: parent.height
145 anchors.verticalCenter: parent.verticalCenter
146 spacing: 8
147
148 IconImage {
149 id: activeWindowIcon
150
151 height: 14
152 width: 14
153
154 anchors.verticalCenter: parent.verticalCenter
155
156 source: {
157 let icon = activeWindowDisplay.windowEntry?.icon
158 if (typeof icon === 'string' || icon instanceof String) {
159 if (icon.includes("?path=")) {
160 const split = icon.split("?path=")
161 if (split.length !== 2)
162 return icon
163 const name = split[0]
164 const path = split[1]
165 const fileName = name.substring(
166 name.lastIndexOf("/") + 1)
167 return `file://${path}/${fileName}`
168 } else
169 icon = Quickshell.iconPath(icon);
170 return icon
171 }
172 return ""
173 }
174 asynchronous: true
175 smooth: true
176 mipmap: true
177 }
178
179 Text {
180 id: windowTitle
181
182 width: Math.min(implicitWidth, bar.width - 2*Math.max(left.width, right.width) - 2*8 - activeWindowIcon.width - activeWindowDisplayContent.spacing)
183
184 property var appAliases: { "Firefox": "Mozilla Firefox", "mpv Media Player": "mpv", "Thunderbird": "Mozilla Thunderbird", "Thunderbird (LMU)": "Mozilla Thunderbird" }
185
186 elide: Text.ElideRight
187 maximumLineCount: 1
188 color: "white"
189 anchors.verticalCenter: parent.verticalCenter
190 text: {
191 if (!activeWindowDisplay.activeWindow)
192 return "";
193
194 var title = activeWindowDisplay.activeWindow.title;
195 var appName = activeWindowDisplay.windowEntry?.name;
196 if (appAliases[appName])
197 appName = appAliases[appName];
198 if (appName && title.endsWith(appName)) {
199 const oldTitle = title;
200 title = title.substring(0, title.length - appName.length);
201 title = title.replace(/\s*(—|-)\s*$/, "");
202 if (!title)
203 title = oldTitle;
204 }
205 return title;
206 }
207 }
208 }
209 } 56 }
210 } 57 }
211 58
@@ -219,170 +66,22 @@ PanelWindow {
219 anchors.verticalCenter: parent.verticalCenter 66 anchors.verticalCenter: parent.verticalCenter
220 spacing: 0 67 spacing: 0
221 68
222 Item { 69 SystemTray {}
223 anchors.verticalCenter: parent.verticalCenter
224 width: systemTrayRow.childrenRect.width
225 height: parent.height
226 clip: true
227
228 Row {
229 id: systemTrayRow
230 anchors.centerIn: parent
231 width: childrenRect.width
232 height: parent.height
233 spacing: 0
234
235 Repeater {
236 model: SystemTray.items.values
237
238 delegate: Item {
239 property var trayItem: modelData
240 property string iconSource: {
241 let icon = trayItem && trayItem.icon
242 if (typeof icon === 'string' || icon instanceof String) {
243 if (icon.includes("?path=")) {
244 const split = icon.split("?path=")
245 if (split.length !== 2)
246 return icon
247 const name = split[0]
248 const path = split[1]
249 const fileName = name.substring(
250 name.lastIndexOf("/") + 1)
251 return `file://${path}/${fileName}`
252 }
253 return icon
254 }
255 return ""
256 }
257
258 width: 16
259 height: parent.height
260 anchors.verticalCenter: parent.verticalCenter
261 70
262 IconImage { 71 Item {
263 anchors.centerIn: parent
264 width: parent.width
265 height: parent.width
266 source: parent.iconSource
267 asynchronous: true
268 smooth: true
269 mipmap: true
270 }
271
272 MouseArea {
273 id: trayItemArea
274
275 anchors.fill: parent
276 acceptedButtons: Qt.LeftButton | Qt.RightButton
277 hoverEnabled: true
278 cursorShape: Qt.PointingHandCursor
279 onClicked: mouse => {
280 if (!trayItem)
281 return
282
283 if (mouse.button === Qt.LeftButton
284 && !trayItem.onlyMenu) {
285 trayItem.activate()
286 return
287 }
288
289 if (trayItem.hasMenu) {
290 var globalPos = mapToGlobal(0, 0)
291 var currentScreen = screen || Screen
292 var screenX = currentScreen.x || 0
293 var relativeX = globalPos.x - screenX
294 menuAnchor.menu = trayItem.menu
295 menuAnchor.anchor.window = bar
296 menuAnchor.anchor.rect = Qt.rect(
297 relativeX,
298 21,
299 parent.width, 1)
300 menuAnchor.open()
301 }
302 }
303 }
304 }
305 }
306 }
307 QsMenuAnchor {
308 id: menuAnchor
309 }
310 }
311
312 Rectangle {
313 height: parent.height 72 height: parent.height
314 width: 4 73 width: 4
315 color: "transparent"
316 } 74 }
317 75
318 Rectangle { 76 KeyboardLayout {}
319 id: kbdWidget
320 77
321 property var keyboardAbbrev: { "English (programmer Dvorak)": "dvp", "English (US)": "us" } 78 Item {
322
323 width: kbdLabel.contentWidth + 8
324 color: {
325 if (kbdMouseArea.containsMouse) {
326 return "#33808080";
327 }
328 return "transparent";
329 }
330 height: parent.height
331 anchors.verticalCenter: parent.verticalCenter
332
333 MouseArea {
334 id: kbdMouseArea
335
336 anchors.fill: parent
337 hoverEnabled: true
338 cursorShape: Qt.PointingHandCursor
339 enabled: true
340 onClicked: {
341 NiriService.sendCommand({ "Action": { "SwitchLayout": { "layout": "Next" } } }, _ => {})
342 }
343 }
344
345 Text {
346 id: kbdLabel
347
348 font.pointSize: 10
349 font.family: "Fira Sans"
350 color: {
351 if (NiriService.keyboardLayouts?.current_idx === 0)
352 return "#555";
353 return "white";
354 }
355 anchors.centerIn: parent
356
357 text: {
358 const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx];
359 return kbdWidget.keyboardAbbrev[currentLayout] ? kbdWidget.keyboardAbbrev[currentLayout] : currentLayout;
360 }
361 }
362 }
363
364 Rectangle {
365 height: parent.height 79 height: parent.height
366 width: 4 80 width: 4
367 color: "transparent"
368 } 81 }
369 82
370 Text { 83 Clock {
371 id: clock 84 id: clock
372 color: "white"
373
374 anchors.verticalCenter: parent.verticalCenter
375
376 Custom.Chrono {
377 id: chrono
378 format: "W{0:%V-%u} {0:%F} {0:%H:%M:%S%Ez}"
379 }
380
381 text: chrono.date
382
383 font.pointSize: 10
384 font.family: "Fira Sans"
385 font.features: { "tnum": 1 }
386 } 85 }
387 } 86 }
388} \ No newline at end of file 87} \ No newline at end of file