From f7d5a58bc654a26427b992d5c0f5aa74c5ea9990 Mon Sep 17 00:00:00 2001 From: tripleducky Date: Fri, 24 Oct 2025 21:32:46 -0600 Subject: [PATCH 1/5] updated bar to my preferences added volume widget systray launcher buttons --- simple-bar/README.md | 45 ++++++ simple-bar/modules/bar/Bar.qml | 34 ++++- simple-bar/modules/bar/LauncherButton.qml | 160 ++++++++++++++++++++++ simple-bar/modules/bar/Power.qml | 34 +++-- simple-bar/modules/bar/Systray.qml | 56 ++++++++ simple-bar/modules/bar/Time.qml | 25 +++- simple-bar/modules/bar/Volume.qml | 66 +++++++++ simple-bar/modules/bar/Workspaces.qml | 2 +- simple-bar/shell.qml | 2 + 9 files changed, 404 insertions(+), 20 deletions(-) create mode 100644 simple-bar/README.md create mode 100644 simple-bar/modules/bar/LauncherButton.qml create mode 100644 simple-bar/modules/bar/Systray.qml create mode 100644 simple-bar/modules/bar/Volume.qml diff --git a/simple-bar/README.md b/simple-bar/README.md new file mode 100644 index 0000000..336107f --- /dev/null +++ b/simple-bar/README.md @@ -0,0 +1,45 @@ +# simple-bar + +A minimal Quickshell bar with a system tray, time, battery, volume, and simple app launchers with single-instance focus. + +## Features +- Volume widget (PipeWire): mute on click, scroll to change, shows percent +- System tray: left/middle/right click actions, context menu displayed properly +- Time widget: 12-hour clock with date, implicit sizing for stable layout +- Battery widget (UPower): percentage with implicit sizing +- Launcher buttons: + - Nerd font icons + - Detects if an app is already open and focuses it instead of spawning + - If not open, launches detached via Quickshell.execDetached + +## Configure launchers +Edit `modules/bar/Bar.qml` and adjust the example loaders on the left side: + +``` +Loader { active: true; sourceComponent: LauncherButton { + icon: "" // nerd-font glyph + exec: "/usr/bin/alacritty" // command to start when not running + matchAppId: "alacritty" // used to detect existing windows + spawner: bar // use bar.spawn (execDetached) +}} +``` + +Tips: +- `matchAppId` is case-insensitive and matches substrings against multiple fields (Wayland toplevel appId and title; compositor fields like class/wmClass). +- If focusing doesn’t work at first, open the app and try a different token seen in its appId/class/title. Using the exact appId is usually best (e.g., `"Alacritty"`). +- Set `singleInstance: true` (default) to avoid duplicate instances when a match exists. + +## Spawn behavior +The bar prefers the documented Quickshell API: +- `Quickshell.execDetached(["sh", "-c", cmd])` to start processes detached +- Falls back to `niri.spawn(cmd)` if available + +No external helper is needed. + +## System tray +- Passes the bar window to tray menu display to satisfy platform menu requirements. +- Requires `//@ pragma UseQApplication` at the top of `shell.qml` (already set). + +## Notes +- Fonts: icons use "Symbols Nerd Font" and text uses "Barlow Medium"; adjust families to your installed fonts as needed. +- Layout: widgets use implicit sizing to prevent layout issues on startup. diff --git a/simple-bar/modules/bar/Bar.qml b/simple-bar/modules/bar/Bar.qml index 6102428..bd35f61 100644 --- a/simple-bar/modules/bar/Bar.qml +++ b/simple-bar/modules/bar/Bar.qml @@ -4,6 +4,23 @@ import Quickshell PanelWindow { id: bar + function spawn(cmd) { + try { + if (typeof Quickshell !== 'undefined' && typeof Quickshell.execDetached === 'function') { + // Use a shell to interpret the string command when necessary. + Quickshell.execDetached(["sh", "-c", cmd]); + return true; + } + // Fallback: attempt niri.spawn if provided by the compositor integration. + if (typeof niri !== 'undefined' && typeof niri.spawn === 'function') { + niri.spawn(cmd); + return true; + } + } catch (e) { + // ignore + } + return false; + } anchors { top: true left: true @@ -15,15 +32,22 @@ PanelWindow { Rectangle { anchors.fill: parent color: "#222222" - bottomLeftRadius: 20 - bottomRightRadius: 20 + bottomLeftRadius: 0 + bottomRightRadius: 0 + // left RowLayout { anchors { left: parent.left leftMargin: 25 } + spacing: 10 Loader { active: true; sourceComponent: Workspaces {} } + // Launchers: rely on Bar.spawn() -> Quickshell.execDetached to start commands detached. + Loader { active: true; sourceComponent: LauncherButton { icon: "󰖟"; exec: "/usr/bin/helium-browser"; matchAppId: "helium"; spawner: bar } } + Loader { active: true; sourceComponent: LauncherButton { icon: ""; exec: "/usr/bin/alacritty"; matchAppId: "alacritty"; spawner: bar } } + Loader { active: true; sourceComponent: LauncherButton { icon: ""; exec: "/usr/bin/dolphin"; matchAppId: "dolphin"; spawner: bar } } + Loader { active: true; sourceComponent: LauncherButton { icon: "󱩽"; exec: "/usr/bin/gedit"; matchAppId: "gedit"; spawner: bar } } } // center RowLayout { @@ -33,7 +57,7 @@ PanelWindow { } Text { - text: niri.focusedWindowTitle + text: (typeof niri !== 'undefined' && typeof niri.focusedWindowTitle === 'string') ? niri.focusedWindowTitle : "" font.family: "Barlow Medium" font.pixelSize: 16 color: "#999999" @@ -46,7 +70,9 @@ PanelWindow { right: parent.right rightMargin: 25 } - spacing: 10 + spacing: 20 + Loader { active: true; sourceComponent: Systray { window: bar } } + Loader { active: true; sourceComponent: Volume {} } Loader { active: true; sourceComponent: Power {} } Loader { active: true; sourceComponent: Time {} } } diff --git a/simple-bar/modules/bar/LauncherButton.qml b/simple-bar/modules/bar/LauncherButton.qml new file mode 100644 index 0000000..ef0896d --- /dev/null +++ b/simple-bar/modules/bar/LauncherButton.qml @@ -0,0 +1,160 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Wayland as Wayland + +Item { + id: root + property alias icon: iconText.text + property string exec: "" // command to run when not open + property string matchAppId: "" // app id or wm-class to detect running windows + property int iconSize: 16 + property var spawner: undefined // optional object (e.g. the bar) with a spawn/spawnCommand method + // If true, never spawn a new instance when a matching window exists; instead just try to focus. + // If focusing fails, do nothing (prevents duplicate instances). + property bool singleInstance: true + + // Uniform cell sizing so icons align evenly regardless of glyph width + property int padding: 1 + property int cellWidth: iconSize + padding * 2 + width: cellWidth + height: Math.max(iconSize + padding * 2, iconText.implicitHeight + padding * 2) + Layout.preferredWidth: width + Layout.preferredHeight: height + + // Nerd-font icon text representing the app + Text { + id: iconText + text: "?" // replace with nerd font char via `icon` property + font.family: "Symbols Nerd Font" + font.pixelSize: root.iconSize + color: isOpen ? "#c4a912" : "#dac878" + anchors.centerIn: parent + } + + // Determine if a matching window is open by checking Wayland toplevels first, + // then compositor-specific collections (niri) as a fallback. + property bool isOpen: { + try { + var wins = listCandidates(); + for (var k=0;k 0) return out; + } + // Fallback: niri-provided windows + if (typeof niri !== 'undefined') { + if (niri.windows) return niri.windows; + if (niri.clients) return niri.clients; + if (niri.workspaces) { + for (var i=0;i 0) { + try { + // Prefer a provided spawner object (e.g. the bar) so we don't rely on environment globals + if (root.spawner && typeof root.spawner.spawn === 'function' && root.spawner.spawn(root.exec)) return; + if (typeof Quickshell !== 'undefined' && typeof Quickshell.execDetached === 'function') { + Quickshell.execDetached(["sh", "-c", root.exec]); + return; + } else if (typeof niri !== 'undefined' && typeof niri.spawn === 'function') { + niri.spawn(root.exec); + return; + } else { + // No spawn method available + } + } catch(e) { + // ignore + } + } + } + } +} diff --git a/simple-bar/modules/bar/Power.qml b/simple-bar/modules/bar/Power.qml index a91140b..48c5aa6 100644 --- a/simple-bar/modules/bar/Power.qml +++ b/simple-bar/modules/bar/Power.qml @@ -4,17 +4,31 @@ import Quickshell import Quickshell.Services.UPower Rectangle { - Text { - id: powerDisplay - anchors { - verticalCenter: parent.verticalCenter + // Keep background transparent so it doesn't show a white box behind the text + color: "transparent" + Row { + id: powerRow + anchors.verticalCenter: parent.verticalCenter + spacing: 6 + + Text { + id: powerIcon + text: "󰄌" + color: "#999999" + font.pixelSize: 16 + // Leave font.family unset so icon glyph can come from an icon/nerd font via fallback. } - text: Number(UPower.displayDevice.percentage * 100).toFixed(2) + "%" - color: "#999999" - font.family: "Barlow Medium" - font.pixelSize: 16 - Component.onCompleted: { - parent.width = powerDisplay.contentWidth + + Text { + id: powerPercent + text: Number(UPower.displayDevice.percentage * 100).toFixed(0) + "%" + color: "#999999" + font.family: "Barlow Medium" + font.pixelSize: 16 } } + + // Bind the Rectangle size to the row content so layout spacing is consistent + implicitWidth: powerRow.implicitWidth + implicitHeight: powerRow.implicitHeight } diff --git a/simple-bar/modules/bar/Systray.qml b/simple-bar/modules/bar/Systray.qml new file mode 100644 index 0000000..8107d2f --- /dev/null +++ b/simple-bar/modules/bar/Systray.qml @@ -0,0 +1,56 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import Quickshell +import Quickshell.Services.SystemTray + +// Minimal system tray row; shows icons and opens menus with the bar window context +RowLayout { + // The window the bar lives in; required for showing platform menus + required property var window + spacing: 8 + + Repeater { + model: SystemTray.items + + Item { + required property SystemTrayItem modelData + + implicitWidth: 20 + implicitHeight: 20 + + Image { + anchors.fill: parent + source: modelData.icon + fillMode: Image.PreserveAspectFit + smooth: true + } + + MouseArea { + id: mouseArea + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton + hoverEnabled: true + + onClicked: function(mouse) { + if (mouse.button === Qt.LeftButton) { + modelData.activate(); + } else if (mouse.button === Qt.RightButton) { + if (modelData.menu && window) { + // Map local coordinates into window coordinates + var pos = mouseArea.mapToItem(window.contentItem, 0, mouseArea.height); + modelData.display(window, pos.x, pos.y); + } + } else if (mouse.button === Qt.MiddleButton) { + modelData.secondaryActivate(); + } + } + + onWheel: function(wheel) { modelData.scroll(wheel.angleDelta.y / 120, "vertical"); } + + ToolTip.visible: containsMouse && (modelData.tooltip?.title !== undefined && modelData.tooltip?.title !== "") + ToolTip.text: modelData.tooltip?.title ?? "" + } + } + } +} diff --git a/simple-bar/modules/bar/Time.qml b/simple-bar/modules/bar/Time.qml index 5ea2487..03172fe 100644 --- a/simple-bar/modules/bar/Time.qml +++ b/simple-bar/modules/bar/Time.qml @@ -3,6 +3,8 @@ import QtQuick.Layouts import Quickshell Rectangle { + // Make the background transparent so the parent bar color shows through + color: "transparent" SystemClock { id: clock precision: SystemClock.Seconds @@ -12,12 +14,25 @@ Rectangle { anchors { verticalCenter: parent.verticalCenter } - text: Qt.formatDateTime(clock.date, "hh:mm dd MMM, yyyy") - color: "#666666" + text: { + var d = clock.date; + if (!d) return ""; + var hours = d.getHours(); + var ampm = hours >= 12 ? "PM" : "AM"; + var h = hours % 12; + if (h === 0) h = 12; + var mins = d.getMinutes(); + var minsStr = mins < 10 ? "0" + mins : mins; + return h + ":" + minsStr + " " + ampm + " " + Qt.formatDate(d, "dd MMM, yyyy"); + } + color: "#c4a912" font.family: "Barlow Medium" font.pixelSize: 16 - Component.onCompleted: { - parent.width = timeBlock.contentWidth - } + // Use implicit sizing so the parent Rectangle's size follows the text + // Binding to contentWidth/contentHeight ensures the layout updates + // when fonts or the clock become available (avoids race at startup). } + + implicitWidth: timeBlock.contentWidth + implicitHeight: timeBlock.contentHeight } diff --git a/simple-bar/modules/bar/Volume.qml b/simple-bar/modules/bar/Volume.qml new file mode 100644 index 0000000..6ac354d --- /dev/null +++ b/simple-bar/modules/bar/Volume.qml @@ -0,0 +1,66 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Services.Pipewire + +Item { + PwObjectTracker { + objects: [Pipewire.defaultAudioSink] + } + + property var sink: Pipewire.defaultAudioSink + property real volume: sink?.audio?.volume ?? 0 + property bool muted: sink?.audio?.muted ?? false + + implicitWidth: volumeLayout.implicitWidth + implicitHeight: volumeLayout.implicitHeight + + RowLayout { + id: volumeLayout + anchors.fill: parent + spacing: 6 + + // Icon + Text { + text: muted ? "" : "󰕾" // Mute icon when muted, volume icon otherwise + color: "#999999" + font.family: "Symbols Nerd Font" + font.pixelSize: 16 + } + + // Percent text + Text { + text: { + var vol = Number(volume); + if (isNaN(vol) || !isFinite(vol)) { + return "0%"; + } + return Math.round(vol * 100) + "%"; + } + color: muted ? "#ff0000" : "#999999" + font.family: "Barlow Medium" + font.pixelSize: 16 + } + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + + onClicked: { + if (sink && sink.audio) { + sink.audio.muted = !sink.audio.muted; + } + } + + onWheel: function(wheel) { + if (sink && sink.audio) { + var delta = wheel.angleDelta.y / 120; // Standard wheel delta + var newVolume = volume + (delta * 0.05); // Change by 5% per scroll step + newVolume = Math.max(0, Math.min(1.5, newVolume)); // Clamp between 0 and 1 + sink.audio.volume = newVolume; + } + } + } +} \ No newline at end of file diff --git a/simple-bar/modules/bar/Workspaces.qml b/simple-bar/modules/bar/Workspaces.qml index f5d9ae9..512583d 100644 --- a/simple-bar/modules/bar/Workspaces.qml +++ b/simple-bar/modules/bar/Workspaces.qml @@ -34,7 +34,7 @@ Rectangle { width: 15 height: 15 radius: 10 - color: model.isActive ? "#000000" : "#333333" + color: model.isActive ? "#c4a912" : "#dac878" MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor diff --git a/simple-bar/shell.qml b/simple-bar/shell.qml index 4810544..af5b7b7 100644 --- a/simple-bar/shell.qml +++ b/simple-bar/shell.qml @@ -1,3 +1,5 @@ +//@ pragma UseQApplication + import QtQuick import QtQuick.Layouts import Quickshell From 736703a502d30b2e1cf945781404891f7e6cc752 Mon Sep 17 00:00:00 2001 From: tripleducky Date: Fri, 24 Oct 2025 21:56:01 -0600 Subject: [PATCH 2/5] Create Screenshot_20251024_211907.png --- Screenshot_20251024_211907.png | Bin 0 -> 33337 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Screenshot_20251024_211907.png diff --git a/Screenshot_20251024_211907.png b/Screenshot_20251024_211907.png new file mode 100644 index 0000000000000000000000000000000000000000..b7d262fe2a518578a9abf64604e2233067cdc1a9 GIT binary patch literal 33337 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 Date: Fri, 24 Oct 2025 21:58:54 -0600 Subject: [PATCH 3/5] Revise README with updated project details Updated README.md to reflect changes in project description, setup instructions, and usage examples. --- README.md | 58 +++++++++++++------------------------------------------ 1 file changed, 13 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index cc998c1..996b432 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,18 @@ -## quickshell-niri +a fork of the simple-bar for -This project contains examples of [Quickshell](https://quickshell.outfoxxed.me/) configuration for the [niri](https://github.com/YaLTeR/niri) Wayland compositor, using the [QML plugin for niri](https://github.com/imiric/qml-niri). +https://github.com/imiric/quickshell-niri +includes: + 1. volume widget + 2. system tray + 3. buttons intended to be used for launching specific programs -### Setup +requirements: +1. quickshell +2. https://github.com/imiric/qml-niri +3. nerd font symbols + on arch: sudo pacman -S ttf-nerd-fonts-symbols -1. Install Quickshell version >=0.2.1, and niri version >=25.08. +it looks like this: -2. [Install the QML plugin for niri.](https://github.com/imiric/qml-niri#installation) - -3. For specific widgets: - - Battery: [UPower](https://upower.freedesktop.org/) - -4. Fonts/icons: [Barlow](https://tribby.com/fonts/barlow/) - - -### Usage - -Clone this repository, and copy or symlink any of the examples into `~/.config/quickshell/`. E.g.: -```shell -git clone https://github.com/imiric/quickshell-niri.git -ln -s "$PWD/quickshell-niri/simple-bar" ~/.config/quickshell/niri-simple-bar -``` - -Then you can run Quickshell with the specific configuration: -```shell -quickshell --config niri-simple-bar -``` - -You can run this automatically when niri starts by adding this to your niri configuration file (`~/.config/niri/config.kdl`): -```kdl -spawn-at-startup "quickshell" "--config" "niri-simple-bar" -``` - - -### Examples - -#### [Simple bar](/simple-bar) - -![Simple bar](/assets/simple-bar.png) - -A plain bar with a workspace indicator and switcher, centered title of the currently focused window, and text battery and date/time widgets. - -This is a slightly modified version of [SimpleQuickshellBar](https://github.com/the-ink-serpent/SimpleQuickshellBar), but for niri instead of Hyprland. - - -## License - -[MIT](/LICENSE) +![screenshot of simple bar with goodies](https://github.com/tripleducky/quickshell-niri-bar-with-goodies/blob/main/Screenshot_20251024_211907.png) From 53730f53b61434c9ac23f0e4e9e6f3082f3924ba Mon Sep 17 00:00:00 2001 From: tripleducky Date: Fri, 24 Oct 2025 21:59:32 -0600 Subject: [PATCH 4/5] Delete fancy-bar directory --- fancy-bar/config.json | 7 - fancy-bar/modules/bar/Bar.qml | 111 ------------- fancy-bar/modules/bar/Battery.qml | 86 ---------- fancy-bar/modules/bar/DateTime.qml | 116 ------------- fancy-bar/modules/bar/FocusedWindow.qml | 35 ---- fancy-bar/modules/bar/Workspaces.qml | 48 ------ fancy-bar/modules/common/Config.qml | 104 ------------ fancy-bar/modules/common/Types.qml | 70 -------- fancy-bar/modules/common/utils/ColorUtils.qml | 130 --------------- .../common/widgets/ProgressBarText.qml | 156 ------------------ fancy-bar/modules/icons/BatteryIcon.qml | 89 ---------- fancy-bar/services/Battery.qml | 56 ------- fancy-bar/services/Niri.qml | 14 -- fancy-bar/shell.qml | 18 -- 14 files changed, 1040 deletions(-) delete mode 100644 fancy-bar/config.json delete mode 100644 fancy-bar/modules/bar/Bar.qml delete mode 100644 fancy-bar/modules/bar/Battery.qml delete mode 100644 fancy-bar/modules/bar/DateTime.qml delete mode 100644 fancy-bar/modules/bar/FocusedWindow.qml delete mode 100644 fancy-bar/modules/bar/Workspaces.qml delete mode 100644 fancy-bar/modules/common/Config.qml delete mode 100644 fancy-bar/modules/common/Types.qml delete mode 100644 fancy-bar/modules/common/utils/ColorUtils.qml delete mode 100644 fancy-bar/modules/common/widgets/ProgressBarText.qml delete mode 100644 fancy-bar/modules/icons/BatteryIcon.qml delete mode 100644 fancy-bar/services/Battery.qml delete mode 100644 fancy-bar/services/Niri.qml delete mode 100644 fancy-bar/shell.qml diff --git a/fancy-bar/config.json b/fancy-bar/config.json deleted file mode 100644 index 12e12ee..0000000 --- a/fancy-bar/config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "theme": { - "font": { - "family": "Barlow Medium" - } - } -} diff --git a/fancy-bar/modules/bar/Bar.qml b/fancy-bar/modules/bar/Bar.qml deleted file mode 100644 index a692f38..0000000 --- a/fancy-bar/modules/bar/Bar.qml +++ /dev/null @@ -1,111 +0,0 @@ -import QtQuick -import QtQuick.Effects -import QtQuick.Layouts -import Quickshell -import Quickshell.Wayland -import qs.modules.common - -Item { - id: root - property int position: Types.Position.Top - property string color: "gray" - property int size: 30 - - WlrLayershell { - id: barShadow - implicitHeight: bar.height + 100 - color: "transparent" - layer: WlrLayer.Bottom - exclusiveZone: 0 - anchors: bar.anchors - - Rectangle { - color: barContent.color - anchors { - top: root.position === Types.Position.Top ? parent.top : undefined - bottom: root.position === Types.Position.Bottom ? parent.bottom : undefined - } - height: barContent.height - // The +40 here and the -20 shadowHorizontalOffset are to have the - // shadow extend all the way along the edge. Otherwise it would be - // slightly cut off at the left and right corners. - width: parent.width + 40 - - layer.enabled: true - layer.effect: MultiEffect { - shadowEnabled: true - // The vertical offset makes the shadow slightly more prominent - shadowVerticalOffset: root.position === Types.Position.Top ? 5 : -5 - shadowHorizontalOffset: -20 - shadowBlur: 1 - blurMultiplier: 1.5 - shadowColor: "#C0000000" - } - } - } - - PanelWindow { - id: bar - implicitHeight: root.size - color: "transparent" - anchors { - top: root.position === Types.Position.Top - bottom: root.position === Types.Position.Bottom - left: true - right: true - } - - Rectangle { - id: barContent - anchors.fill: parent - color: root.color - - RowLayout { - id: leftLayout - anchors { - left: parent.left - leftMargin: 25 - } - Loader { active: Config.data.workspaces.enabled; sourceComponent: Workspaces {} } - } - - RowLayout { - id: centerLayout - - anchors { - left: leftLayout.right - leftMargin: 5 - verticalCenter: parent.verticalCenter - } - Loader { active: Config.data.focusedWindow.enabled; sourceComponent: FocusedWindow {} } - - } - - RowLayout { - id: rightLayout - - anchors { - verticalCenter: parent.verticalCenter - right: parent.right - rightMargin: 25 - } - spacing: 10 - Loader { - active: Config.data.battery.enabled - sourceComponent: Battery { - orientation: Types.stringToOrientation(Config.data.battery.orientation) - } - } - Loader { - active: Config.data.datetime.enabled - sourceComponent: DateTime { - size: Math.min( - root.size * Config.data.datetime.scale - root.size * 0.2, - root.size - ) - } - } - } - } - } -} diff --git a/fancy-bar/modules/bar/Battery.qml b/fancy-bar/modules/bar/Battery.qml deleted file mode 100644 index 55dccbc..0000000 --- a/fancy-bar/modules/bar/Battery.qml +++ /dev/null @@ -1,86 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import Qt5Compat.GraphicalEffects -import Quickshell -import qs.modules.common -import qs.modules.common.widgets -import qs.modules.icons -import qs.services - -MouseArea { - id: root - - property int orientation: Types.Orientation.Horizontal - property real size: 1 - - readonly property var chargeState: Battery.chargeState - readonly property bool isCharging: Battery.isCharging - readonly property bool isPluggedIn: Battery.isPluggedIn - readonly property real percentage: Battery.percentage - readonly property bool isLow: percentage <= Config.data.battery.low / 100 - readonly property bool isCritical: percentage <= Config.data.battery.critical / 100 - - implicitWidth: batteryProgress.implicitWidth - - hoverEnabled: true - - ProgressBarText { - id: batteryProgress - anchors { - left: icon.left - bottom: icon.bottom - } - valueBarWidth: icon.bodyWidth - valueBarHeight: icon.bodyHeight - value: percentage - text: Config.data.battery.showPercentage ? Math.round(value * 100) : "" - orientation: root.orientation - shimmer: isCharging - pulse: isCharging - highlightColor: (() => { - if (isCritical && !isCharging) { - return Config.data.theme.color.error; - } - if (isLow && !isCharging) { - return Config.data.theme.color.warning; - } - return Config.data.theme.color.ok; - })() - font.family: "Noto Sans" - font.pixelSize: 14 - textColor: Config.data.theme.color.foreground - - // Clip the progress bar within the borders of the battery icon body - layer.enabled: true - layer.effect: OpacityMask { - maskSource: Item { - width: batteryProgress.width - height: batteryProgress.height - - Rectangle { - x: icon.borderWidth - y: icon.borderWidth - width: icon.bodyWidth - icon.borderWidth * 2 - height: icon.bodyHeight - icon.borderWidth * 2 - radius: icon.bodyRadius / 2 - } - } - } - } - - BatteryIcon { - id: icon - anchors.centerIn: parent - size: Math.min(Config.data.battery.scale * Config.data.theme.widget.size, - Config.data.bar.size) - iconColor: Config.data.theme.color.foreground - orientation: root.orientation - } - - /* - BatteryPopup { - id: batteryPopup - hoverTarget: root - } - */ -} diff --git a/fancy-bar/modules/bar/DateTime.qml b/fancy-bar/modules/bar/DateTime.qml deleted file mode 100644 index e8ebde6..0000000 --- a/fancy-bar/modules/bar/DateTime.qml +++ /dev/null @@ -1,116 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import Quickshell -import qs.modules.common - -// DateTime component that displays time and date in a vertically stacked -// layout, with both blocks horizontally centered along the same axis. The width -// and height of the blocks is dynamically determined to avoid layout shifting -// with proportional fonts as digits change, and to make the shorter block -// slightly larger to compensate. -Item { - id: root - property real size: 1 - - SystemClock { - id: clock - precision: SystemClock.Seconds - } - - implicitWidth: contentItem.implicitWidth - implicitHeight: size - - // Fixed-width blocks used as width references for the actual time and date blocks. - // The reference isn't perfect, but should look good in most cases. - TextMetrics { - id: timeMetrics - font: timeBlock.font - text: Qt.formatDateTime(new Date(2000, 12, 30, 23, 59, 59), - Config.data.datetime.time.format || "hh:mm") - } - - TextMetrics { - id: dateMetrics - font: dateBlock.font - text: Qt.formatDateTime(new Date(2000, 12, 30), - Config.data.datetime.date.format || "yyyy-MM-dd") - } - - ColumnLayout { - id: contentItem - anchors.centerIn: parent - width: Math.max(timeBlock.Layout.preferredWidth, dateBlock.Layout.preferredWidth) - height: parent.height - spacing: gapSize - - Text { - id: timeBlock - Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: (root.size - gapSize) / 2 - Layout.preferredWidth: timeMetrics.advanceWidth - - text: Qt.formatDateTime(clock.date, Config.data.datetime.time.format || "hh:mm") - font.family: Config.data.datetime.font.family || Config.data.theme.font.family - font.pixelSize: baseFontSize * timeScale - font.weight: Config.data.datetime.font.weight - color: Config.data.theme.color.textMuted - visible: Config.data.datetime.time.enabled !== false - verticalAlignment: Text.AlignVCenter - } - - Text { - id: dateBlock - Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: (root.size - gapSize) / 2 - Layout.preferredWidth: dateMetrics.advanceWidth - - text: Qt.formatDateTime(clock.date, Config.data.datetime.date.format || "yyyy-MM-dd") - font.family: Config.data.datetime.font.family || Config.data.theme.font.family - font.pixelSize: baseFontSize * dateScale - font.weight: Config.data.datetime.font.weight - color: Config.data.theme.color.textMuted - visible: Config.data.datetime.date.enabled !== false - verticalAlignment: Text.AlignVCenter - } - } - - readonly property real baseFontSize: { - (timeBlock.visible && dateBlock.visible ? 0.5 : 1) - * size * Config.data.datetime.font.scale - } - readonly property real maxBlockHeight: size - gapSize - readonly property real gapSize: size * 0.1 - property real timeScale: 1 - property real dateScale: 1 - - Component.onCompleted: { - if (!timeBlock.visible || !dateBlock.visible) return; - - const timeWidth = timeBlock.contentWidth; - const dateWidth = dateBlock.contentWidth; - - // Give narrower block a boost - let targetTimeScale = dateWidth > timeWidth ? 1.3 : 1; - let targetDateScale = timeWidth > dateWidth ? 1.3 : 1; - - timeScale = targetTimeScale; - dateScale = targetDateScale; - - // Scale down if either block is too tall - if (timeBlock.contentHeight > maxBlockHeight) { - timeScale *= maxBlockHeight / timeBlock.contentHeight; - } - if (dateBlock.contentHeight > maxBlockHeight) { - dateScale *= maxBlockHeight / dateBlock.contentHeight; - } - - // Ensure scaled block doesn't exceed the widest block's width - const maxWidth = Math.max(timeWidth, dateWidth); - if (timeBlock.contentWidth > maxWidth) { - timeScale *= maxWidth / timeBlock.contentWidth; - } - if (dateBlock.contentWidth > maxWidth) { - dateScale *= maxWidth / dateBlock.contentWidth; - } - } -} diff --git a/fancy-bar/modules/bar/FocusedWindow.qml b/fancy-bar/modules/bar/FocusedWindow.qml deleted file mode 100644 index 81b8f77..0000000 --- a/fancy-bar/modules/bar/FocusedWindow.qml +++ /dev/null @@ -1,35 +0,0 @@ -import QtQuick -import qs.modules.common -import qs.services - -Row { - spacing: 5 - Image { - anchors.verticalCenter: parent.verticalCenter - source: Niri.focusedWindow?.iconPath ? "file://" + Niri.focusedWindow?.iconPath : "" - sourceSize.width: Config.data.focusedWindow.icon.scale * Config.data.theme.widget.size - sourceSize.height: Config.data.focusedWindow.icon.scale * Config.data.theme.widget.size - visible: Config.data.focusedWindow.icon.enabled && Niri.focusedWindow?.iconPath !== "" - smooth: true - } - - // Fallback for missing icons - Rectangle { - anchors.verticalCenter: parent.verticalCenter - width: Config.data.focusedWindow.icon.scale * Config.data.theme.widget.size - height: Config.data.focusedWindow.icon.scale * Config.data.theme.widget.size - color: "#CCC" - visible: Config.data.focusedWindow.icon.enabled && Niri.focusedWindow?.iconPath === "" - radius: 12 - } - - Text { - anchors.verticalCenter: parent.verticalCenter - text: Niri.focusedWindow?.title ?? "" - font.family: Config.data.focusedWindow.font.family || Config.data.theme.font.family - font.pixelSize: Config.data.focusedWindow.font.scale * Config.data.theme.font.size - font.weight: Config.data.focusedWindow.font.weight - color: Config.data.theme.color.text - visible: Config.data.focusedWindow.title.enabled - } -} diff --git a/fancy-bar/modules/bar/Workspaces.qml b/fancy-bar/modules/bar/Workspaces.qml deleted file mode 100644 index 3e4b8f3..0000000 --- a/fancy-bar/modules/bar/Workspaces.qml +++ /dev/null @@ -1,48 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import Quickshell -import qs.modules.common -import qs.services - -Rectangle { - anchors.left: parent.left - color: Config.data.theme.color.background2 - height: 25 - width: 215 - bottomLeftRadius: 10 - bottomRightRadius: 10 - - Rectangle { - anchors { - verticalCenter: parent.verticalCenter - left: parent.left - right: parent.right - leftMargin: 10 - rightMargin: 10 - } - - RowLayout { - anchors { - verticalCenter: parent.verticalCenter - } - spacing: 5 - - Repeater { - model: Niri.workspaces - - Rectangle { - visible: index < 11 - width: Config.data.workspaces.icon.scale * Config.data.theme.widget.size - height: Config.data.workspaces.icon.scale * Config.data.theme.widget.size - radius: Config.data.workspaces.icon.scale * Config.data.theme.widget.size * Config.data.workspaces.icon.radius - color: model.isActive ? Config.data.theme.color.active : Config.data.theme.color.inactive - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: Niri.focusWorkspaceById(model.id) - } - } - } - } - } -} diff --git a/fancy-bar/modules/common/Config.qml b/fancy-bar/modules/common/Config.qml deleted file mode 100644 index b151e1d..0000000 --- a/fancy-bar/modules/common/Config.qml +++ /dev/null @@ -1,104 +0,0 @@ -pragma Singleton -import Quickshell -import Quickshell.Io -import qs.modules.common - -Singleton { - property var data: adapter - - FileView { - path: Quickshell.shellPath("config.json") - watchChanges: true - onFileChanged: reload() - onAdapterUpdated: writeAdapter() - - JsonAdapter { - id: adapter - - // Global theme. Source of default and base values for all components. - property JsonObject theme: JsonObject { - property JsonObject color: JsonObject { - property string active: "#000000" - property string inactive: "#333333" - property string text: "#999999" - property string textMuted: "#777777" - property string foreground: "#999999" - property string background: "#222222" - property string background2: "#666666" - property string ok: "#1A7F39" - property string error: "#E5002E" - property string warning: "#E5BF00" - } - property JsonObject font: JsonObject { - property string family: "Sans" - // Size in pixels of all fonts. The actual size of fonts in - // individual components will be proportial to this value. - property real size: 14 - } - property JsonObject widget: JsonObject { - // Size in pixels of all widgets. The actual size of - // individual widgets will be proportial to this value. - property real size: 24 - } - } - - property JsonObject bar: JsonObject { - property string position: Types.positionToString(Types.Position.Top) - property int size: 30 - } - - property JsonObject focusedWindow: JsonObject { - property bool enabled: true - property JsonObject icon: JsonObject { - property bool enabled: true - property real scale: 1 - } - property JsonObject title: JsonObject { - property bool enabled: true - } - property JsonObject font: JsonObject { - property string family - property real scale: 1.2 - property int weight: 600 - } - } - - property JsonObject battery: JsonObject { - property bool enabled: true - property real scale: 1.5 - property int low: 20 - property int critical: 10 - property int suspend: 5 - property bool automaticSuspend: true - property bool showPercentage: true - property string orientation: Types.orientationToString(Types.Orientation.Horizontal) - } - - property JsonObject datetime: JsonObject { - property bool enabled: true - property real scale: 1 - property JsonObject time: JsonObject { - property bool enabled: true - property string format: "hh:mm" - } - property JsonObject date: JsonObject { - property bool enabled: true - property string format: "yyyy-MM-dd" - } - property JsonObject font: JsonObject { - property string family - property real scale: 1.1 - property int weight: 400 - } - } - - property JsonObject workspaces: JsonObject { - property bool enabled: true - property JsonObject icon: JsonObject { - property real scale: 0.6 - property real radius: 1 - } - } - } - } -} diff --git a/fancy-bar/modules/common/Types.qml b/fancy-bar/modules/common/Types.qml deleted file mode 100644 index 12131d3..0000000 --- a/fancy-bar/modules/common/Types.qml +++ /dev/null @@ -1,70 +0,0 @@ -pragma Singleton -import QtQuick - -QtObject { - enum Orientation { - Horizontal, - Vertical - } - - enum Position { - Top, - Bottom - } - - /** - * I would prefer to use stdlib enum conversion functions: - * https://doc.qt.io/qt-6/qtqml-typesystem-enumerations.html - * But these aren't defined in Quickshell v0.2.1, for some reason, even - * though it does use Qt 6.10... - */ - function stringToOrientation(str) { - const normalized = str.toLowerCase(); - switch (normalized) { - case "horizontal": - return Types.Orientation.Horizontal; - case "vertical": - return Types.Orientation.Vertical; - default: - console.error("Error: invalid Orientation value:", str) - return -1; - } - } - - function orientationToString(value) { - switch (value) { - case Types.Orientation.Horizontal: - return "horizontal" - case Types.Orientation.Vertical: - return "vertical" - default: - console.error("Error: invalid Orientation value:", value) - return ""; - } - } - - function stringToPosition(str) { - const normalized = str.toLowerCase(); - switch (normalized) { - case "top": - return Types.Position.Top; - case "bottom": - return Types.Position.Bottom; - default: - console.error("Error: invalid Position value:", str) - return -1; - } - } - - function positionToString(value) { - switch (value) { - case Types.Position.Top: - return "top" - case Types.Position.Bottom: - return "bottom" - default: - console.error("Error: invalid Position value:", value) - return ""; - } - } -} diff --git a/fancy-bar/modules/common/utils/ColorUtils.qml b/fancy-bar/modules/common/utils/ColorUtils.qml deleted file mode 100644 index 795757e..0000000 --- a/fancy-bar/modules/common/utils/ColorUtils.qml +++ /dev/null @@ -1,130 +0,0 @@ -pragma Singleton -import Quickshell - -/* - Copied from https://github.com/end-4/dots-hyprland/blob/449df7f161e6435569bc7d9499b2e444dd8aa153/dots/.config/quickshell/ii/modules/common/functions/ColorUtils.qml -*/ -Singleton { - id: root - - /** - * Returns a color with the hue of color2 and the saturation, value, and alpha of color1. - * - * @param {string} color1 - The base color (any Qt.color-compatible string). - * @param {string} color2 - The color to take hue from. - * @returns {Qt.rgba} The resulting color. - */ - function withHueOf(color1, color2) { - var c1 = Qt.color(color1); - var c2 = Qt.color(color2); - - // Qt.color hsvHue/hsvSaturation/hsvValue/alpha return 0-1 - var hue = c2.hsvHue; - var sat = c1.hsvSaturation; - var val = c1.hsvValue; - var alpha = c1.a; - - return Qt.hsva(hue, sat, val, alpha); - } - - /** - * Returns a color with the saturation of color2 and the hue/value/alpha of color1. - * - * @param {string} color1 - The base color (any Qt.color-compatible string). - * @param {string} color2 - The color to take saturation from. - * @returns {Qt.rgba} The resulting color. - */ - function withSaturationOf(color1, color2) { - var c1 = Qt.color(color1); - var c2 = Qt.color(color2); - - var hue = c1.hsvHue; - var sat = c2.hsvSaturation; - var val = c1.hsvValue; - var alpha = c1.a; - - return Qt.hsva(hue, sat, val, alpha); - } - - /** - * Returns a color with the given lightness and the hue, saturation, and alpha of the input color (using HSL). - * - * @param {string} color - The base color (any Qt.color-compatible string). - * @param {number} lightness - The lightness value to use (0-1). - * @returns {Qt.rgba} The resulting color. - */ - function withLightness(color, lightness) { - var c = Qt.color(color); - return Qt.hsla(c.hslHue, c.hslSaturation, lightness, c.a); - } - - /** - * Returns a color with the lightness of color2 and the hue, saturation, and alpha of color1 (using HSL). - * - * @param {string} color1 - The base color (any Qt.color-compatible string). - * @param {string} color2 - The color to take lightness from. - * @returns {Qt.rgba} The resulting color. - */ - function withLightnessOf(color1, color2) { - var c2 = Qt.color(color2); - return colorWithLightness(color1, c2.hslLightness); - } - - /** - * Adapts color1 to the accent (hue and saturation) of color2 using HSL, keeping lightness and alpha from color1. - * - * @param {string} color1 - The base color (any Qt.color-compatible string). - * @param {string} color2 - The accent color. - * @returns {Qt.rgba} The resulting color. - */ - function adaptToAccent(color1, color2) { - var c1 = Qt.color(color1); - var c2 = Qt.color(color2); - - var hue = c2.hslHue; - var sat = c2.hslSaturation; - var light = c1.hslLightness; - var alpha = c1.a; - - return Qt.hsla(hue, sat, light, alpha); - } - - /** - * Mixes two colors by a given percentage. - * - * @param {string} color1 - The first color (any Qt.color-compatible string). - * @param {string} color2 - The second color. - * @param {number} percentage - The mix ratio (0-1). 1 = all color1, 0 = all color2. - * @returns {Qt.rgba} The resulting mixed color. - */ - function mix(color1, color2, percentage = 0.5) { - var c1 = Qt.color(color1); - var c2 = Qt.color(color2); - return Qt.rgba(percentage * c1.r + (1 - percentage) * c2.r, percentage * c1.g + (1 - percentage) * c2.g, percentage * c1.b + (1 - percentage) * c2.b, percentage * c1.a + (1 - percentage) * c2.a); - } - - /** - * Transparentizes a color by a given percentage. - * - * @param {string} color - The color (any Qt.color-compatible string). - * @param {number} percentage - The amount to transparentize (0-1). - * @returns {Qt.rgba} The resulting color. - */ - function transparentize(color, percentage = 1) { - var c = Qt.color(color); - return Qt.rgba(c.r, c.g, c.b, c.a * (1 - percentage)); - } - - /** - * Sets the alpha channel of a color. - * - * @param {string} color - The base color (any Qt.color-compatible string). - * @param {number} alpha - The desired alpha (0-1). - * @returns {Qt.rgba} The resulting color with applied alpha. - */ - function applyAlpha(color, alpha) { - var c = Qt.color(color); - var a = Math.max(0, Math.min(1, alpha)); - return Qt.rgba(c.r, c.g, c.b, a); - } -} diff --git a/fancy-bar/modules/common/widgets/ProgressBarText.qml b/fancy-bar/modules/common/widgets/ProgressBarText.qml deleted file mode 100644 index 7c7b9f5..0000000 --- a/fancy-bar/modules/common/widgets/ProgressBarText.qml +++ /dev/null @@ -1,156 +0,0 @@ -import QtQuick -import QtQuick.Controls -import qs.modules.common -import qs.modules.common.utils - -/** - * A progress bar with optional text centered inside it. - * Partially based on https://github.com/end-4/dots-hyprland/blob/449df7f161e6435569bc7d9499b2e444dd8aa153/dots/.config/quickshell/ii/modules/common/widgets/ClippedProgressBar.qml - */ -ProgressBar { - id: root - property int orientation: Types.Orientation.Horizontal - property real valueBarWidth: 2 - property real valueBarHeight: 1 - property color highlightColor: "gray" - property color trackColor: ColorUtils.transparentize(highlightColor, 0.7) - property color textColor: "white" - property string text - property bool shimmer: false - property bool pulse: false - - font.weight: text.length > 2 ? Font.Medium : Font.DemiBold - - background: Item { - implicitHeight: valueBarHeight - implicitWidth: valueBarWidth - } - - contentItem: Rectangle { - id: contentItem - anchors.fill: parent - color: root.trackColor - - SequentialAnimation on color { - running: root.pulse - loops: Animation.Infinite - - ColorAnimation { - from: root.trackColor - to: { - var c = Qt.color(root.trackColor); - var boostedLight = Math.min(1.0, c.hslLightness + 0.2); - return Qt.hsla(c.hslHue, c.hslSaturation, boostedLight, c.a); - } - duration: 1000 - easing.type: Easing.InOutQuad - } - ColorAnimation { - from: { - var c = Qt.color(root.trackColor); - var boostedLight = Math.min(1.0, c.hslLightness + 0.2); - return Qt.hsla(c.hslHue, c.hslSaturation, boostedLight, c.a); - } - to: root.trackColor - duration: 1000 - easing.type: Easing.InOutQuad - } - } - - Rectangle { - id: progressFill - color: root.highlightColor - clip: true // ensure the shimmer is only visible inside progressFill - anchors { - top: parent.top - bottom: parent.bottom - left: parent.left - right: undefined - } - width: parent.width * root.visualPosition - height: parent.height - - states: State { - name: "vertical" - when: root.orientation === Types.Orientation.Vertical - AnchorChanges { - target: progressFill - anchors { - top: undefined - bottom: parent.bottom - left: parent.left - right: parent.right - } - } - PropertyChanges { - target: progressFill - width: parent.width - height: parent.height * root.visualPosition - } - } - - Rectangle { - id: shimmerOverlay - visible: root.shimmer - width: root.valueBarWidth - height: root.valueBarHeight - property real shimmerWidth: root.orientation === Types.Orientation.Vertical - ? root.valueBarHeight * 0.2 : root.valueBarWidth * 0.2 - x: root.orientation === Types.Orientation.Vertical ? 0 : -progressFill.x - y: root.orientation === Types.Orientation.Vertical ? -progressFill.y : 0 - opacity: 0.5 - - gradient: Gradient { - orientation: root.orientation === Types.Orientation.Vertical - ? Gradient.Vertical : Gradient.Horizontal - GradientStop { position: -0.3; color: "transparent" } - GradientStop { - position: Math.max(-0.3, - shimmerAnimation.position - shimmerOverlay.shimmerWidth - / (root.orientation === Types.Orientation.Vertical - ? root.valueBarHeight : root.valueBarWidth)) - color: "transparent" - } - GradientStop { position: shimmerAnimation.position; color: "white" } - GradientStop { - position: Math.min(1.3, - shimmerAnimation.position + shimmerOverlay.shimmerWidth - / (root.orientation === Types.Orientation.Vertical - ? root.valueBarHeight : root.valueBarWidth)) - color: "transparent" - } - GradientStop { position: 1.3; color: "transparent" } - } - - SequentialAnimation on x { - id: shimmerAnimation - property real position: 0.0 - running: root.shimmer - loops: Animation.Infinite - - NumberAnimation { - target: shimmerAnimation - property: "position" - from: root.orientation === Types.Orientation.Vertical ? 1.2 : -0.2 - to: root.orientation === Types.Orientation.Vertical ? 0.8 - value : value + 0.2 - duration: 3000 - easing.type: Easing.InOutExpo - } - } - } - } - } - - Text { - id: overlayText - font: root.font - text: root.text - color: textColor - opacity: 0.5 - width: root.width - height: root.height - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - style: Text.Outline - } -} diff --git a/fancy-bar/modules/icons/BatteryIcon.qml b/fancy-bar/modules/icons/BatteryIcon.qml deleted file mode 100644 index 8d97cab..0000000 --- a/fancy-bar/modules/icons/BatteryIcon.qml +++ /dev/null @@ -1,89 +0,0 @@ -import QtQuick -import qs.modules.common - -Item { - id: root - - property color iconColor: "white" - property int orientation: Types.Orientation.Horizontal - property real size: 1 - - readonly property real borderWidth: size * 0.05 - readonly property real bodyWidth: body.width - readonly property real bodyHeight: body.height - readonly property real bodyRadius: body.radius - - state: Types.orientationToString(orientation) - width: orientation === Types.Orientation.Horizontal ? size : size * 0.6 - height: orientation === Types.Orientation.Vertical ? size : size * 0.6 - - Rectangle { - id: body - color: "transparent" - border.color: root.iconColor - border.width: root.borderWidth - radius: root.size * 0.1 - } - - Rectangle { - id: nub - color: root.iconColor - radius: 0 - } - - states: [ - State { - name: "horizontal" - AnchorChanges { - target: body - anchors.left: parent.left - anchors.right: nub.left - anchors.verticalCenter: parent.verticalCenter - } - AnchorChanges { - target: nub - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - } - PropertyChanges { - target: body - width: root.width * 0.9 - height: root.height - } - PropertyChanges { - target: nub - width: root.size * 0.1 - height: root.size * 0.2 - topRightRadius: root.size * 0.1 - bottomRightRadius: root.size * 0.1 - } - }, - State { - name: "vertical" - AnchorChanges { - target: body - anchors.left: parent.left - anchors.right: parent.right - anchors.top: nub.bottom - anchors.bottom: parent.bottom - } - AnchorChanges { - target: nub - anchors.top: parent.top - anchors.horizontalCenter: parent.horizontalCenter - } - PropertyChanges { - target: body - width: root.width - height: root.height * 0.9 - } - PropertyChanges { - target: nub - width: root.size * 0.2 - height: root.size * 0.1 - topLeftRadius: root.size * 0.1 - topRightRadius: root.size * 0.1 - } - } - ] -} diff --git a/fancy-bar/services/Battery.qml b/fancy-bar/services/Battery.qml deleted file mode 100644 index aa0c96a..0000000 --- a/fancy-bar/services/Battery.qml +++ /dev/null @@ -1,56 +0,0 @@ -pragma Singleton - -import Quickshell -import Quickshell.Services.UPower -import QtQuick -import Quickshell.Io -import qs.services -import qs.modules.common - -Singleton { - property bool available: UPower.displayDevice.isLaptopBattery - property var chargeState: UPower.displayDevice.state - property bool isCharging: chargeState == UPowerDeviceState.Charging - property bool isPluggedIn: isCharging || chargeState == UPowerDeviceState.PendingCharge - property real percentage: UPower.displayDevice?.percentage ?? 1 - readonly property bool allowAutomaticSuspend: Config.data.battery.automaticSuspend - - property bool isLow: available && (percentage <= Config.data.battery.low / 100) - property bool isCritical: available && (percentage <= Config.data.battery.critical / 100) - property bool isSuspending: available && (percentage <= Config.data.battery.suspend / 100) - - property bool isLowAndNotCharging: isLow && !isCharging - property bool isCriticalAndNotCharging: isCritical && !isCharging - property bool isSuspendingAndNotCharging: allowAutomaticSuspend && isSuspending && !isCharging - - property real energyRate: UPower.displayDevice.changeRate - property real timeToEmpty: UPower.displayDevice.timeToEmpty - property real timeToFull: UPower.displayDevice.timeToFull - - onIsLowAndNotChargingChanged: { - if (available && isLowAndNotCharging) Quickshell.execDetached([ - "notify-send", - "Low battery", - "Consider plugging in your device", - "-u", "critical", - "-a", "Shell" - ]) - } - - onIsCriticalAndNotChargingChanged: { - if (available && isCriticalAndNotCharging) Quickshell.execDetached([ - "notify-send", - "Critically low battery", - "Please charge!\nAutomatic suspend triggers at %1".arg(Config.data.power.battery.suspend), - "-u", "critical", - "-a", "Shell" - ]); - - } - - onIsSuspendingAndNotChargingChanged: { - if (available && isSuspendingAndNotCharging) { - Quickshell.execDetached(["sh", "-c", `systemctl suspend || loginctl suspend`]); - } - } -} diff --git a/fancy-bar/services/Niri.qml b/fancy-bar/services/Niri.qml deleted file mode 100644 index 9fd639f..0000000 --- a/fancy-bar/services/Niri.qml +++ /dev/null @@ -1,14 +0,0 @@ -pragma Singleton -import QtQuick -import Niri 0.1 - -Niri { - id: niri - - Component.onCompleted: connect() - - onConnected: console.log("Connected to niri") - onErrorOccurred: function(error) { - console.error("Niri error:", error) - } -} diff --git a/fancy-bar/shell.qml b/fancy-bar/shell.qml deleted file mode 100644 index b2f552f..0000000 --- a/fancy-bar/shell.qml +++ /dev/null @@ -1,18 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Wayland -import "./modules/bar/" -import "./modules/common/" -import "./services/" - -ShellRoot{ - LazyLoader{ - active: true - component: Bar{ - position: Types.stringToPosition(Config.data.bar.position) - size: Config.data.bar.size - color: Config.data.theme.color.background - } - } -} From 1d99bfae3757fcea27587cf17eefbc9a4b7ae057 Mon Sep 17 00:00:00 2001 From: tripleducky Date: Fri, 24 Oct 2025 22:00:00 -0600 Subject: [PATCH 5/5] Delete assets directory --- assets/simple-bar.png | Bin 41116 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 assets/simple-bar.png diff --git a/assets/simple-bar.png b/assets/simple-bar.png deleted file mode 100644 index 65ea682c9063f19f9ee008ec39eedad0269741f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41116 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