me like nix
0

Configure Feed

Select the types of activity you want to include in your feed.

1import Quickshell 2import Quickshell.Wayland 3import Quickshell.Io 4import QtQuick 5import QtQuick.Layouts 6 7ShellRoot { 8 PanelWindow { 9 id: root 10 11 // Catppuccin Frappe palette 12 readonly property color colBase: "#303446" 13 readonly property color colMantle: "#292c3c" 14 readonly property color colSurface0: "#414559" 15 readonly property color colText: "#c6d0f5" 16 readonly property color colSubtext0: "#a5adce" 17 readonly property color colOverlay0: "#737994" 18 readonly property color colBlue: "#8caaee" 19 readonly property color colGreen: "#a6d189" 20 readonly property color colPeach: "#ef9f76" 21 readonly property color colMauve: "#ca9ee6" 22 readonly property color colRed: "#e78284" 23 readonly property color colYellow: "#e5c890" 24 readonly property color colMaroon: "#ea999c" 25 readonly property color colLavender: "#babbf1" 26 readonly property color colSky: "#99d1db" 27 readonly property color colSapphire: "#85c1dc" 28 29 readonly property string fontFamily: "BerkeleyMono Nerd Font" 30 readonly property int fontSize: 14 31 32 // Nerd Font icons (using Unicode escapes) 33 // Volume 34 readonly property string iconVolHigh: "\uf028" 35 readonly property string iconVolLow: "\uf027" 36 readonly property string iconVolMute: "\uf6a9" 37 // Network 38 readonly property string iconWifi: "\uf1eb" 39 // Power profiles 40 readonly property string iconBolt: "\uf0e7" 41 readonly property string iconBalance: "\uf24e" 42 readonly property string iconLeaf: "\uf06c" 43 // CPU 44 readonly property string iconCpu: "\uf2db" 45 // Memory 46 readonly property string iconMem: "\uefc5" 47 // Temperature 48 readonly property string iconTempLow: "\uf2cb" 49 readonly property string iconTempMed: "\uf2c9" 50 readonly property string iconTempHigh: "\uf2c7" 51 // Backlight 52 readonly property string iconSun: "\uf185" 53 // Battery 54 readonly property string iconBatEmpty: "\uf244" 55 readonly property string iconBatQuarter: "\uf243" 56 readonly property string iconBatHalf: "\uf242" 57 readonly property string iconBatThreeQ: "\uf241" 58 readonly property string iconBatFull: "\uf240" 59 readonly property string iconBatCharge: "\uf0e7" 60 // Power 61 readonly property string iconPower: "\u23fb" 62 63 // System data 64 property int cpuUsage: 0 65 property int memUsage: 0 66 property int temperature: 0 67 property var lastCpuIdle: 0 68 property var lastCpuTotal: 0 69 property string networkName: "" 70 property int networkStrength: 0 71 property bool networkConnected: false 72 property int volume: 0 73 property bool volumeMuted: false 74 property int brightness: 0 75 property int batteryPercent: 0 76 property string batteryStatus: "" 77 property string powerProfile: "" 78 79 anchors { 80 top: true 81 left: true 82 right: true 83 } 84 margins.top: 0 85 margins.bottom: 0 86 margins.left: 0 87 margins.right: 0 88 implicitHeight: 30 89 color: Qt.rgba(0.188, 0.204, 0.275, 0.85) 90 91 // CPU process 92 Process { 93 id: cpuProc 94 command: ["sh", "-c", "head -1 /proc/stat"] 95 stdout: SplitParser { 96 onRead: data => { 97 if (!data) return 98 var p = data.trim().split(/\s+/) 99 var idle = parseInt(p[4]) + parseInt(p[5]) 100 var total = p.slice(1, 8).reduce((a, b) => a + parseInt(b), 0) 101 if (root.lastCpuTotal > 0) { 102 root.cpuUsage = Math.round(100 * (1 - (idle - root.lastCpuIdle) / (total - root.lastCpuTotal))) 103 } 104 root.lastCpuTotal = total 105 root.lastCpuIdle = idle 106 } 107 } 108 Component.onCompleted: running = true 109 } 110 111 // Memory process 112 Process { 113 id: memProc 114 command: ["sh", "-c", "free | grep Mem"] 115 stdout: SplitParser { 116 onRead: data => { 117 if (!data) return 118 var parts = data.trim().split(/\s+/) 119 var total = parseInt(parts[1]) || 1 120 var used = parseInt(parts[2]) || 0 121 root.memUsage = Math.round(100 * used / total) 122 } 123 } 124 Component.onCompleted: running = true 125 } 126 127 // Temperature 128 Process { 129 id: tempProc 130 command: ["sh", "-c", "cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null || echo 0"] 131 stdout: SplitParser { 132 onRead: data => { 133 if (!data) return 134 root.temperature = Math.round(parseInt(data.trim()) / 1000) 135 } 136 } 137 Component.onCompleted: running = true 138 } 139 140 // Network 141 Process { 142 id: netProc 143 command: ["sh", "-c", "nmcli -t -f ACTIVE,SSID,SIGNAL dev wifi | grep '^yes' | head -1"] 144 stdout: SplitParser { 145 onRead: data => { 146 if (!data || data.trim() === "") { 147 root.networkConnected = false 148 root.networkName = "Disconnected" 149 root.networkStrength = 0 150 return 151 } 152 var parts = data.trim().split(":") 153 root.networkConnected = true 154 root.networkName = parts[1] || "" 155 root.networkStrength = parseInt(parts[2]) || 0 156 } 157 } 158 Component.onCompleted: running = true 159 } 160 161 // Volume 162 Process { 163 id: volProc 164 command: ["sh", "-c", "wpctl get-volume @DEFAULT_AUDIO_SINK@"] 165 stdout: SplitParser { 166 onRead: data => { 167 if (!data) return 168 root.volumeMuted = data.indexOf("[MUTED]") !== -1 169 var match = data.match(/Volume:\s+([\d.]+)/) 170 if (match) { 171 root.volume = Math.round(parseFloat(match[1]) * 100) 172 } 173 } 174 } 175 Component.onCompleted: running = true 176 } 177 178 // Brightness 179 Process { 180 id: brightProc 181 command: ["sh", "-c", "brightnessctl -m | cut -d, -f4 | tr -d '%'"] 182 stdout: SplitParser { 183 onRead: data => { 184 if (!data) return 185 root.brightness = parseInt(data.trim()) || 0 186 } 187 } 188 Component.onCompleted: running = true 189 } 190 191 // Battery 192 Process { 193 id: batProc 194 command: ["sh", "-c", "cat /sys/class/power_supply/BAT1/capacity 2>/dev/null || echo 0"] 195 stdout: SplitParser { 196 onRead: data => { 197 if (!data) return 198 root.batteryPercent = parseInt(data.trim()) || 0 199 } 200 } 201 Component.onCompleted: running = true 202 } 203 204 Process { 205 id: batStatusProc 206 command: ["sh", "-c", "cat /sys/class/power_supply/BAT1/status 2>/dev/null || echo Unknown"] 207 stdout: SplitParser { 208 onRead: data => { 209 if (!data) return 210 root.batteryStatus = data.trim() 211 } 212 } 213 Component.onCompleted: running = true 214 } 215 216 // Power profile 217 Process { 218 id: powerProc 219 command: ["sh", "-c", "powerprofilesctl get 2>/dev/null || echo unknown"] 220 stdout: SplitParser { 221 onRead: data => { 222 if (!data) return 223 root.powerProfile = data.trim() 224 } 225 } 226 Component.onCompleted: running = true 227 } 228 229 // Update timer 230 Timer { 231 interval: 2000 232 running: true 233 repeat: true 234 onTriggered: { 235 cpuProc.running = true 236 memProc.running = true 237 tempProc.running = true 238 netProc.running = true 239 volProc.running = true 240 brightProc.running = true 241 batProc.running = true 242 batStatusProc.running = true 243 powerProc.running = true 244 } 245 } 246 247 RowLayout { 248 anchors.fill: parent 249 anchors.leftMargin: 12 250 anchors.rightMargin: 12 251 spacing: 0 252 253 // Clock 254 Text { 255 id: clockText 256 color: root.colBlue 257 font { family: root.fontFamily; pixelSize: root.fontSize } 258 text: Qt.formatDateTime(new Date(), "dd-MM-yyyy HH:mm") 259 Timer { 260 interval: 1000 261 running: true 262 repeat: true 263 onTriggered: clockText.text = Qt.formatDateTime(new Date(), "dd-MM-yyyy HH:mm") 264 } 265 } 266 267 Item { Layout.fillWidth: true } 268 269 // Right section 270 RowLayout { 271 spacing: 12 272 273 // Volume 274 Text { 275 color: root.colMaroon 276 font { family: root.fontFamily; pixelSize: root.fontSize } 277 text: root.volume + "% " + (root.volumeMuted ? root.iconVolMute : (root.volume > 50 ? root.iconVolHigh : root.iconVolLow)) 278 MouseArea { 279 anchors.fill: parent 280 cursorShape: Qt.PointingHandCursor 281 onClicked: volClickProc.running = true 282 } 283 } 284 285 Process { 286 id: volClickProc 287 command: ["pavucontrol"] 288 } 289 290 Rectangle { width: 1; height: 16; color: root.colOverlay0 } 291 292 // Network 293 Text { 294 color: root.colGreen 295 font { family: root.fontFamily; pixelSize: root.fontSize } 296 text: root.networkConnected ? root.networkName + " (" + root.networkStrength + "%) " + root.iconWifi : "Disconnected \u26a0" 297 } 298 299 Rectangle { width: 1; height: 16; color: root.colOverlay0 } 300 301 // Power Profile 302 Text { 303 color: root.colText 304 font { family: root.fontFamily; pixelSize: root.fontSize } 305 text: { 306 if (root.powerProfile === "performance") return root.iconBolt 307 if (root.powerProfile === "balanced") return root.iconBalance 308 if (root.powerProfile === "power-saver") return root.iconLeaf 309 return root.iconBalance 310 } 311 } 312 313 Rectangle { width: 1; height: 16; color: root.colOverlay0 } 314 315 // CPU 316 Text { 317 color: root.colPeach 318 font { family: root.fontFamily; pixelSize: root.fontSize } 319 text: root.cpuUsage + "% " + root.iconCpu 320 } 321 322 Rectangle { width: 1; height: 16; color: root.colOverlay0 } 323 324 // Memory 325 Text { 326 color: root.colMauve 327 font { family: root.fontFamily; pixelSize: root.fontSize } 328 text: root.memUsage + "% " + root.iconMem 329 } 330 331 Rectangle { width: 1; height: 16; color: root.colOverlay0 } 332 333 // Temperature 334 Text { 335 color: root.colRed 336 font { family: root.fontFamily; pixelSize: root.fontSize } 337 text: { 338 var icon = root.temperature >= 80 ? root.iconTempHigh : (root.temperature >= 50 ? root.iconTempMed : root.iconTempLow) 339 return root.temperature + "\u00b0C " + icon 340 } 341 } 342 343 Rectangle { width: 1; height: 16; color: root.colOverlay0 } 344 345 // Backlight 346 Text { 347 color: root.colYellow 348 font { family: root.fontFamily; pixelSize: root.fontSize } 349 text: root.brightness + "% " + root.iconSun 350 } 351 352 Rectangle { width: 1; height: 16; color: root.colOverlay0 } 353 354 // Battery 355 Text { 356 color: { 357 if (root.batteryStatus === "Charging") return root.colGreen 358 if (root.batteryPercent <= 15) return root.colRed 359 if (root.batteryPercent <= 30) return root.colRed 360 return root.colGreen 361 } 362 font { family: root.fontFamily; pixelSize: root.fontSize } 363 text: { 364 var icon 365 if (root.batteryStatus === "Charging") { 366 icon = root.iconBatCharge 367 } else { 368 var icons = [root.iconBatEmpty, root.iconBatQuarter, root.iconBatHalf, root.iconBatThreeQ, root.iconBatFull] 369 var idx = Math.min(Math.floor(root.batteryPercent / 25), 4) 370 icon = icons[idx] 371 } 372 return root.batteryPercent + "% " + icon 373 } 374 } 375 376 Rectangle { width: 1; height: 16; color: root.colOverlay0 } 377 378 // Power button 379 Text { 380 color: root.colRed 381 font { family: root.fontFamily; pixelSize: root.fontSize } 382 text: root.iconPower 383 } 384 } 385 } 386 } 387}