diff --git a/quickshell/.config/quickshell/modules/Cpu.qml b/quickshell/.config/quickshell/modules/Cpu.qml index cac51a5..3cfdbaf 100644 --- a/quickshell/.config/quickshell/modules/Cpu.qml +++ b/quickshell/.config/quickshell/modules/Cpu.qml @@ -15,7 +15,7 @@ Rectangle { Process { id: cpuProc command: ["sh", "-c", "head -1 /proc/stat"] - property double cpuUsage + //property double cpuUsage stdout: SplitParser { onRead: data => { if (!data) { diff --git a/quickshell/.config/quickshell/swayshell.qml b/quickshell/.config/quickshell/swayshell.qml index d7f6abd..0b0f0a7 100755 --- a/quickshell/.config/quickshell/swayshell.qml +++ b/quickshell/.config/quickshell/swayshell.qml @@ -12,336 +12,337 @@ import QtQuick.Layouts // Some credit goes to my friends Lucy and Babsi // Zoe here, ignore the wide ass code, emacs qml-mode adds 2 on my tab-width for some reason -PanelWindow { - id: root - - property color colBg: "#454545" - property color colAppBg: "#333333" - property color colFg: "#ffffff" - property string fontFamily: "Hack Nerd Font" - property int fontSize: 16 - property int appletRadHeight: 25 - property int appletSpacing: 6 - - - property int cpuUsage: 0 - property var lastCpuIdle: 0 - property var lastCpuTotal: 0 - property real ramUsage: 0.00 - - property var batCharMin: (UPower.displayDevice.timeToFull / 60).toFixed(2) - property var batDisMin: (UPower.displayDevice.timeToEmpty / 60).toFixed(2) - property var batTime: 0 - - anchors { - right: true - left: true - top:true - } - - color: "transparent" - implicitHeight: root.appletRadHeight + 5 - margins { - right: 0 // 5 - left: 0 // 5 - top: 0 // 5 - bottom: 0 - } - Rectangle { - color: root.colBg - anchors.fill: parent - // radius: root.appletRadHeight - } - - RowLayout { - id: leftRow - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - Item { - id: rootItem - implicitWidth: root.appletRadHeight - height: root.appletRadHeight - Row { - id: workspaceRow - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - leftPadding: 10 - - Repeater { - id: wsRepeater - model: I3.workspaces - anchors.centerIn: parent - - Rectangle { - id: workspaceNumber - property bool isOnMon: { - if (!modelData) - return false - if (!modelData.monitor) - return false - if (!rootItem.screen) - return false; - return modelData.monitor.name === rootItem.screen.name; - } - - required property var modelData - height: root.appletRadHeight * 1.1 - width: root.appletRadHeight * 1.1 - radius: root.appletRadHeight - color: root.colAppBg - Text { - anchors.centerIn: parent - text: parent.modelData.number - color: root.colFg - opacity: workspaceNumber.modelData.focused ? 1 : 0.5 - font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } - } - - MouseArea { - anchors.fill: parent - onClicked: {parent.modelData.activate();} - } - } - } - } - } - } - /* - RowLayout { - id: centerRow - spacing: root.appletSpacing - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - } - */ - RowLayout { - id: rightRow - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - spacing: root.appletSpacing +Variants { + model: Quickshell.screens + delegate: WlrLayershell { + id: root + layer: WlrLayer.Top + required property ShellScreen modelData + screen: modelData - Item { - Process { - id: cpuProc - command: ["sh", "-c", "head -1 /proc/stat"] - stdout: SplitParser { - onRead: data => { - if (!data) return - var p = data.trim().split(/\s+/) - var idle = parseInt(p[4]) + parseInt(p[5]) - var total = p.slice(1, 8).reduce((a, b) => a + parseInt(b), 0) - if (lastCpuTotal > 0) { - cpuUsage = Math.round(100 * (1 - (idle - lastCpuIdle) / (total - lastCpuTotal))) - } - lastCpuTotal = total - lastCpuIdle = idle - } - } - Component.onCompleted: running = true - } + readonly property color colBg: "#3c1450" + readonly property color colAppBg: "#1e0a28" + readonly property color colFg: "#d2d2d2" + readonly property color colDark: "#230f05" + readonly property string fontFamily: "Iosevka" + readonly property int fontSize: 18 + readonly property int appletRadHeight: 25 + readonly property int appletSpacing: 6 + + property real lastCpuTotal: 0.0 + property real lastCpuIdle: 0.0 + property real cpuUsage + + property real ramUsage: 0.00 + + property var batCharMin: (UPower.displayDevice.timeToFull / 60).toFixed(2) + property var batDisMin: (UPower.displayDevice.timeToEmpty / 60).toFixed(2) + property var batTime: 0 + + anchors { + right: true + left: true + top:true + } + + color: "transparent" + implicitHeight: root.appletRadHeight + 10 + margins { + right: 5 + left: 5 + top: 5 + bottom: 0 + } + Rectangle { + id: barRect + color: root.colBg + anchors.fill: parent + radius: root.appletRadHeight + } + + RowLayout { + id: leftRow + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + spacing: root.appletSpacing - Process { - id: ramProc - command: ["sh", "-c", "free | grep Mem"] - stdout: SplitParser { - onRead: data => { - if (!data) return - var parts = data.trim().split(/\s+/) - var used = parseInt(parts[2]) || 0 - ramUsage = used /1048576 - } - } - Component.onCompleted: running = true - } - Timer { - interval: 2000 - running: true - repeat: true - onTriggered: { - cpuProc.running = true - ramProc.running = true - } - } - Item { - id: procItem - Row { - id: procRow - spacing: root.appletSpacing - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - leftPadding: 10 + Loader { + id: batLoader + active: true + Layout.leftMargin: 8 + sourceComponent: Rectangle { + id: batRect + clip: true + color: root.colAppBg + visible: UPower.displayDevice.isPresent + implicitHeight: root.appletRadHeight + implicitWidth: batText.implicitWidth + 25 + radius: root.appletRadHeight - Loader { - id: batLoader - active: true - sourceComponent: Rectangle { - id: batRect - clip: true - color: root.colAppBg - visible: UPower.displayDevice.isPresent - implicitHeight: root.appletRadHeight - implicitWidth: batText.implicitWidth + 25 - radius: root.appletRadHeight - - function getBatStat() { - if (UPower.displayDevice.state == UPowerDeviceState.Discharging) { - batTime = Math.floor(batDisMin / 60) + "h " + ((batDisMin - (Math.floor(batDisMin / 60) * 60)).toFixed(0)) + "min" - return batTime; - } - if (UPower.displayDevice.state == UPowerDeviceState.Charging) { - batTime = Math.floor(batCharMin / 60) + "h " + ((batCharMin - (Math.floor(batCharMin / 60) * 60)).toFixed(0)) + "min" - return batTime; - } - if (UPower.displayDevice.state == UPowerDeviceState.FullyCharged) { - return "Full"; - } - } - function batStatProc() { - return Math.round(UPower.displayDevice.percentage * 100) + "%"; - } - - Text { - id: batText - anchors.centerIn: parent - color: root.colFg - text: batStatProc() + " - " + getBatStat() - font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } - } + function getBatStat() { + if (UPower.displayDevice.state == UPowerDeviceState.Discharging) { + batTime = Math.floor(batDisMin / 60) + "h " + ((batDisMin - (Math.floor(batDisMin / 60) * 60)).toFixed(0)) + "min" + return batTime; } + if (UPower.displayDevice.state == UPowerDeviceState.Charging) { + batTime = Math.floor(batCharMin / 60) + "h " + ((batCharMin - (Math.floor(batCharMin / 60) * 60)).toFixed(0)) + "min" + return batTime; + } + if (UPower.displayDevice.state == UPowerDeviceState.FullyCharged) { + return "Full"; + } + } + function batStatProc() { + return Math.round(UPower.displayDevice.percentage * 100) + "%"; } - - Rectangle { - height: root.appletRadHeight - width: cpuText.paintedWidth + 25 - radius: root.appletRadHeight - color: root.colAppBg - - Text { - id: cpuText - anchors.centerIn: parent - text: "CPU: " + cpuUsage + "%" - color: root.colFg - font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } - } + Text { + id: batText + anchors.centerIn: parent + color: root.colFg + text: batStatProc() + " - " + getBatStat() + font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } } - Rectangle { - height: root.appletRadHeight - width: ramText.paintedWidth + 28 - radius: root.appletRadHeight - color: root.colAppBg - - Text { - id: ramText - anchors.centerIn: parent - text: "RAM: " + ramUsage.toFixed(2) + " GiB" - color: root.colFg - font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } - } - } - Rectangle { - id: pwRect - color: root.colAppBg - property PwNode defaultAudio: Pipewire.ready ? Pipewire.preferredDefaultAudioSink : null - property bool mute: Pipewire.ready ? defaultAudio?.audio.muted : null - radius: root.appletRadHeight - implicitHeight: root.appletRadHeight - implicitWidth: pwText.implicitWidth + 25 - - PwObjectTracker { - objects: [Pipewire.ready ? Pipewire.defaultAudioSink : null] - } - - Process { - id: pavuLauncher - command: ["pavucontrol"] - running: false - } - - Text { - id: pwText - anchors.centerIn: pwRect - color: root.colFg - opacity: pwRect.defaultAudio?.audio.muted ? 0.6 : 1.0 - font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } - text: pwRect.mute ? "MUT: " + Math.floor(pwRect.defaultAudio?.audio.volume * 100) + "%" : "VOL: " + Math.floor(pwRect.defaultAudio?.audio.volume * 100) + "%" - } - MouseArea { - id: clickHandler - hoverEnabled: true - acceptedButtons: Qt.LeftButton - cursorShape: Qt.PointingHandCursor - anchors.fill: pwRect - onClicked: pavuLauncher.running = true - } - } - } } - } - - Row { - id: clockRow Rectangle { - id: clockRect - clip: true - implicitHeight: root.appletRadHeight - implicitWidth: clockText.implicitWidth + 25 + id: cpuRect color: root.colAppBg + implicitHeight: root.appletRadHeight + implicitWidth: cpuText.width + 25 radius: root.appletRadHeight - SystemClock { - id: clock - precision: SystemClock.Seconds + Process { + id: cpuProc + command: ["sh", "-c", "head -1 /proc/stat"] + stdout: SplitParser { + onRead: data => { + if (!data) { + return; + } + else { + var p = data.trim().split(/\s+/); + var idle = parseInt(p[4]) + parseInt(p[5]); + var total = p.slice(1, 8).reduce((a, b) => a + parseInt(b), 0); + root.cpuUsage = Math.round(100 * (1 - (idle - root.lastCpuIdle) / (total - root.lastCpuTotal))); + root.lastCpuTotal = total; + root.lastCpuIdle = idle; + } + } + } + Component.onCompleted: running = true + } + Timer { + id: cpuProcRestarter + interval: 2000 + repeat: true + running: true + onTriggered: cpuProc.running = true } Text { - id: clockText - anchors.centerIn: clockRect + id: cpuText + anchors.centerIn: parent color: root.colFg font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } - text: Qt.formatDateTime(clock.date, "yyyy.MM.dd - hh:mm:ss") + text: "CPU: " + root.cpuUsage + "%" + } + } + + Rectangle { + id: ramRect + implicitHeight: root.appletRadHeight + radius: root.appletRadHeight + implicitWidth: ramText.width + 25 + color: root.colAppBg + Process { + id: ramProc + command: ["sh", "-c", "free | grep Mem"] + running: true + stdout: SplitParser { + onRead: data => { + if (!data) { + return; + } + var parts = data.trim().split(/\s+/); + var used = parseInt(parts[2]) || 0; + root.ramUsage = used / 1048576; + } + } + } + Timer { + id: ramProcRestarter + interval: 2000 + running: true + repeat: true + onTriggered: ramProc.running = true + } + Text { + id: ramText + anchors.centerIn: ramRect + text: "RAM: " + root.ramUsage.toFixed(2) + " GiB" + font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } + color: root.colFg } } } - Row { - id: trayWholeRow - rightPadding: 10 - Rectangle { - id: trayRect - color: root.colAppBg - visible: iconRepeater.count != 0 - radius: root.appletRadHeight - Layout.fillHeight: true - implicitHeight: root.appletRadHeight - implicitWidth: iconlayout.implicitWidth + 16 - - RowLayout { - id: iconlayout - anchors.centerIn: trayRect + RowLayout { + id: centerRow + anchors.centerIn: parent + spacing: root.appletSpacing + + Item { + id: wsItem + implicitWidth: root.appletRadHeight + height: root.appletRadHeight + Row { + id: workspaceRow + anchors.centerIn: parent + leftPadding: 10 + Repeater { - id: iconRepeater - model: SystemTray.items - delegate: WrapperMouseArea { - id: iconWrapper + id: wsRepeater + model: I3.workspaces + anchors.centerIn: parent + + Rectangle { + id: workspaceNumber + property bool isOnMon: { + if (!modelData) + return false + if (!modelData.monitor) + return false + if (!wsItem.screen) + return false; + return modelData.monitor.name === wsItem.screen.name; + } + required property var modelData - child: IconImage { - source: iconWrapper.modelData.icon - implicitSize: 16 + height: root.appletRadHeight * 1.1 + width: root.appletRadHeight * 1.1 + radius: root.appletRadHeight + color: root.colAppBg + Text { + anchors.centerIn: parent + text: parent.modelData.number + color: root.colFg + opacity: workspaceNumber.modelData.focused ? 1 : 0.5 + font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } } - QsMenuAnchor { - id: menu - anchor.item: iconWrapper - menu: modelData.menu + + MouseArea { + anchors.fill: parent + onClicked: {parent.modelData.activate();} } - acceptedButtons: Qt.LeftButton | Qt.RightButton - onClicked: mouse => { - if (mouse.button == Qt.RightButton) { - menu.open(); + } + } + } + } + } + RowLayout { + id: rightRow + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + spacing: root.appletSpacing + + Row { + id: trayWholeRow + Rectangle { + id: trayRect + color: root.colAppBg + visible: iconRepeater.count != 0 + radius: root.appletRadHeight + Layout.fillHeight: true + implicitHeight: root.appletRadHeight + implicitWidth: iconlayout.implicitWidth + 16 + + RowLayout { + id: iconlayout + anchors.centerIn: trayRect + Repeater { + id: iconRepeater + model: SystemTray.items + delegate: WrapperMouseArea { + id: iconWrapper + required property var modelData + child: IconImage { + source: iconWrapper.modelData.icon + implicitSize: 16 + } + QsMenuAnchor { + id: menu + anchor.item: iconWrapper + menu: modelData.menu + } + acceptedButtons: Qt.LeftButton | Qt.RightButton + onClicked: mouse => { + if (mouse.button == Qt.RightButton) { + menu.open(); + } } } } } } } + Rectangle { + id: pwRect + color: root.colAppBg + property PwNode defaultAudio: Pipewire.ready ? Pipewire.preferredDefaultAudioSink : null + property bool mute: Pipewire.ready ? defaultAudio?.audio.muted : null + radius: root.appletRadHeight + implicitHeight: root.appletRadHeight + implicitWidth: pwText.implicitWidth + 25 + + PwObjectTracker { + objects: [Pipewire.ready ? Pipewire.defaultAudioSink : null] + } + + Process { + id: pavuLauncher + command: ["pavucontrol"] + running: false + } + + Text { + id: pwText + anchors.centerIn: pwRect + color: root.colFg + opacity: pwRect.defaultAudio?.audio.muted ? 0.6 : 1.0 + font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } + text: pwRect.mute ? "MUT: " + Math.floor(pwRect.defaultAudio?.audio.volume * 100) + "%" : "VOL: " + Math.floor(pwRect.defaultAudio?.audio.volume * 100) + "%" + } + MouseArea { + id: clickHandler + hoverEnabled: true + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + anchors.fill: pwRect + onClicked: pavuLauncher.running = true + } + } + + Row { + id: clockRow + Layout.rightMargin: 8 + Rectangle { + id: clockRect + clip: true + implicitHeight: root.appletRadHeight + implicitWidth: clockText.implicitWidth + 25 + color: root.colAppBg + radius: root.appletRadHeight + SystemClock { + id: clock + precision: SystemClock.Seconds + } + Text { + id: clockText + anchors.centerIn: clockRect + color: root.colFg + font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } + text: Qt.formatDateTime(clock.date, "yyyy.MM.dd - hh:mm:ss") + } + } + } } } }