| 1 | pragma Singleton |
| 2 | import QtQuick |
| 3 | import Quickshell |
| 4 | import Quickshell.Io |
| 5 | |
| 6 | // pywal16 colours (~/.cache/wal/colors.json), hot-reloaded whenever `wal` runs. |
| 7 | Singleton { |
| 8 | id: root |
| 9 | |
| 10 | // ---- knobs -------------------------------------------------------- |
| 11 | property string font: "JetBrainsMono Nerd Font" // any Nerd Font mono |
| 12 | property int fontSize: 12 |
| 13 | property int wsFontSize: 11 // workspace icons only; everything else uses fontSize |
| 14 | property real panelAlpha: 0.88 |
| 15 | // your waybar uses @color14 for underlines/active workspace, so that is the default. |
| 16 | // set -1 to auto-pick the most vivid of color1..color6 instead |
| 17 | property int accentIndex: 14 |
| 18 | property int barHeight: 22 |
| 19 | property real barAlpha: 1.0 |
| 20 | |
| 21 | readonly property string walFile: Quickshell.env("HOME") + "/.cache/wal/colors.json" |
| 22 | |
| 23 | FileView { |
| 24 | path: root.walFile |
| 25 | watchChanges: true |
| 26 | onFileChanged: reload() |
| 27 | adapter: JsonAdapter { |
| 28 | id: wal |
| 29 | property JsonObject special: JsonObject { |
| 30 | property string background: "#0b1514" |
| 31 | property string foreground: "#cfe3df" |
| 32 | property string cursor: "#cfe3df" |
| 33 | } |
| 34 | property JsonObject colors: JsonObject { |
| 35 | property string color0: "#0b1514" |
| 36 | property string color1: "#c0616b" |
| 37 | property string color2: "#3fa593" |
| 38 | property string color3: "#7fb6a8" |
| 39 | property string color4: "#3a8f8a" |
| 40 | property string color5: "#5f9f9a" |
| 41 | property string color6: "#4fbfae" |
| 42 | property string color7: "#cfe3df" |
| 43 | property string color8: "#4a5f5c" |
| 44 | property string color9: "#d97a84" |
| 45 | property string color10: "#52c2ae" |
| 46 | property string color11: "#9ad0c3" |
| 47 | property string color12: "#4fb0a9" |
| 48 | property string color13: "#78b8b2" |
| 49 | property string color14: "#6fd6c5" |
| 50 | property string color15: "#e3f2ef" |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | readonly property var pal: [ |
| 56 | wal.colors.color0, wal.colors.color1, wal.colors.color2, wal.colors.color3, |
| 57 | wal.colors.color4, wal.colors.color5, wal.colors.color6, wal.colors.color7, |
| 58 | wal.colors.color8, wal.colors.color9, wal.colors.color10, wal.colors.color11, |
| 59 | wal.colors.color12, wal.colors.color13, wal.colors.color14, wal.colors.color15 |
| 60 | ] |
| 61 | |
| 62 | function mix(a, b, t) { |
| 63 | return Qt.rgba(a.r + (b.r - a.r) * t, a.g + (b.g - a.g) * t, a.b + (b.b - a.b) * t, 1) |
| 64 | } |
| 65 | |
| 66 | function autoAccent() { |
| 67 | var best = 4, score = -1 |
| 68 | for (var i = 1; i <= 6; i++) { |
| 69 | var c = Qt.color(pal[i]) |
| 70 | var s = c.hsvSaturation * c.hsvValue |
| 71 | if (s > score) { score = s; best = i } |
| 72 | } |
| 73 | return Qt.color(pal[best]) |
| 74 | } |
| 75 | |
| 76 | // ---- palette ------------------------------------------------------ |
| 77 | readonly property color bg: wal.special.background |
| 78 | readonly property color fg: wal.special.foreground |
| 79 | readonly property color accent: accentIndex >= 0 ? Qt.color(pal[accentIndex]) : autoAccent() |
| 80 | readonly property color accentDim: mix(bg, accent, 0.45) |
| 81 | readonly property color surface: mix(bg, fg, 0.06) |
| 82 | readonly property color surfaceHi: mix(bg, fg, 0.14) |
| 83 | readonly property color line: mix(bg, accent, 0.35) |
| 84 | readonly property color dim: mix(bg, fg, 0.55) |
| 85 | readonly property color err: Qt.color(pal[1]) |
| 86 | readonly property color barBg: Qt.rgba(bg.r, bg.g, bg.b, barAlpha) |
| 87 | readonly property color cursorC: wal.special.cursor |
| 88 | readonly property color bgA: Qt.rgba(bg.r, bg.g, bg.b, panelAlpha) |
| 89 | |
| 90 | // ---- Nerd Font (Material Design) glyphs --------------------------- |
| 91 | function cp(c) { |
| 92 | c -= 0x10000 |
| 93 | return String.fromCharCode(0xD800 + (c >> 10), 0xDC00 + (c & 0x3FF)) |
| 94 | } |
| 95 | readonly property string iHome: cp(0xF02DC) |
| 96 | readonly property string iVolHigh: cp(0xF057E) |
| 97 | readonly property string iVolMed: cp(0xF0580) |
| 98 | readonly property string iVolLow: cp(0xF057F) |
| 99 | readonly property string iVolOff: cp(0xF0581) |
| 100 | readonly property string iMic: cp(0xF036C) |
| 101 | readonly property string iMicOff: cp(0xF036D) |
| 102 | readonly property string iWifi: cp(0xF05A9) |
| 103 | readonly property string iWifiOff: cp(0xF05AA) |
| 104 | readonly property string iBt: cp(0xF00AF) |
| 105 | readonly property string iBtOff: cp(0xF00B2) |
| 106 | readonly property string iBtConn: cp(0xF00B1) |
| 107 | readonly property string iPower: cp(0xF0425) |
| 108 | readonly property string iClose: cp(0xF0156) |
| 109 | readonly property string iPrev: cp(0xF04AE) |
| 110 | readonly property string iNext: cp(0xF04AD) |
| 111 | readonly property string iPlay: cp(0xF040A) |
| 112 | readonly property string iPause: cp(0xF03E4) |
| 113 | readonly property string iBright: cp(0xF00DF) |
| 114 | readonly property string iLock: cp(0xF033E) |
| 115 | readonly property string iLogout: cp(0xF0343) |
| 116 | readonly property string iSleep: cp(0xF04B2) |
| 117 | readonly property string iReboot: cp(0xF0709) |
| 118 | readonly property string iRefresh: cp(0xF0450) |
| 119 | readonly property string iHeadphones: cp(0xF02CB) |
| 120 | readonly property string iSpeaker: cp(0xF04C3) |
| 121 | readonly property string iMusic: cp(0xF075A) |
| 122 | readonly property string iTrash: cp(0xF01B4) |
| 123 | readonly property string iCheck: cp(0xF012C) |
| 124 | readonly property string iMouse: cp(0xF037D) |
| 125 | readonly property string iKeyboard: cp(0xF030C) |
| 126 | readonly property string iPhone: cp(0xF011C) |
| 127 | readonly property string iGamepad: cp(0xF0297) |
| 128 | readonly property string iSearch: cp(0xF0349) |
| 129 | |
| 130 | readonly property string iHeadset: cp(0xF02CE) |
| 131 | readonly property string iCamera: cp(0xF0100) |
| 132 | readonly property string iCrop: cp(0xF019E) |
| 133 | readonly property string iWindow: cp(0xF05B0) |
| 134 | readonly property string iMonitor: cp(0xF0379) |
| 135 | readonly property string iSave: cp(0xF0193) |
| 136 | readonly property string iClipboard: cp(0xF0147) |
| 137 | readonly property string iBell: cp(0xF009A) |
| 138 | readonly property string iBellOff: cp(0xF009B) |
| 139 | readonly property string iChip: cp(0xF061A) |
| 140 | readonly property string iMem: cp(0xF035B) |
| 141 | readonly property string iDisk: cp(0xF02CA) |
| 142 | readonly property string iGpu: cp(0xF08AE) |
| 143 | readonly property string iLeaf: cp(0xF032A) |
| 144 | readonly property string iBalance: cp(0xF05D1) |
| 145 | readonly property string iSpeed: cp(0xF04C5) |
| 146 | readonly property string iCal: cp(0xF00ED) |
| 147 | readonly property string iClock: cp(0xF0954) |
| 148 | readonly property string iArch: cp(0xF08C7) |
| 149 | readonly property string iEthernet: cp(0xF0200) |
| 150 | readonly property string iPlug: cp(0xF06A5) |
| 151 | readonly property string iBatCharge: cp(0xF0084) |
| 152 | readonly property string iShuffle: cp(0xF049D) |
| 153 | readonly property string iImage: cp(0xF02E9) |
| 154 | |
| 155 | // workspace icons: the exact Font Awesome glyphs from your waybar config. |
| 156 | // 1 browser, 2 code, 3 book, 4 cog, 5 chat, 6 file, 7 folder, 8 terminal, 9 flask, 10 image |
| 157 | // 11-20 repeat the same ten, like your waybar format-icons did |
| 158 | readonly property var wsIcons: [ |
| 159 | String.fromCharCode(0xf269), String.fromCharCode(0xf121), String.fromCharCode(0xf02d), |
| 160 | String.fromCharCode(0xf085), String.fromCharCode(0xf086), String.fromCharCode(0xf1c9), |
| 161 | String.fromCharCode(0xf07c), String.fromCharCode(0xf120), String.fromCharCode(0xf0c3), |
| 162 | String.fromCharCode(0xf03e) |
| 163 | ] |
| 164 | function wsIcon(id) { return id >= 1 ? wsIcons[(id - 1) % 10] : String(id) } |
| 165 | |
| 166 | readonly property var batLevels: [0xF007A, 0xF007B, 0xF007C, 0xF007D, 0xF007E, |
| 167 | 0xF007F, 0xF0080, 0xF0081, 0xF0082, 0xF0079] |
| 168 | function batIcon(p, charging, plugged) { |
| 169 | if (charging) return iBatCharge |
| 170 | if (plugged) return iPlug |
| 171 | return cp(batLevels[Math.max(0, Math.min(9, Math.floor(p * 10)))]) |
| 172 | } |
| 173 | function fmtTime(s) { |
| 174 | if (!s || s <= 0) return "-" |
| 175 | var h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60) |
| 176 | return h > 0 ? h + "h " + m + "m" : m + "m" |
| 177 | } |
| 178 | |
| 179 | function volIcon(v, muted) { |
| 180 | if (muted || v <= 0) return iVolOff |
| 181 | return v < 0.34 ? iVolLow : (v < 0.67 ? iVolMed : iVolHigh) |
| 182 | } |
| 183 | function wifiIcon(sig) { |
| 184 | return cp(sig >= 75 ? 0xF0928 : sig >= 50 ? 0xF0925 : sig >= 25 ? 0xF0922 : 0xF091F) |
| 185 | } |
| 186 | } |