import QtQuick import QtQuick.Effects import Quickshell import Quickshell.Io import Quickshell.Wayland import "." as M PanelWindow { id: root required property var screen color: "transparent" WlrLayershell.layer: WlrLayer.Background WlrLayershell.exclusiveZone: -1 WlrLayershell.namespace: "nova-overview-backdrop" mask: Region {} anchors.top: true anchors.left: true anchors.right: true anchors.bottom: true SystemClock { id: clock precision: SystemClock.Seconds } // Slow drifting gradient background Rectangle { anchors.fill: parent property real _phase: 0 NumberAnimation on _phase { from: 0 to: 360 duration: 30000 loops: Animation.Infinite } gradient: Gradient { orientation: Gradient.Horizontal GradientStop { position: 0 color: Qt.rgba(M.Theme.base0C.r, M.Theme.base0C.g, M.Theme.base0C.b, 0.06) } GradientStop { position: 0.5 color: Qt.rgba(M.Theme.base0E.r, M.Theme.base0E.g, M.Theme.base0E.b, 0.04) } GradientStop { position: 1 color: Qt.rgba(M.Theme.base09.r, M.Theme.base09.g, M.Theme.base09.b, 0.06) } } } // Scanning line — slow horizontal sweep Rectangle { id: scanLine width: 2 height: parent.height opacity: 0.08 color: M.Theme.base0D NumberAnimation on x { from: 0 to: root.width duration: 8000 loops: Animation.Infinite easing.type: Easing.InOutSine } // Glow trail Rectangle { anchors.top: parent.top anchors.bottom: parent.bottom anchors.right: parent.left width: 60 gradient: Gradient { orientation: Gradient.Horizontal GradientStop { position: 0 color: "transparent" } GradientStop { position: 1 color: Qt.rgba(M.Theme.base0D.r, M.Theme.base0D.g, M.Theme.base0D.b, 0.04) } } } } // Vertical scan line — slower Rectangle { id: vScanLine width: parent.width height: 1 opacity: 0.06 color: M.Theme.base0E NumberAnimation on y { from: 0 to: root.height duration: 12000 loops: Animation.Infinite easing.type: Easing.InOutSine } } // Floating hex grid Canvas { anchors.fill: parent opacity: 0.04 onPaint: { const ctx = getContext("2d"); const w = width, h = height; ctx.clearRect(0, 0, w, h); ctx.strokeStyle = M.Theme.base05.toString(); ctx.lineWidth = 0.5; const size = 40; const dx = size * 1.5; const dy = size * Math.sqrt(3); for (let col = -1; col < w / dx + 1; col++) { for (let row = -1; row < h / dy + 1; row++) { const cx = col * dx; const cy = row * dy + (col % 2 ? dy / 2 : 0); ctx.beginPath(); for (let i = 0; i < 6; i++) { const angle = Math.PI / 3 * i - Math.PI / 6; const px = cx + size * 0.5 * Math.cos(angle); const py = cy + size * 0.5 * Math.sin(angle); if (i === 0) ctx.moveTo(px, py); else ctx.lineTo(px, py); } ctx.closePath(); ctx.stroke(); } } } } // Center content Column { anchors.centerIn: parent spacing: 20 // Large neon clock Item { anchors.horizontalCenter: parent.horizontalCenter width: clockRow.width height: clockRow.height Row { id: glowSrc visible: false anchors.centerIn: parent Text { text: Qt.formatDateTime(clock.date, "HH") color: M.Theme.base0D font.pixelSize: 96 font.family: M.Theme.fontFamily font.bold: true anchors.verticalCenter: parent.verticalCenter } Text { text: ":" color: _colon._colors[_colon._colorIdx % _colon._colors.length] font.pixelSize: 96 font.family: M.Theme.fontFamily font.bold: true opacity: _colon.opacity anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 800 } } } Text { text: Qt.formatDateTime(clock.date, "mm") color: M.Theme.base0E font.pixelSize: 96 font.family: M.Theme.fontFamily font.bold: true anchors.verticalCenter: parent.verticalCenter } } MultiEffect { source: glowSrc anchors.fill: glowSrc shadowEnabled: true shadowColor: M.Theme.base0D shadowBlur: 1.0 shadowVerticalOffset: 0 shadowHorizontalOffset: 0 } Row { id: clockRow anchors.centerIn: parent Text { text: Qt.formatDateTime(clock.date, "HH") color: M.Theme.base0D opacity: 0.9 font.pixelSize: 96 font.family: M.Theme.fontFamily font.bold: true anchors.verticalCenter: parent.verticalCenter } Text { id: _colon text: ":" font.pixelSize: 96 font.family: M.Theme.fontFamily font.bold: true anchors.verticalCenter: parent.verticalCenter property int _colorIdx: 0 readonly property var _colors: [M.Theme.base08, M.Theme.base09, M.Theme.base0A, M.Theme.base0B, M.Theme.base0C, M.Theme.base0D, M.Theme.base0E, M.Theme.base05] color: _colors[_colorIdx % _colors.length] Behavior on color { ColorAnimation { duration: 800 } } SequentialAnimation { loops: Animation.Infinite running: true NumberAnimation { target: _colon property: "opacity" to: 0.1 duration: 1000 easing.type: Easing.InOutSine } ScriptAction { script: _colon._colorIdx++ } NumberAnimation { target: _colon property: "opacity" to: 0.9 duration: 1000 easing.type: Easing.InOutSine } } } Text { text: Qt.formatDateTime(clock.date, "mm") color: M.Theme.base0E opacity: 0.9 font.pixelSize: 96 font.family: M.Theme.fontFamily font.bold: true anchors.verticalCenter: parent.verticalCenter } } } // Seconds bar Item { anchors.horizontalCenter: parent.horizontalCenter width: clockRow.width height: 3 Rectangle { anchors.fill: parent color: M.Theme.base02 radius: 1 opacity: 0.2 } Rectangle { width: parent.width * (clock.date.getSeconds() / 59) height: parent.height radius: 1 opacity: 0.6 color: _colon._colors[_colon._colorIdx % _colon._colors.length] Behavior on color { ColorAnimation { duration: 800 } } Behavior on width { NumberAnimation { duration: 300 } } } } // Date Text { anchors.horizontalCenter: parent.horizontalCenter text: Qt.formatDateTime(clock.date, "dddd, dd MMMM yyyy") color: M.Theme.base05 opacity: 0.4 font.pixelSize: 20 font.family: M.Theme.fontFamily font.letterSpacing: 6 layer.enabled: true layer.effect: MultiEffect { shadowEnabled: true shadowColor: M.Theme.base0D shadowBlur: 0.3 shadowVerticalOffset: 0 shadowHorizontalOffset: 0 } } // System stats row Row { anchors.horizontalCenter: parent.horizontalCenter spacing: 30 Repeater { model: [ { label: "CPU", file: "/proc/stat" }, { label: "MEM", file: "/proc/meminfo" }, { label: "TMP", file: "/sys/class/thermal/thermal_zone0/temp" } ] delegate: Column { required property var modelData required property int index spacing: 4 property int _val: 0 readonly property var _accent: [M.Theme.base08, M.Theme.base0B, M.Theme.base09][index] Timer { interval: 2000 running: true repeat: true triggeredOnStart: true onTriggered: _reader.running = true } Process { id: _reader command: ["sh", "-c", { "CPU": "awk '/^cpu /{u=$2+$4; t=$2+$3+$4+$5+$6+$7+$8; print int(u*100/t)}' /proc/stat", "MEM": "awk '/MemTotal/{t=$2}/MemAvailable/{a=$2}END{print int((t-a)*100/t)}' /proc/meminfo", "TMP": "awk '{print int($1/1000)}' /sys/class/thermal/thermal_zone0/temp" }[modelData.label]] stdout: StdioCollector { onStreamFinished: parent.parent._val = parseInt(text) || 0 } } Text { anchors.horizontalCenter: parent.horizontalCenter text: parent._val + (parent.modelData.label === "TMP" ? "°" : "%") color: parent._accent opacity: 0.7 font.pixelSize: 18 font.family: M.Theme.fontFamily font.bold: true } // Mini bar Item { anchors.horizontalCenter: parent.horizontalCenter width: 50 height: 3 Rectangle { anchors.fill: parent color: M.Theme.base02 radius: 1 opacity: 0.15 } Rectangle { width: parent.width * Math.min(1, parent.parent._val / 100) height: parent.height radius: 1 opacity: 0.5 color: parent.parent._accent Behavior on width { NumberAnimation { duration: 500 } } } } Text { anchors.horizontalCenter: parent.horizontalCenter text: parent.modelData.label color: M.Theme.base04 opacity: 0.4 font.pixelSize: 10 font.family: M.Theme.fontFamily font.letterSpacing: 3 } } } } } }