From 14dd8214aced8ac97d476dd16c6d8e57200f5d78 Mon Sep 17 00:00:00 2001 From: Crony Akatsuki Date: Wed, 11 Mar 2026 20:49:24 +0100 Subject: [PATCH] feat: simple bar for now. --- .envrc | 2 + .gitignore | 1 + default.nix | 25 ++++++++ flake.lock | 48 ++++++++++++++ flake.nix | 35 ++++++++++ shell.nix | 17 +++++ src/shell.qml | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 303 insertions(+) create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 default.nix create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 shell.nix create mode 100644 src/shell.qml diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..6752988 --- /dev/null +++ b/.envrc @@ -0,0 +1,2 @@ +watch_file flake.nix shell.nix default.nix +use flake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b42106 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.direnv/ diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..54d15f4 --- /dev/null +++ b/default.nix @@ -0,0 +1,25 @@ +{ + stdenv, + quickshell, + makeWrapper, + ... +}: +stdenv.mkDerivation { + name = "cronyshell"; + + src = ./.; + + nativeBuildInputs = [makeWrapper]; + + installPhase = '' + mkdir -p $out/bin + mkdir -p $out/share/quickshell/cronyshell + + cp -r $src/src/* $out/share/quickshell/cronyshell + + cp ${quickshell}/bin/quickshell $out/bin/cronyshell + + wrapProgram $out/bin/cronyshell \ + --add-flags "-p $out/share/quickshell/cronyshell" + ''; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..23d5c9d --- /dev/null +++ b/flake.lock @@ -0,0 +1,48 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1772963539, + "narHash": "sha256-9jVDGZnvCckTGdYT53d/EfznygLskyLQXYwJLKMPsZs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "9dcb002ca1690658be4a04645215baea8b95f31d", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "quickshell": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1773129285, + "narHash": "sha256-7G6x33z271v/jhBC5Le7NPOZhv9902+MfCkC9poMwf0=", + "ref": "refs/heads/master", + "rev": "bd6217927739a79c1c4ff279051f9625cd4b2b5e", + "revCount": 752, + "type": "git", + "url": "https://git.outfoxxed.me/quickshell/quickshell" + }, + "original": { + "type": "git", + "url": "https://git.outfoxxed.me/quickshell/quickshell" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "quickshell": "quickshell" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..7ba8210 --- /dev/null +++ b/flake.nix @@ -0,0 +1,35 @@ +{ + description = "crony shell"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + + quickshell = { + url = "git+https://git.outfoxxed.me/quickshell/quickshell"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { + self, + nixpkgs, + ... + } @ inputs: let + systems = ["x86_64-linux"]; + forEachSystem = nixpkgs.lib.genAttrs systems; + pkgsForEach = nixpkgs.legacyPackages; + in { + packages = forEachSystem (system: { + default = self.packages.${system}.cronyshell; + cronyshell = pkgsForEach.${system}.callPackage ./default.nix { + quickshell = inputs.quickshell.packages.${system}.default; + }; + }); + + devShells = forEachSystem (system: { + default = pkgsForEach.${system}.callPackage ./shell.nix { + quickshell = inputs.quickshell.packages.${system}.default; + }; + }); + }; +} diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..d65a1c2 --- /dev/null +++ b/shell.nix @@ -0,0 +1,17 @@ +{ + pkgs, + quickshell, + ... +}: +pkgs.mkShell { + packages = [ + quickshell + pkgs.kdePackages.qtdeclarative + ]; + shellHook = '' + # Required for qmlls to find the correct type declarations + # Sadly Quickshell doesn't export some types declaratively + export QMLLS_BUILD_DIRS=${pkgs.kdePackages.qtdeclarative}/lib/qt-6/qml/:${quickshell}/lib/qt-6/qml/ + export QML_IMPORT_PATH=$PWD/src + ''; +} diff --git a/src/shell.qml b/src/shell.qml new file mode 100644 index 0000000..b5c6386 --- /dev/null +++ b/src/shell.qml @@ -0,0 +1,175 @@ +import Quickshell +import Quickshell.Wayland +import Quickshell.Hyprland +import Quickshell.Widgets +import Quickshell.Io +import QtQuick +import QtQuick.Layouts + +PanelWindow { + id: root + + MarginWrapperManager { + margin: 10 + } + + // Theme properties + property color colBg: "#1f1d2e" + property color colFg: "#e0def4" + property color colMuted: "#6e6a86" + property color colCyan: "#9ccfd8" + property color colBlue: "#31748f" + property color colYellow: "#f6c177" + property string fontFamily: "CommitMono Nerd Font" + property int fontSize: 16 + + // System stats + property int cpuUsage: 0 + property var lastCpuIdle: 0 + property var lastCpuTotal: 0 + property int memUsage: 0 + property string clock + + 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 (root.lastCpuTotal > 0) { + root.cpuUsage = Math.round(100 * (1 - (idle - root.lastCpuIdle) / (total - root.lastCpuTotal))); + } + root.lastCpuTotal = total; + root.lastCpuIdle = idle; + } + } + Component.onCompleted: running = true + } + Process { + id: memProc + command: ["sh", "-c", "free | grep Mem"] + stdout: SplitParser { + onRead: data => { + if (!data) + return; + var parts = data.trim().split(/\s+/); + var total = parseInt(parts[1]) || 1; + var used = parseInt(parts[2]) || 0; + root.memUsage = Math.round(100 * used / total); + } + } + Component.onCompleted: running = true + } + + Timer { + interval: 5000 + running: true + repeat: true + onTriggered: { + cpuProc.running = true; + memProc.running = true; + } + } + + anchors.top: true + anchors.left: true + anchors.right: true + implicitHeight: 24 + color: root.colBg + + RowLayout { + anchors.fill: parent + + Item { + Layout.leftMargin: 5 + } + + Repeater { + model: 9 + Text { + // Live data from hyprland + property var ws: Hyprland.workspaces.values.find(w => w.id == index + 1) + property bool isActive: Hyprland.focusedWorkspace?.id == (index + 1) + + text: index + 1 + color: isActive ? root.colCyan : (ws ? root.colFg : root.colMuted) + font { + pixelSize: root.fontSize + family: root.fontFamily + bold: true + } + + MouseArea { + anchors.fill: parent + onClicked: Hyprland.dispatch("workspace " + (index + 1)) + } + } + } + + Item { + Layout.fillWidth: true + } + + Text { + text: "CPU: " + root.cpuUsage + "%" + color: root.colYellow + font { + pixelSize: root.fontSize + family: root.fontFamily + bold: true + } + } + + Rectangle { + width: 2 + height: 16 + color: root.colMuted + Layout.rightMargin: 4 + Layout.leftMargin: 4 + } + + Text { + text: "Mem: " + root.memUsage + "%" + color: root.colCyan + font { + family: root.fontFamily + pixelSize: root.fontSize + bold: true + } + } + + Rectangle { + width: 2 + height: 16 + color: root.colMuted + Layout.rightMargin: 4 + Layout.leftMargin: 4 + } + + Text { + id: clock + text: Qt.formatDateTime(new Date(), "ddd, MMM dd - HH:mm") + color: root.colBlue + font { + family: root.fontFamily + pixelSize: root.fontSize + bold: true + } + + Timer { + interval: 1000 + running: true + repeat: true + onTriggered: clock.text = Qt.formatDateTime(new Date(), "ddd, MMM dd - HH:mm") + } + } + + Item { + Layout.rightMargin: 5 + } + } +}