diff options
Diffstat (limited to 'quickshell')
| -rw-r--r-- | quickshell/mpd/shell.qml | 22 | ||||
| -rw-r--r-- | quickshell/mpd/shell.qml.bak | 470 | ||||
| -rw-r--r-- | quickshell/shell.qml | 33 | ||||
| -rw-r--r-- | quickshell/shell.qml.bak | 488 |
4 files changed, 985 insertions, 28 deletions
diff --git a/quickshell/mpd/shell.qml b/quickshell/mpd/shell.qml index 04a74b8..d45f127 100644 --- a/quickshell/mpd/shell.qml +++ b/quickshell/mpd/shell.qml @@ -3,15 +3,15 @@ import Quickshell.Io import QtQuick import QtQuick.Layouts ShellRoot { - property color colBg: "#000000" - property color colFg: "#ffffff" - property color colMuted: "#313244" - property color colCyan: "#89dceb" - property color colPurple: "#cba6f7" - property color colRed: "#f38ba8" - property color colYellow: "#f9e2af" - property color colBlue: "#89b4fa" - property color colGreen: "#A3BE8C" + property color colBg: "#1d2021" // Gruvbox Background (Hard) + property color colFg: "#ebdbb2" // Gruvbox Foreground + property color colMuted: "#928374" // Gruvbox Gray (Muted) + property color colCyan: "#8ec07c" // Gruvbox Aqua/Cyan + property color colPurple: "#d3869b" // Gruvbox Purple + property color colRed: "#fb4934" // Gruvbox Red (Bright) + property color colYellow: "#fabd2f" // Gruvbox Yellow (Bright) + property color colBlue: "#83a598" // Gruvbox Blue + property color colGreen: "#b8bb26" // Gruvbox Green property string fontFamily: "Iosevka NerdFont Propo" property int fontSize: 16 property string mpd_title: "" @@ -286,7 +286,7 @@ ShellRoot { width: parent.width * mpd_progress height: parent.height radius: 2 - color: isPlaying ? colCyan : colYellow + color: isPlaying ? colRed : colYellow Behavior on width { enabled: !isSeeking NumberAnimation { duration: 950; easing.type: Easing.Linear } @@ -506,7 +506,7 @@ ShellRoot { id: progressFill width: progressTrack.width * mpd_progress height: parent.height; radius: 2 - color: isPlaying ? colCyan : colYellow + color: isPlaying ? colRed : colYellow Behavior on width { enabled: !isSeeking NumberAnimation { duration: 950; easing.type: Easing.Linear } diff --git a/quickshell/mpd/shell.qml.bak b/quickshell/mpd/shell.qml.bak new file mode 100644 index 0000000..be04cf0 --- /dev/null +++ b/quickshell/mpd/shell.qml.bak @@ -0,0 +1,470 @@ +import Quickshell +import Quickshell.Io +import QtQuick +import QtQuick.Layouts +ShellRoot { + + property color colBg: "#000000" + property color colFg: "#ffffff" + property color colMuted: "#313244" + property color colCyan: "#89dceb" + property color colPurple: "#cba6f7" + property color colRed: "#f38ba8" + property color colYellow: "#f9e2af" + property color colBlue: "#89b4fa" + property color colGreen: "#A3BE8C" + property string fontFamily: "Iosevka Nerd Font Propo" + property int fontSize: 16 + + + property string mpd_title: "" + property string mpd_artist: "" + property string mpd_elapsed: "0:00" + property string mpd_duration: "0:00" + property string mpd_file: "" + property real mpd_progress: 0.0 + property bool isPlaying: false + property bool isPaused: false + property bool isActive: isPlaying || isPaused + property bool isSeeking: false + property bool cardVisible: false + property string artPath: "/tmp/mpdrop_art.png" + property string artCache: "" + + function timeToSecs(t) { + var p = t.split(":") + if (p.length === 2) return parseInt(p[0]) * 60 + parseInt(p[1]) + if (p.length === 3) return parseInt(p[0]) * 3600 + parseInt(p[1]) * 60 + parseInt(p[2]) + return 0 + } + + // Art Extractor + + Process { + id: artProc + property string filePath: "" + command: ["sh", "-c", "ffmpeg -i \"" + Qt.musicFolder + filePath + "\" -an -vcodec copy /tm/mdrop_art.png -y 2>/dev/null"] + running: false + onExited: { + artCache = "" + artCache = artPath + } + } + + // File Path Folder + Process { + id: fileProc + command: ["mpc", "--format", "%file%", "current"] + stdout: StdioCollector { + onStreamFinished: { + var f = this.text.trim() + if (f !== "" && f !== mpd_file) { + mpd_file = f + artProc.filePath = f + artProc.running = false + artProc.running = true + } + } + } + } + + // Idle Watcher + + Process { + id: idleProc + command: ["mpc", "idlewait"] + running: true + onExited: { + statusProc.running = true + } + } + + // Status Fetcher + Process { + id: statusProc + command: ["mpc", "status", "--format", "%title%||%artist||%duration%"] + stdout: StdioCollector { + onStreamFinished: { + var lines = this.text.trim().split("\n") + if (lines.length >= 2) { + var meta = lines[0].split("||") + var newTitle = meta[0] || "Unknown" + + if (newTitle !== mpd_title) fileProc.running = true + + mpd_title = newTitle + mpd_artist = meta[1] || "" + mpd_duration = meta[2] || "0:00" + + var sl = lines[1] + isPlaying = sl.indexOf("[playing]") !== -1 + isPaused = sl.indexOf("[paused]") !== -1 + + var tm = sl.match(/(\d+:\d+)\/(\d+:\d+)/) + if (tm) { + mpd_elapsed = tm[1] + var total = timeToSecs(tm[2]) + if (!isSeeking) { + mpd_progress = total > 0 ? timeToSecs(tm[1]) / total : 0 + } + + + } + else { + mpd_title = ""; mpd_artist = "" + mpd_elapsed = "0:00"; mpd_duration = "0:00" + mpd_progress = 0; isPlaying = false; isPaused = false + } + } + } + } + onExited: idleProc.running = true +} + property real progressPerSecond: { + var total = timeToSecs(mpd_duration) + return total > 0 ? 1.0 / total : 0 + } + + Timer { + id: progressTimer + interval: 1000 + running: isPlaying && !isSeeking + repeat: true + onTriggered: { + mpd_progress = Math.min(1.0, mpd_progress + progressPerSecond) + var elapsed = Math.round(mpd_progress * timeToSecs(mpd_duration)) + var m = Math.floor(elapsed / 60) + var s = elapsed % 60 + mpd_elapsed = m + ":" + (s < 10 ? "0" + s : s) + } + } + + + Timer { + id: seekResetTimer + interval: 1100 + repeat: false + onTriggered: isSeeking = false + } + + // Control process + Process { + id: ctrlProc + property var args: ["toggle"] + command: ["mpc"].concat(args) + running: false + onExited: statusProc.running = true + } + + // Hover Card + PanelWindow { + visible: cardVisible && isActive + screen: Quickshell.screens[0] + exclusionMode: ExclusionMode.Ignore + anchors { bottom: true; left: true } + implicitWidth: 280 + implicitHeight: 320 + color: "transparent" + + Rectangle { + anchors.fill: parent + anchors.margin: 12 + radius: 12 + color: colBg + border.color: colMuted + border.width: 1 + + opacity: cardVisible ? 1 : 0 + Behavior on opacity { NumberAnimation { duration: 200 } } + + Column { + anchors.fill: parent + anchors.margin: 12 + spacing: 10 + + // Album Art + Rectangle { + width: parent.width + height: parent.width + radius: 8 + color: colMuted + clip: true + + + Image { + id: artImage + anchors.fill: parent + source: artCache !== "" ? "file://" + artCache : "" + fillMode: Image.PreserveAspectCrop + cache: false + smooth: true + + //Placeholder for when no art + Text { + anchors.centerIn: parent + text: "๐ผ" + font.pixelSize: 48 + font.family: fontFamily + color: colMuted + visible: artImage.status !== Image.Ready + } + } + } + + // Title + Text { + text: mpd_title + color: colFg + font.pixelSize: 13 + font.family: fontFamily + font.bold: true + elide: Text.ElideRight + width: parent.width + } + + // Artist + Text { + text: mpd_artist + color: colMuted + font.pixelSize: 12 + font.family: fontFamily + elide: Text.ElideRight + width: parent.width + visible: mpd_artist !== "" + } + + // Progress Bar + Rectangle { + width: parent.width + height: 3 + radius: 2 + color: colMuted + + Rectangle: { + width: parent.width * mpd_progress + height: parent.height + radius: 2 + color: isPlaying ? colCyan : colYellow + Behavior on width { + enabled: !isSeeking + NumberAnimation { duration: 950; easing.type: Easing.Linear } + } + + } + } + + // Time + RowLayout { + width: parent.width + Text { + text: mpd_elapsed + color: colFg + font.pixelSize: 11 + font.family: fontFamily + } + Item { Layout.fillWidth: true } + Text { + text: mpd_duration + color: colMuted + font.pixelSize: 11 + font.family: fontFamily + } + + } + } + } + } + + // โโ The bar โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + PanelWindow { + id: mainBar + visible: isActive + screen: Quickshell.screens[0] + exclusionMode: PanelWindow + anchors { bottom: true; left: true; right: true } + implicitHeight: 36 + color: colBg + + // hover Detection + HoverHandler { + id: barHover + onHoveredChanged: cardVisible = barHover.hovered + } + + + + Rectangle { + anchors.fill: parent + color: colBg + Rectangle { + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: colMuted + } + RowLayout { + anchors.fill: parent + anchors.leftMargin: 8 + anchors.rightMargin: 8 + spacing: 0 + // โโ Music icon โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + Text { + text: isPaused ? "๓ฐ" : "๓ฐ" + color: isPaused ? colYellow : colCyan + font.pixelSize: fontSize + font.family: fontFamily + font.bold: true + Behavior on color { ColorAnimation { duration: 200 } } + } + Item { width: 8 } + // โโ Title โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + Text { + text: mpd_title || "Unknown" + color: colPurple + font.pixelSize: fontSize + font.family: fontFamily + font.bold: true + elide: Text.ElideRight + Layout.maximumWidth: 220 + } + // โโ Separator + Artist โโโโโโโโโโโโโโโโโโโโโโโโโ + Rectangle { + Layout.preferredWidth: 1; Layout.preferredHeight: 16 + Layout.leftMargin: 8; Layout.rightMargin: 8 + color: colMuted + visible: mpd_artist !== "" + } + Text { + text: mpd_artist + color: colCyan + font.pixelSize: fontSize + font.family: fontFamily + font.bold: true + elide: Text.ElideRight + Layout.maximumWidth: 180 + visible: mpd_artist !== "" + } + // โโ Separator โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + Rectangle { + Layout.preferredWidth: 1; Layout.preferredHeight: 16 + Layout.leftMargin: 8; Layout.rightMargin: 8 + color: colMuted + } + // โโ Prev โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + Text { + text: "๓ฐฎ" + color: prevH.containsMouse ? colCyan : colFg + font.pixelSize: fontSize + font.family: fontFamily + font.bold: true + Layout.rightMargin: 10 + HoverHandler { id: prevH } + TapHandler { onTapped: { if (!ctrlProc.running) { ctrlProc.args = ["prev"]; ctrlProc.running = true } } } + Behavior on color { ColorAnimation { duration: 100 } } + } + // โโ Play / Pause โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + Text { + text: isPlaying ? "๓ฐค" : "๓ฐ" + color: playH.containsMouse ? colPurple : colCyan + font.pixelSize: fontSize + 2 + font.family: fontFamily + font.bold: true + Layout.rightMargin: 10 + HoverHandler { id: playH } + TapHandler { onTapped: { if (!ctrlProc.running) { ctrlProc.args = ["toggle"]; ctrlProc.running = true } } } + Behavior on color { ColorAnimation { duration: 100 } } + } + // โโ Next โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + Text { + text: "๓ฐญ" + color: nextH.containsMouse ? colCyan : colFg + font.pixelSize: fontSize + font.family: fontFamily + font.bold: true + Layout.rightMargin: 10 + HoverHandler { id: nextH } + TapHandler { onTapped: { if (!ctrlProc.running) { ctrlProc.args = ["next"]; ctrlProc.running = true } } } + Behavior on color { ColorAnimation { duration: 100 } } + } + // โโ Stop โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + Text { + text: "๓ฐ" + color: stopH.containsMouse ? colRed : colMuted + font.pixelSize: fontSize + font.family: fontFamily + font.bold: true + HoverHandler { id: stopH } + TapHandler { onTapped: { if (!ctrlProc.running) { ctrlProc.args = ["stop"]; ctrlProc.running = true } } } + Behavior on color { ColorAnimation { duration: 100 } } + } + // โโ Separator โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + Rectangle { + Layout.preferredWidth: 1; Layout.preferredHeight: 16 + Layout.leftMargin: 8; Layout.rightMargin: 8 + color: colMuted + } + // โโ Elapsed โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + Text { + text: mpd_elapsed + color: colFg + font.pixelSize: fontSize + font.family: fontFamily + font.bold: true + Layout.rightMargin: 8 + } + // โโ Progress bar โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + Rectangle { + id: progressTrack + Layout.fillWidth: true + height: 4 + radius: 2 + color: colMuted + + // Fill + Rectangle { + id: progressFill + width: progressTrack.width * mpd_progress + height: parent.height + radius: 2 + color: isPlaying ? colCyan : colYellow + Behavior on width { + enabled: !isSeeking + NumberAnimation { duration: 950; easing.type: Easing.Linear } + } + Behavior on color { ColorAnimation { duration: 300 } } + } + + // Seek โ child of progressTrack so parent.width works + MouseArea { + anchors.fill: parent + anchors.topMargin: -6 + anchors.bottomMargin: -6 + cursorShape: Qt.PointingHandCursor + onClicked: (mouse) => { + if (!ctrlProc.running) { + var pct = Math.max(0, Math.min(1, mouse.x / progressTrack.width)) + var pctInt = Math.round(pct * 100) + isSeeking = true + mpd_progress = pct + ctrlProc.args = ["seek", pctInt + "%"] + ctrlProc.running = true + seekResetTimer.restart() + } + } + } + } + // โโ Duration โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ + Text { + text: mpd_duration + color: colMuted + font.pixelSize: fontSize + font.family: fontFamily + font.bold: true + Layout.leftMargin: 8 + } + Item { width: 8 } + } + } + } +} diff --git a/quickshell/shell.qml b/quickshell/shell.qml index 313827c..c2b76a0 100644 --- a/quickshell/shell.qml +++ b/quickshell/shell.qml @@ -8,18 +8,18 @@ import QtQuick.Layouts ShellRoot { id: root - // --- BLACKOUT THEME COLORS --- - property color colBg: "#000000" // True Black to match Ghostty - property color colFg: "#ffffff" // Pure White to match Oh-My-Posh - property color colMuted: "#313244" // Dark Grey (Surface1) - property color colCyan: "#89dceb" // Catppuccin Sky - property color colPurple: "#cba6f7" // Catppuccin Mauve - property color colRed: "#f38ba8" // Catppuccin Red - property color colYellow: "#f9e2af" // Catppuccin Yellow - property color colBlue: "#89b4fa" // Catppuccin Blue - property color colGreen: "#A3BE8C" + property color colBg: "#1d2021" // Gruvbox Background (Hard) + property color colFg: "#ebdbb2" // Gruvbox Foreground + property color colMuted: "#928374" // Gruvbox Gray (Muted) + property color colCyan: "#8ec07c" // Gruvbox Aqua/Cyan + property color colPurple: "#d3869b" // Gruvbox Purple + property color colRed: "#fb4934" // Gruvbox Red (Bright) + property color colYellow: "#fabd2f" // Gruvbox Yellow (Bright) + property color colBlue: "#83a598" // Gruvbox Blue + property color colGreen: "#b8bb26" // Gruvbox Green // Font - property string fontFamily: "Iosevka Nerd Font Propo" + + property string fontFamily: "Iosevka Nerdfont Propo" property int fontSize: 16 // System info properties @@ -35,12 +35,11 @@ ShellRoot { property int cpuTempInt: parseInt(cpuTemp, 10) property string upTime: "0" - property color tempColor: { - if (cpuTempInt < 50 ) return "#a6e3a1" // Green - else if (cpuTempInt < 70) return "#f9e2af" // Yellow - else return "#f38ba8" // Red - } - + property color tempColor: { + if (cpuTempInt < 50 ) return "#b8bb26" // Gruvbox Green + else if (cpuTempInt < 70) return "#fabd2f" // Gruvbox Yellow + else return "#fb4934" // Gruvbox Red + } property int notificationCount: 0 property var lastCpuIdle: 0 diff --git a/quickshell/shell.qml.bak b/quickshell/shell.qml.bak new file mode 100644 index 0000000..313827c --- /dev/null +++ b/quickshell/shell.qml.bak @@ -0,0 +1,488 @@ +import Quickshell +import Quickshell.Wayland +import Quickshell.Io +import Quickshell.Hyprland +import QtQuick +import QtQuick.Layouts + +ShellRoot { + id: root + + // --- BLACKOUT THEME COLORS --- + property color colBg: "#000000" // True Black to match Ghostty + property color colFg: "#ffffff" // Pure White to match Oh-My-Posh + property color colMuted: "#313244" // Dark Grey (Surface1) + property color colCyan: "#89dceb" // Catppuccin Sky + property color colPurple: "#cba6f7" // Catppuccin Mauve + property color colRed: "#f38ba8" // Catppuccin Red + property color colYellow: "#f9e2af" // Catppuccin Yellow + property color colBlue: "#89b4fa" // Catppuccin Blue + property color colGreen: "#A3BE8C" + // Font + property string fontFamily: "Iosevka Nerd Font Propo" + property int fontSize: 16 + + // System info properties + property string kernelVersion: "Arch" + property string powerProfile: "" + property int cpuUsage: 0 + property string memUsage: "" + property string diskUsage: "" + property int volumeLevel: 0 + property string activeWindow: "Window" + property string currentLayout: "Tile" + property string cpuTemp: "0" + property int cpuTempInt: parseInt(cpuTemp, 10) + property string upTime: "0" + + property color tempColor: { + if (cpuTempInt < 50 ) return "#a6e3a1" // Green + else if (cpuTempInt < 70) return "#f9e2af" // Yellow + else return "#f38ba8" // Red + } + + property int notificationCount: 0 + + property var lastCpuIdle: 0 + property var lastCpuTotal: 0 + + property string weatherIcon: "๎ฝ " + property string weatherTemp: "--ยฐC" + property string weatherPrecip: "--%" + property string weatherWind: "--kph" + property string netConnection: "" + + + Process { + id: connectionProc + command: ["sh", "-c", "sed 's/dormant/๓ฐคฏ /;s/down/๓ฐคญ /;s/up/๓ฐคจ /' /sys/class/net/wlp8s0/operstate"] + stdout: SplitParser { + onRead: data => { if (data) netConnection = data.trim() } + } + Component.onCompleted: running = true + } + // System UpTime + Process { + id: upTimeProc + command: ["sh", "-c", "uptime|awk '{gsub(\",\",\"\");print $3}'"] + // command: ["sh", "-c", "uptime"] + stdout: SplitParser { + onRead: data => { if (data) upTime = data.trim() } + } + Component.onCompleted: running = true + } + + + + // CPU usage + Process { + id: cpuProc + command: ["sh", "-c", "head -1 /proc/stat"] + stdout: SplitParser { + onRead: data => { + if (!data) return + var parts = data.trim().split(/\s+/) + var user = parseInt(parts[1]) || 0 + var nice = parseInt(parts[2]) || 0 + var system = parseInt(parts[3]) || 0 + var idle = parseInt(parts[4]) || 0 + var iowait = parseInt(parts[5]) || 0 + var irq = parseInt(parts[6]) || 0 + var softirq = parseInt(parts[7]) || 0 + var total = user + nice + system + idle + iowait + irq + softirq + var idleTime = idle + iowait + if (lastCpuTotal > 0) { + var totalDiff = total - lastCpuTotal + var idleDiff = idleTime - lastCpuIdle + if (totalDiff > 0) cpuUsage = Math.round(100 * (totalDiff - idleDiff) / totalDiff) + } + lastCpuTotal = total + lastCpuIdle = idleTime + } + } + Component.onCompleted: running = true + } + + // Notification monitor + Process { + id: notifListener + command: ["sh", "-c", "dbus-monitor \"interface='org.freedesktop.Notifications',member='Notify'\" \"interface='org.freedesktop.Notifications',member='NotificationClosed'\""] + running: true + stdout: SplitParser { + onRead: data => { + countPoller.running = true + } + } +} + // Notification Updater + Process { + id: countPoller + command: ["sh", "-c", "dunstctl count | awk -F : '/History/ {print $2}'"] + stdout: SplitParser { + onRead: data => { + if (data) notificationCount = parseInt(data.trim()) + } + } +} + // show notification history + Process { + id: showHistoryProc + command: ["sh", "-c", "count=$(dunstctl count history); for i in $(seq 1 $count); do dunstctl history-pop; done"] + } + + // clear notifications + Process { + id: clearAllProc + command: ["dunstctl", "history-clear"] + onExited: { + countPoller.running = true; + } + } + + // Memory usage + Process { + id: memProc + command: ["sh", "-c", "free -h | grep Mem"] + stdout: SplitParser { + onRead: data => { + if (!data) return + var parts = data.trim().split(/\s+/) + var used = parts[2] || "0" + memUsage = used + } + } + Component.onCompleted: running = true + } + + // Weather + Process { + id: weatherProc + // Call your python script directly + command: ["python3", "/opt/scripts/weather.py"] + + stdout: SplitParser { + onRead: data => { + if (!data || data.trim() === "") return + var parts = data.trim().split(/\s+/) + if (parts.length >= 4) { + weatherIcon = parts[0] + weatherTemp = parts[1] + weatherPrecip = parts[2] + " " + parts[3] + weatherWind = parts[4] + " " + parts[5] + } + } + + } + Component.onCompleted: running = true +} + // Disk usage + Process { + id: diskProc + command: ["sh", "-c", "df -h / | tail -1"] + stdout: SplitParser { + onRead: data => { + if (!data) return + var parts = data.trim().split(/\s+/) + var StrInGB = parts[2] || "0G" + diskUsage = StrInGB + } + } + Component.onCompleted: running = true + } + + // Volume level + Process { + id: volProc + command: ["wpctl", "get-volume", "@DEFAULT_AUDIO_SINK@"] + stdout: SplitParser { + onRead: data => { + if (!data) return + var match = data.match(/Volume:\s*([\d.]+)/) + if (match) volumeLevel = Math.round(parseFloat(match[1]) * 100) + } + } + Component.onCompleted: running = true + } + + // Active window title + Process { + id: windowProc + command: ["sh", "-c", "hyprctl activewindow -j | jq -r '.title // empty'"] + stdout: SplitParser { + onRead: data => { if (data && data.trim()) activeWindow = data.trim() } + } + Component.onCompleted: running = true + } + + // Current layout + Process { + id: layoutProc + command: ["sh", "-c", "hyprctl activewindow -j | jq -r 'if .floating then \"Floating\" elif .fullscreen == 1 then \"Fullscreen\" else \"Tiled\" end'"] + stdout: SplitParser { + onRead: data => { if (data && data.trim()) currentLayout = data.trim() } + } + Component.onCompleted: running = true + } + + // CPU Temp + Process { + id: cpuTempProc + command: ["sh", "-c", "sensors | awk '/Tctl:/ {print $2}'"] + stdout: SplitParser { + onRead: data => { if (data && data.length > 0) cpuTemp = data.trim() } + } + } + + // Timers + + Timer { + interval: 5000; running: true; repeat: true + onTriggered: { + connectionProc.running = true + } + } + // UpTime Timer + Timer { + interval: 60000; running: true; repeat: true + onTriggered: { + upTimeProc.running = true + } + } + // SysEssentials Timer + Timer { + interval: 2000; running: true; repeat: true + onTriggered: { + cpuProc.running = true; memProc.running = true; diskProc.running = true + volProc.running = true; cpuTempProc.running = true; powerProfileProc.running = true + } + } + // Weather Timer + Timer { + interval: 3600000; running: true; repeat: true; onTriggered: { + console.log("Weather fetched at: " + new Date().toString()) + weatherProc.running = true + } + } + + Connections { + target: Hyprland + function onRawEvent(event) { windowProc.running = true; layoutProc.running = true } + } + + Timer { + interval: 200; running: true; repeat: true + onTriggered: { windowProc.running = true; layoutProc.running = true } + } + + Variants { + model: Quickshell.screens + PanelWindow { + property var modelData + screen: modelData + anchors { top: true; left: true; right: true } + implicitHeight: 30 + color: root.colBg + + Rectangle { + anchors.fill: parent + color: root.colBg + + RowLayout { + anchors.fill: parent; spacing: 0 + Item { width: 8 } + + // Arch Icon + Rectangle { + Layout.preferredWidth: 24; Layout.preferredHeight: 24; color: "transparent" + Image { + anchors.fill: parent + source: "file:///home/subh/.config/quickshell/icons/arch.png" + fillMode: Image.PreserveAspectFit + } + } + + Item { width: 8 } + + // Workspaces + Repeater { + model: 9 + Rectangle { + Layout.preferredWidth: 20; Layout.preferredHeight: parent.height; color: "transparent" + property var workspace: Hyprland.workspaces.values.find(ws => ws.id === index + 1) ?? null + property bool isActive: Hyprland.focusedWorkspace?.id === (index + 1) + property bool hasWindows: workspace !== null + + Text { + text: index + 1 + color: parent.isActive ? root.colCyan : (parent.hasWindows ? root.colFg : root.colMuted) + font.pixelSize: root.fontSize; font.family: root.fontFamily; font.bold: true + anchors.centerIn: parent + } + Rectangle { + width: 20; height: 3 + color: parent.isActive ? root.colPurple : "transparent" + anchors.horizontalCenter: parent.horizontalCenter; anchors.bottom: parent.bottom + } + MouseArea { + anchors.fill: parent + onClicked: Hyprland.dispatch("workspace " + (index + 1)) + } + } + } + + // Separator + Rectangle { Layout.preferredWidth: 1; Layout.preferredHeight: 16; Layout.leftMargin: 8; Layout.rightMargin: 8; color: root.colMuted } + + // Layout + Text { text: currentLayout; color: root.colFg; font.pixelSize: root.fontSize; font.family: root.fontFamily; font.bold: true } + Rectangle { Layout.preferredWidth: 1; Layout.preferredHeight: 16; Layout.leftMargin: 8; Layout.rightMargin: 8; color: root.colMuted } + Text { text: "๓ฐฆ " + upTime; color: root.colCyan; font.pixelSize: root.fontSize; font.family: root.fontFamily; font.bold: true } + + Rectangle { Layout.preferredWidth: 1; Layout.preferredHeight: 16; Layout.leftMargin: 8; Layout.rightMargin: 8; color: root.colMuted } + + // Window Title + Text { + text: activeWindow; color: root.colPurple; font.pixelSize: root.fontSize; font.family: root.fontFamily; font.bold: true + Layout.fillWidth: true; Layout.leftMargin: 8; elide: Text.ElideRight; maximumLineCount: 1 + } + RowLayout { + id: weatherRow + spacing: 10 + + Text { + text: weatherIcon + color: root.colYellow + font.pixelSize: 18 + font.family: root.fontFamily + font.bold: true + } + + Text { + text: weatherTemp + font.family: root.fontFamily + font.pixelSize: root.fontSize + color: root.colYellow + font.bold: true + } + + Text { + text: weatherPrecip + font.family: root.fontFamily + font.pixelSize: root.fontSize + color: root.colGreen + font.bold: true + } + + Text { + text: weatherWind + font.family: root.fontFamily + font.pixelSize: root.fontSize + color: root.colBlue + font.bold: true + Layout.rightMargin: 8 + } + + } + + Rectangle { Layout.preferredWidth: 1; Layout.preferredHeight: 16; Layout.rightMargin: 8; color: root.colMuted } + + Text { text: "๏ " + cpuTemp; color: tempColor; font.pixelSize: root.fontSize; font.family: root.fontFamily; font.bold: true; Layout.rightMargin: 8 } + Rectangle { Layout.preferredWidth: 1; Layout.preferredHeight: 16; Layout.rightMargin: 8; color: root.colMuted } + + Text { text: "๏ผ " + cpuUsage + "%"; color: root.colPurple; font.pixelSize: root.fontSize; font.family: root.fontFamily; font.bold: true; Layout.rightMargin: 8 } + Rectangle { Layout.preferredWidth: 1; Layout.preferredHeight: 16; Layout.rightMargin: 8; color: root.colMuted } + + Text { text: "๎ " + memUsage; color: root.colCyan; font.pixelSize: root.fontSize; font.family: root.fontFamily; font.bold: true; Layout.rightMargin: 8 } + Rectangle { Layout.preferredWidth: 1; Layout.preferredHeight: 16; Layout.rightMargin: 8; color: root.colMuted } + + Text { text: "๏ " + diskUsage; color: root.colBlue; font.pixelSize: root.fontSize; font.family: root.fontFamily; font.bold: true; Layout.rightMargin: 8 } + Rectangle { Layout.preferredWidth: 1; Layout.preferredHeight: 16; Layout.rightMargin: 8; color: root.colMuted } + + Text { text: netConnection; color: root.colBlue; font.pixelSize: root.fontSize; font.family: root.fontFamily; font.bold: true; Layout.rightMargin: 4 } + // netspeed + RowLayout { + id: netSpeedRow + visible: root.netConnection == "๓ฐคจ" + spacing: 0 + + Rectangle { + Layout.preferredWidth: 1; Layout.preferredHeight: 16 + Layout.leftMargin: 8; Layout.rightMargin: 8 + color: root.colMuted + } + Text { + id: netSpeed + color: root.colRed + font.pixelSize: 15 + font.family: root.fontFamily + font.bold: true + Layout.rightMargin: 8 + + Process { + id: netProc + command: ["bash", "/opt/scripts/netspeed.sh", "wlp8s0"] + running: root.netConnection == "๓ฐคจ" + stdout: SplitParser { + onRead: data => netSpeed.text = data.trim() + } + } + } + } + + Rectangle { Layout.preferredWidth: 1; Layout.preferredHeight: 16; Layout.rightMargin: 8; color: root.colMuted } + Text { text: "๏จ " + volumeLevel + "%"; color: root.colPurple; font.pixelSize: root.fontSize; font.family: root.fontFamily; font.bold: true; Layout.rightMargin: 8 } + Rectangle { Layout.preferredWidth: 1; Layout.preferredHeight: 16; Layout.rightMargin: 8; color: root.colMuted } + + + // Clock + Text { + id: clockText + text: Qt.formatDateTime(new Date(), "ddd, MMM dd - HH:mm") + color: root.colFg + font.pixelSize: root.fontSize; font.family: root.fontFamily; font.bold: true; Layout.rightMargin: 8 + Timer { + interval: 1000; running: true; repeat: true + onTriggered: clockText.text = Qt.formatDateTime(new Date(), "ddd, MMM dd - HH:mm:ss") + } + } + + RowLayout { + id: notifRow + visible: root.notificationCount > 0 + spacing: 0 + + Rectangle { + Layout.preferredWidth: 1; Layout.preferredHeight: 16 + Layout.leftMargin: 8; Layout.rightMargin: 8 + color: root.colMuted + } + + Text { + text: "๓ฐ " + root.notificationCount + color: root.colYellow + font.pixelSize: root.fontSize + font.family: root.fontFamily + font.bold: true + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + + acceptedButtons: Qt.LeftButton | Qt.RightButton + onClicked: (mouse) => { + if (mouse.button === Qt.RightButton) { + clearAllProc.running = true; + } else { + showHistoryProc.running = true; + } + } + } + } + } + + Item { width: 8 } + } + } + } + } +} |
