From 56d8f73751eb4d86a35398d98d64b31f7a216a70 Mon Sep 17 00:00:00 2001 From: Rexiel Scarlet <37258415+Rexcrazy804@users.noreply.github.com> Date: Mon, 16 Jun 2025 16:38:50 +0400 Subject: [PATCH 1/4] initial work on basic bar --- basic_bar/.qmlformat.ini | 8 ++ basic_bar/Containers/Left.qml | 24 ++++ basic_bar/Containers/Middle.qml | 18 +++ basic_bar/Containers/Right.qml | 22 ++++ basic_bar/Data/Audio.qml | 36 ++++++ basic_bar/Data/Colors.qml | 113 +++++++++++++++++ basic_bar/Data/Fonts.qml | 10 ++ basic_bar/Data/Time.qml | 10 ++ basic_bar/Generics/MatIcon.qml | 31 +++++ basic_bar/Generics/MouseArea.qml | 35 ++++++ basic_bar/Generics/Notification.qml | 181 ++++++++++++++++++++++++++++ basic_bar/Generics/RoundedImage.qml | 53 ++++++++ basic_bar/Generics/WaybarItem.qml | 46 +++++++ basic_bar/Layers/Top.qml | 64 ++++++++++ basic_bar/Widgets/Clock.qml | 35 ++++++ basic_bar/Widgets/OsText.qml | 30 +++++ basic_bar/Widgets/PowerProfs.qml | 95 +++++++++++++++ basic_bar/Widgets/Session.qml | 93 ++++++++++++++ basic_bar/Widgets/WorkspaceName.qml | 43 +++++++ basic_bar/Widgets/Workspaces.qml | 83 +++++++++++++ basic_bar/shell.qml | 22 ++++ 21 files changed, 1052 insertions(+) create mode 100644 basic_bar/.qmlformat.ini create mode 100644 basic_bar/Containers/Left.qml create mode 100644 basic_bar/Containers/Middle.qml create mode 100644 basic_bar/Containers/Right.qml create mode 100644 basic_bar/Data/Audio.qml create mode 100644 basic_bar/Data/Colors.qml create mode 100644 basic_bar/Data/Fonts.qml create mode 100644 basic_bar/Data/Time.qml create mode 100644 basic_bar/Generics/MatIcon.qml create mode 100644 basic_bar/Generics/MouseArea.qml create mode 100644 basic_bar/Generics/Notification.qml create mode 100644 basic_bar/Generics/RoundedImage.qml create mode 100644 basic_bar/Generics/WaybarItem.qml create mode 100644 basic_bar/Layers/Top.qml create mode 100644 basic_bar/Widgets/Clock.qml create mode 100644 basic_bar/Widgets/OsText.qml create mode 100644 basic_bar/Widgets/PowerProfs.qml create mode 100644 basic_bar/Widgets/Session.qml create mode 100644 basic_bar/Widgets/WorkspaceName.qml create mode 100644 basic_bar/Widgets/Workspaces.qml create mode 100644 basic_bar/shell.qml diff --git a/basic_bar/.qmlformat.ini b/basic_bar/.qmlformat.ini new file mode 100644 index 0000000..0a8a26f --- /dev/null +++ b/basic_bar/.qmlformat.ini @@ -0,0 +1,8 @@ +[General] +FunctionsSpacing=true +IndentWidth=2 +MaxColumnWidth=-1 +NewlineType=native +NormalizeOrder=true +ObjectsSpacing=true +UseTabs=false diff --git a/basic_bar/Containers/Left.qml b/basic_bar/Containers/Left.qml new file mode 100644 index 0000000..9ee5e9d --- /dev/null +++ b/basic_bar/Containers/Left.qml @@ -0,0 +1,24 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Wayland + +import "../Data/" as Dat +import "../Widgets/" as Wid + +Item { + RowLayout { + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.top: parent.top + + Wid.OsText { + } + + Wid.Workspaces { + } + + Wid.WorkspaceName { + } + } +} diff --git a/basic_bar/Containers/Middle.qml b/basic_bar/Containers/Middle.qml new file mode 100644 index 0000000..02cff37 --- /dev/null +++ b/basic_bar/Containers/Middle.qml @@ -0,0 +1,18 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Wayland + +import "../Data/" as Dat +import "../Widgets/" as Wid + +Item { + RowLayout { + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + + Wid.Clock { + } + } +} diff --git a/basic_bar/Containers/Right.qml b/basic_bar/Containers/Right.qml new file mode 100644 index 0000000..12c3a0e --- /dev/null +++ b/basic_bar/Containers/Right.qml @@ -0,0 +1,22 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Wayland + +import "../Data/" as Dat +import "../Widgets/" as Wid + +Item { + RowLayout { + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.top: parent.top + layoutDirection: Qt.RightToLeft + + Wid.Session { + } + + Wid.PowerProfs { + } + } +} diff --git a/basic_bar/Data/Audio.qml b/basic_bar/Data/Audio.qml new file mode 100644 index 0000000..bfcf11f --- /dev/null +++ b/basic_bar/Data/Audio.qml @@ -0,0 +1,36 @@ +pragma Singleton +import QtQuick +import Quickshell +import Quickshell.Services.Pipewire + +// WARNING don't forget to track nodes with PwNodeObjectTracler +Singleton { + id: root + + function getSinkIcon(node: PwNode): string { + return (node.muted) ? "󰝟" : (node.volume > 0.5) ? "󰕾" : (node.volume > 0.01) ? "󰖀" : "󰕿"; + } + + function getSourceIcon(node: PwNode): string { + return (node.muted) ? "󰍭" : "󰍬"; + } + + function toggleMute(node: PwNode) { + node.audio.muted = !node.audio.muted; + } + + function wheelAction(event: WheelEvent, node: PwNode) { + if (event.angleDelta.y < 0) { + node.audio.volume -= 0.01; + } else { + node.audio.volume += 0.01; + } + + if (node.audio.volume > 1.3) { + node.audio.volume = 1.3; + } + if (root.sink.audio.volume < 0) { + node.audio.volume = 0.0; + } + } +} diff --git a/basic_bar/Data/Colors.qml b/basic_bar/Data/Colors.qml new file mode 100644 index 0000000..0f64757 --- /dev/null +++ b/basic_bar/Data/Colors.qml @@ -0,0 +1,113 @@ +pragma Singleton +import Quickshell +import QtQuick + +Singleton { + + // light theme for testing purposes + // feel free to uncomment to get flash banged lol + + // readonly property color background: "#f4fafb" + // readonly property color error: "#ba1a1a" + // readonly property color error_container: "#ffdad6" + // readonly property color inverse_on_surface: "#ecf2f2" + // readonly property color inverse_primary: "#80d4da" + // readonly property color inverse_surface: "#2b3232" + // readonly property color on_background: "#161d1d" + // readonly property color on_error: "#ffffff" + // readonly property color on_error_container: "#410002" + // readonly property color on_primary: "#ffffff" + // readonly property color on_primary_container: "#002022" + // readonly property color on_primary_fixed: "#002022" + // readonly property color on_primary_fixed_variant: "#004f53" + // readonly property color on_secondary: "#ffffff" + // readonly property color on_secondary_container: "#041f21" + // readonly property color on_secondary_fixed: "#041f21" + // readonly property color on_secondary_fixed_variant: "#324b4d" + // readonly property color on_surface: "#161d1d" + // readonly property color on_surface_variant: "#3f4949" + // readonly property color on_tertiary: "#ffffff" + // readonly property color on_tertiary_container: "#091b36" + // readonly property color on_tertiary_fixed: "#091b36" + // readonly property color on_tertiary_fixed_variant: "#374764" + // readonly property color outline: "#6f7979" + // readonly property color outline_variant: "#bec8c9" + // readonly property color primary: "#00696e" + // readonly property color primary_container: "#9cf0f6" + // readonly property color primary_fixed: "#9cf0f6" + // readonly property color primary_fixed_dim: "#80d4da" + // readonly property color scrim: "#000000" + // readonly property color secondary: "#4a6365" + // readonly property color secondary_container: "#cce8e9" + // readonly property color secondary_fixed: "#cce8e9" + // readonly property color secondary_fixed_dim: "#b1cccd" + // readonly property color shadow: "#000000" + // readonly property color source_color: "#478185" + // readonly property color surface: "#f4fafb" + // readonly property color surface_bright: "#f4fafb" + // readonly property color surface_container: "#e9efef" + // readonly property color surface_container_high: "#e3e9e9" + // readonly property color surface_container_highest: "#dde4e4" + // readonly property color surface_container_low: "#eff5f5" + // readonly property color surface_container_lowest: "#ffffff" + // readonly property color surface_dim: "#d5dbdb" + // readonly property color surface_tint: "#00696e" + // readonly property color surface_variant: "#dae4e5" + // readonly property color tertiary: "#4e5f7d" + // readonly property color tertiary_container: "#d6e3ff" + // readonly property color tertiary_fixed: "#d6e3ff" + // readonly property color tertiary_fixed_dim: "#b6c7e9" + + readonly property color background: "#121318" + readonly property color error: "#ffb4ab" + readonly property color error_container: "#93000a" + readonly property color inverse_on_surface: "#2f3036" + readonly property color inverse_primary: "#4d5c92" + readonly property color inverse_surface: "#e3e1e9" + readonly property color on_background: "#e3e1e9" + readonly property color on_error: "#690005" + readonly property color on_error_container: "#ffdad6" + readonly property color on_primary: "#1d2d61" + readonly property color on_primary_container: "#dce1ff" + readonly property color on_primary_fixed: "#04174b" + readonly property color on_primary_fixed_variant: "#354479" + readonly property color on_secondary: "#2b3042" + readonly property color on_secondary_container: "#dee1f9" + readonly property color on_secondary_fixed: "#161b2c" + readonly property color on_secondary_fixed_variant: "#424659" + readonly property color on_surface: "#e3e1e9" + readonly property color on_surface_variant: "#c6c5d0" + readonly property color on_tertiary: "#432740" + readonly property color on_tertiary_container: "#ffd7f5" + readonly property color on_tertiary_fixed: "#2c122a" + readonly property color on_tertiary_fixed_variant: "#5b3d57" + readonly property color outline: "#90909a" + readonly property color outline_variant: "#45464f" + readonly property color primary: "#b6c4ff" + readonly property color primary_container: "#354479" + readonly property color primary_fixed: "#dce1ff" + readonly property color primary_fixed_dim: "#b6c4ff" + readonly property color scrim: "#000000" + readonly property color secondary: "#c2c5dd" + readonly property color secondary_container: "#424659" + readonly property color secondary_fixed: "#dee1f9" + readonly property color secondary_fixed_dim: "#c2c5dd" + readonly property color shadow: "#000000" + readonly property color surface: "#121318" + readonly property color surface_bright: "#38393f" + readonly property color surface_container: "#1e1f25" + readonly property color surface_container_high: "#292a2f" + readonly property color surface_container_highest: "#34343a" + readonly property color surface_container_low: "#1a1b21" + readonly property color surface_container_lowest: "#0d0e13" + readonly property color surface_dim: "#121318" + readonly property color surface_tint: "#b6c4ff" + readonly property color tertiary: "#e3bada" + readonly property color tertiary_container: "#5b3d57" + readonly property color tertiary_fixed: "#ffd7f5" + readonly property color tertiary_fixed_dim: "#e3bada" + + function withAlpha(color: color, alpha: real): color { + return Qt.rgba(color.r, color.g, color.b, alpha); + } +} diff --git a/basic_bar/Data/Fonts.qml b/basic_bar/Data/Fonts.qml new file mode 100644 index 0000000..9afe1d1 --- /dev/null +++ b/basic_bar/Data/Fonts.qml @@ -0,0 +1,10 @@ +pragma Singleton +import Quickshell + +Singleton { + readonly property string caskaydia: "CaskaydiaMono Nerd" + readonly property string dejavuSans: "Dejavu Sans" + readonly property string hurricane: "Hurricane" + readonly property string jpKaisei: "Kaisei Decol" + readonly property string rye: "Rye" +} diff --git a/basic_bar/Data/Time.qml b/basic_bar/Data/Time.qml new file mode 100644 index 0000000..e4ab2e4 --- /dev/null +++ b/basic_bar/Data/Time.qml @@ -0,0 +1,10 @@ +pragma Singleton +import Quickshell +import QtQuick + +SystemClock { + id: clock + + enabled: true + precision: SystemClock.Seconds +} diff --git a/basic_bar/Generics/MatIcon.qml b/basic_bar/Generics/MatIcon.qml new file mode 100644 index 0000000..81898a7 --- /dev/null +++ b/basic_bar/Generics/MatIcon.qml @@ -0,0 +1,31 @@ +// a thin wrapper for Material Symbols +import QtQuick +import "../Data/" as Dat + +Text { + id: root + + property real fill: 0 + property int grad: 0 + required property string icon + + font.family: "Material Symbols Rounded" + font.hintingPreference: Font.PreferFullHinting + + // refer https://developers.google.com/fonts/docs/material_symbols + font.variableAxes: { + "FILL": root.fill, + "opsz": root.fontInfo.pixelSize, + // "GRAD": root.grad, + "wght": root.fontInfo.weight + } + renderType: Text.NativeRendering + text: root.icon + + Behavior on fill { + NumberAnimation { + duration: 180 + easing.type: Easing.InOutQuad + } + } +} diff --git a/basic_bar/Generics/MouseArea.qml b/basic_bar/Generics/MouseArea.qml new file mode 100644 index 0000000..dd5295d --- /dev/null +++ b/basic_bar/Generics/MouseArea.qml @@ -0,0 +1,35 @@ +import QtQuick +import "../Data/" as Dat + +MouseArea { + id: area + + property real clickOpacity: 0.2 + property real hoverOpacity: 0.08 + property color layerColor: "white" + property NumberAnimation layerOpacityAnimation: NumberAnimation { + duration: 200 + easing.type: Easing.InOutQuad + } + property int layerRadius: parent?.radius ?? 0 + property alias layerRect: layer + + anchors.fill: parent + hoverEnabled: true + + onContainsMouseChanged: layer.opacity = (area.containsMouse) ? area.hoverOpacity : 0 + onContainsPressChanged: layer.opacity = (area.containsPress) ? area.clickOpacity : area.hoverOpacity + + Rectangle { + id: layer + + anchors.fill: parent + color: area.layerColor + opacity: 0 + radius: area.layerRadius + + Behavior on opacity { + animation: area.layerOpacityAnimation + } + } +} diff --git a/basic_bar/Generics/Notification.qml b/basic_bar/Generics/Notification.qml new file mode 100644 index 0000000..32ad703 --- /dev/null +++ b/basic_bar/Generics/Notification.qml @@ -0,0 +1,181 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Effects +import Quickshell +import Quickshell.Services.Notifications +import Quickshell.Hyprland + +import "../Data/" as Dat +import "../Generics/" as Gen + +Rectangle { + id: root + + required property Notification notif + + color: "transparent" + height: bodyNActionCol.height + + Behavior on x { + SmoothedAnimation { + } + } + + onXChanged: { + root.opacity = 1 - (Math.abs(root.x) / width); + } + + MouseArea { + id: dragArea + + anchors.fill: parent + + drag { + axis: Drag.XAxis + target: parent + + onActiveChanged: { + if (dragArea.drag.active) { + return; + } + if (Math.abs(root.x) > (root.width / 2)) { + root.notif.dismiss(); + } else { + root.x = 0; + } + } + } + } + + ColumnLayout { + id: bodyNActionCol + + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + spacing: 0 + + Rectangle { + Layout.fillWidth: true + Layout.margins: 10 + color: "transparent" + implicitHeight: sumText.contentHeight + bodText.contentHeight + topLeftRadius: 20 + topRightRadius: 20 + + RowLayout { + id: infoRow + + anchors.top: parent.top + height: sumText.contentHeight + width: parent.width + + Text { + id: sumText + + Layout.maximumWidth: root.width * 0.8 + color: Dat.Colors.primary + elide: Text.ElideRight + text: root.notif?.summary ?? "summary" + } + + Rectangle { + Layout.alignment: Qt.AlignRight + color: "transparent" + implicitHeight: appText.contentHeight + 2 + implicitWidth: appText.contentWidth + 10 + radius: 20 + + Text { + id: appText + + anchors.centerIn: parent + color: Dat.Colors.tertiary + font.bold: true + font.pointSize: 8 + text: root.notif?.appName ?? "idk" + } + } + } + + Text { + id: bodText + + anchors.top: infoRow.bottom + color: Dat.Colors.on_surface + font.pointSize: 11 + text: root.notif?.body ?? "very cool body that is missing" + textFormat: Text.MarkdownText + width: parent.width + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + + MouseArea { + id: bodMArea + + acceptedButtons: Qt.LeftButton + anchors.fill: parent + + // thanks end_4 for this <3 + onClicked: { + const hovLink = bodText.hoveredLink; + if (hovLink == "") { + return; + } + Hyprland.dispatch("exec xdg-open " + hovLink); + } + } + } + } + + Flickable { + id: flick + + Layout.alignment: Qt.AlignRight + Layout.bottomMargin: 10 + Layout.leftMargin: this.Layout.rightMargin + Layout.rightMargin: 10 + boundsBehavior: Flickable.StopAtBounds + clip: true + contentWidth: actionRow.width + implicitHeight: 23 + // thanks to Aureus :> + implicitWidth: Math.min(bodyNActionCol.width - 20, actionRow.width) + + RowLayout { + id: actionRow + + anchors.right: parent.right + height: parent.height + + Repeater { + model: root.notif?.actions + + Rectangle { + required property NotificationAction modelData + + Layout.fillHeight: true + color: Dat.Colors.secondary + implicitWidth: actionText.contentWidth + 14 + radius: 20 + + Text { + id: actionText + + anchors.centerIn: parent + color: Dat.Colors.on_secondary + font.pointSize: 11 + text: parent.modelData?.text ?? "activate" + } + + Gen.MouseArea { + layerColor: actionText.color + + onClicked: parent.modelData.invoke() + } + } + } + } + } + } +} diff --git a/basic_bar/Generics/RoundedImage.qml b/basic_bar/Generics/RoundedImage.qml new file mode 100644 index 0000000..6f221a1 --- /dev/null +++ b/basic_bar/Generics/RoundedImage.qml @@ -0,0 +1,53 @@ +import QtQuick +import QtQuick.Effects + +Item { + id: root + + property alias image: rootIcon + property real radius + property string source + + Image { + id: rootIcon + + anchors.fill: parent + antialiasing: true + fillMode: Image.PreserveAspectCrop + mipmap: true + smooth: true + source: root.source + visible: false + } + + MultiEffect { + id: effect + + anchors.fill: rootIcon + antialiasing: true + maskEnabled: true + maskSource: rootIconMask + maskSpreadAtMin: 1.0 + maskThresholdMax: 1.0 + maskThresholdMin: 0.5 + source: rootIcon + } + + Item { + id: rootIconMask + + antialiasing: true + height: rootIcon.height + layer.enabled: true + layer.smooth: true + smooth: true + visible: false + width: rootIcon.width + + Rectangle { + anchors.fill: parent + height: this.width + radius: root.radius + } + } +} diff --git a/basic_bar/Generics/WaybarItem.qml b/basic_bar/Generics/WaybarItem.qml new file mode 100644 index 0000000..a5fabac --- /dev/null +++ b/basic_bar/Generics/WaybarItem.qml @@ -0,0 +1,46 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Wayland + +import "../Data/" as Dat + +RowLayout { + id: root + + property alias icon: icon + property alias text: text + + anchors.centerIn: parent + height: parent.height ? parent.height : 1 + + Item { + id: iconContainer + + Layout.fillHeight: true + implicitWidth: icon.width + + Text { + id: icon + + anchors.centerIn: parent + font.family: "Material Symbols Rounded" + font.pointSize: 16 + } + } + + Item { + id: textContainer + + Layout.fillHeight: true + implicitWidth: text.width + + Text { + id: text + + anchors.centerIn: parent + font.family: Dat.Fonts.dejavuSans + font.pointSize: 11 + } + } +} diff --git a/basic_bar/Layers/Top.qml b/basic_bar/Layers/Top.qml new file mode 100644 index 0000000..845463e --- /dev/null +++ b/basic_bar/Layers/Top.qml @@ -0,0 +1,64 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Wayland + +import "../Data/" as Dat +import "../Containers/" as Con + +Scope { + Variants { + model: Quickshell.screens + + delegate: WlrLayershell { + id: layerShell + + required property ShellScreen modelData + + anchors.left: true + anchors.right: true + anchors.top: true + color: "transparent" + exclusionMode: ExclusionMode.Auto + focusable: false + implicitHeight: 40 + layer: WlrLayer.Top + namespace: "rexies.quebar.top" + screen: modelData + surfaceFormat.opaque: false + + mask: Region { + item: base + } + + Item { + id: base + + anchors.fill: parent + anchors.margins: 4 + + // radius: 5 + // color: Dat.Colors.withAlpha(Dat.Colors.background, 0.79) + + RowLayout { + anchors.fill: parent + + Con.Left { + Layout.fillHeight: true + Layout.fillWidth: true + } + + Con.Middle { + Layout.fillHeight: true + Layout.fillWidth: true + } + + Con.Right { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + } + } + } +} diff --git a/basic_bar/Widgets/Clock.qml b/basic_bar/Widgets/Clock.qml new file mode 100644 index 0000000..301ddce --- /dev/null +++ b/basic_bar/Widgets/Clock.qml @@ -0,0 +1,35 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Wayland + +import "../Data/" as Dat +import "../Generics/" as Gen + +Rectangle { + property int padding: 16 + + Layout.fillHeight: true + color: Dat.Colors.withAlpha(Dat.Colors.background, 0.79) + implicitWidth: timeContainer.width + padding + radius: 5 + + Gen.WaybarItem { + id: timeContainer + + icon { + id: icon + + color: Dat.Colors.on_background + text: "schedule" + } + + text { + id: text + + color: Dat.Colors.on_background + font.pointSize: 11 + text: Qt.formatDateTime(Dat.Time?.date, "h:mm:ss AP") + } + } +} diff --git a/basic_bar/Widgets/OsText.qml b/basic_bar/Widgets/OsText.qml new file mode 100644 index 0000000..00f787f --- /dev/null +++ b/basic_bar/Widgets/OsText.qml @@ -0,0 +1,30 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Wayland + +import "../Data/" as Dat +import "../Generics/" as Gen + +Rectangle { + property int padding: 16 + + Layout.fillHeight: true + color: Dat.Colors.withAlpha(Dat.Colors.background, 0.79) + implicitWidth: container.width + padding + radius: 5 + + Gen.WaybarItem { + id: container + + icon { + color: Dat.Colors.tertiary + font.family: Dat.Fonts.caskaydia + text: "󱄅" + } + text { + color: Dat.Colors.tertiary + text: "NixOS" + } + } +} diff --git a/basic_bar/Widgets/PowerProfs.qml b/basic_bar/Widgets/PowerProfs.qml new file mode 100644 index 0000000..08d40d3 --- /dev/null +++ b/basic_bar/Widgets/PowerProfs.qml @@ -0,0 +1,95 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Quickshell.Hyprland +import Quickshell.Services.UPower + +import "../Data/" as Dat +import "../Generics/" as Gen + +Rectangle { + Layout.fillHeight: true + clip: true + color: Dat.Colors.withAlpha(Dat.Colors.background, 0.79) + implicitWidth: container.width + radius: 5 + + Behavior on implicitWidth { + NumberAnimation { + duration: 200 + easing.type: Easing.InOutQuad + } + } + + MouseArea { + id: mArea + + anchors.fill: parent + hoverEnabled: true + + RowLayout { + id: container + + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.top: parent.top + clip: true + + Repeater { + model: [ + { + icon: "potted_plant", + profile: PowerProfile.PowerSaver + }, + { + icon: "balance", + profile: PowerProfile.Balanced + }, + { + icon: "speed", + profile: PowerProfile.Performance + }, + ] + + delegate: Item { + id: delegateRoot + + required property int index + required property var modelData + + Layout.fillHeight: true + implicitWidth: this.height ? this.height : 1 + + Rectangle { + id: bgCon + + anchors.fill: parent + anchors.margins: 4 + color: Dat.Colors.primary + radius: 5 + visible: delegateRoot.modelData.profile == PowerProfiles.profile + } + + Gen.MouseArea { + anchors.margins: 4 + layerColor: fgText.color + layerRadius: 5 + visible: !bgCon.visible + + onClicked: PowerProfiles.profile = delegateRoot.modelData.profile + } + + Gen.MatIcon { + id: fgText + + anchors.centerIn: parent + color: bgCon.visible ? Dat.Colors.on_primary : Dat.Colors.on_background + fill: bgCon.visible + font.pointSize: 14 + icon: delegateRoot.modelData.icon + } + } + } + } + } +} diff --git a/basic_bar/Widgets/Session.qml b/basic_bar/Widgets/Session.qml new file mode 100644 index 0000000..4335c60 --- /dev/null +++ b/basic_bar/Widgets/Session.qml @@ -0,0 +1,93 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Wayland + +import "../Data/" as Dat +import "../Generics/" as Gen + +Rectangle { + property int padding: 16 + + Layout.fillHeight: true + color: Dat.Colors.withAlpha(Dat.Colors.background, 0.79) + implicitWidth: (mArea.containsMouse ? 3 : 1) * (this.height ? this.height : 1) + radius: 5 + + Behavior on implicitWidth { + NumberAnimation { + duration: 200 + easing.type: Easing.InOutQuad + } + } + + MouseArea { + id: mArea + + anchors.fill: parent + hoverEnabled: true + + RowLayout { + anchors.fill: parent + clip: true + layoutDirection: Qt.RightToLeft + spacing: 0 + + Repeater { + model: [ + { + icon: "skull", + action: () => { + Quickshell.execDetached({ + command: ["systemctl", "poweroff"] + }); + } + }, + { + icon: "change_circle", + action: () => { + Quickshell.execDetached({ + command: ["systemctl", "reboot"] + }); + } + }, + { + icon: "bedtime", + action: () => { + Quickshell.execDetached({ + command: ["systemctl", "suspend"] + }); + } + }, + ] + + delegate: Item { + id: delegateRoot + + required property var modelData + + Layout.fillHeight: true + implicitWidth: this.height ? this.height : 1 + + Gen.MatIcon { + anchors.centerIn: parent + color: Dat.Colors.primary + fill: delegateMArea.containsMouse + font.pointSize: 16 + icon: delegateRoot.modelData.icon + + MouseArea { + id: delegateMArea + + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + + onClicked: delegateRoot.modelData.action() + } + } + } + } + } + } +} diff --git a/basic_bar/Widgets/WorkspaceName.qml b/basic_bar/Widgets/WorkspaceName.qml new file mode 100644 index 0000000..1e7f127 --- /dev/null +++ b/basic_bar/Widgets/WorkspaceName.qml @@ -0,0 +1,43 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Wayland + +import "../Data/" as Dat +import "../Generics/" as Gen + +Rectangle { + id: root + + property int maximumWidth: 184 + property int padding: 16 + + Layout.fillHeight: true + Layout.maximumWidth: maximumWidth + padding + clip: true + color: Dat.Colors.withAlpha(Dat.Colors.background, 0.79) + implicitWidth: windowNameText.contentWidth + padding + radius: 5 + + Behavior on implicitWidth { + NumberAnimation { + duration: 100 + easing.type: Easing.InOutQuad + } + } + + Text { + id: windowNameText + + property string actWinName: activeWindow?.activated ? activeWindow?.appId : "desktop" + readonly property Toplevel activeWindow: ToplevelManager.activeToplevel + + anchors.centerIn: parent + color: Dat.Colors.on_primary_container + elide: Text.ElideMiddle + font.pointSize: 11 + horizontalAlignment: Text.AlignHCenter + text: actWinName + width: (contentWidth > root.maximumWidth) ? root.maximumWidth : undefined + } +} diff --git a/basic_bar/Widgets/Workspaces.qml b/basic_bar/Widgets/Workspaces.qml new file mode 100644 index 0000000..209a8d6 --- /dev/null +++ b/basic_bar/Widgets/Workspaces.qml @@ -0,0 +1,83 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Hyprland + +import "../Data/" as Dat +import "../Generics/" as Gen + +Rectangle { + Layout.fillHeight: true + clip: true + color: Dat.Colors.withAlpha(Dat.Colors.background, 0.79) + implicitWidth: container.width + radius: 5 + + Behavior on implicitWidth { + NumberAnimation { + duration: 200 + easing.type: Easing.InOutQuad + } + } + + MouseArea { + id: mArea + + anchors.fill: parent + hoverEnabled: true + + RowLayout { + id: container + + property int focusedWorkspace: Hyprland.focusedWorkspace?.id ?? "0" + + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.top: parent.top + clip: true + spacing: 0 + + Repeater { + model: 6 + + delegate: Item { + id: delegateRoot + + required property int index + + Layout.fillHeight: true + implicitWidth: this.height ? this.height : 1 + + Rectangle { + id: bgCon + + anchors.fill: parent + anchors.margins: 4 + color: Dat.Colors.primary + radius: 5 + visible: container.focusedWorkspace == index + 1 + } + + Gen.MouseArea { + anchors.margins: 4 + layerColor: fgText.color + layerRadius: 5 + visible: !bgCon.visible + + onClicked: Hyprland.dispatch("workspace " + (parent.index + 1)) + } + + Text { + id: fgText + + anchors.centerIn: parent + color: bgCon.visible ? Dat.Colors.on_primary : Dat.Colors.on_background + font.pointSize: 11 + text: delegateRoot.index + 1 + } + } + } + } + } +} diff --git a/basic_bar/shell.qml b/basic_bar/shell.qml new file mode 100644 index 0000000..b65bf81 --- /dev/null +++ b/basic_bar/shell.qml @@ -0,0 +1,22 @@ +//@ pragma UseQApplication +import Quickshell +import QtQuick +import "Layers" as Lay + +ShellRoot { + Lay.Top { + } + + // inhibit the reload popup + Connections { + function onReloadCompleted() { + Quickshell.inhibitReloadPopup(); + } + + function onReloadFailed() { + Quickshell.inhibitReloadPopup(); + } + + target: Quickshell + } +} From ceac370f575b15a464a5201ab4e7fa49b93717d6 Mon Sep 17 00:00:00 2001 From: Rexiel Scarlet <37258415+Rexcrazy804@users.noreply.github.com> Date: Mon, 16 Jun 2025 16:52:05 +0400 Subject: [PATCH 2/4] pruned unused imports --- basic_bar/Containers/Left.qml | 4 - basic_bar/Containers/Middle.qml | 4 - basic_bar/Containers/Right.qml | 4 - basic_bar/Data/Colors.qml | 55 --------- basic_bar/Generics/MouseArea.qml | 1 - basic_bar/Generics/Notification.qml | 181 ---------------------------- basic_bar/Layers/Top.qml | 2 - basic_bar/Widgets/Clock.qml | 2 - basic_bar/Widgets/OsText.qml | 2 - basic_bar/Widgets/PowerProfs.qml | 1 - basic_bar/Widgets/Session.qml | 1 - basic_bar/Widgets/WorkspaceName.qml | 3 - basic_bar/Widgets/Workspaces.qml | 1 - 13 files changed, 261 deletions(-) delete mode 100644 basic_bar/Generics/Notification.qml diff --git a/basic_bar/Containers/Left.qml b/basic_bar/Containers/Left.qml index 9ee5e9d..20e8154 100644 --- a/basic_bar/Containers/Left.qml +++ b/basic_bar/Containers/Left.qml @@ -1,9 +1,5 @@ import QtQuick import QtQuick.Layouts -import Quickshell -import Quickshell.Wayland - -import "../Data/" as Dat import "../Widgets/" as Wid Item { diff --git a/basic_bar/Containers/Middle.qml b/basic_bar/Containers/Middle.qml index 02cff37..a875d13 100644 --- a/basic_bar/Containers/Middle.qml +++ b/basic_bar/Containers/Middle.qml @@ -1,9 +1,5 @@ import QtQuick import QtQuick.Layouts -import Quickshell -import Quickshell.Wayland - -import "../Data/" as Dat import "../Widgets/" as Wid Item { diff --git a/basic_bar/Containers/Right.qml b/basic_bar/Containers/Right.qml index 12c3a0e..a97d1c2 100644 --- a/basic_bar/Containers/Right.qml +++ b/basic_bar/Containers/Right.qml @@ -1,9 +1,5 @@ import QtQuick import QtQuick.Layouts -import Quickshell -import Quickshell.Wayland - -import "../Data/" as Dat import "../Widgets/" as Wid Item { diff --git a/basic_bar/Data/Colors.qml b/basic_bar/Data/Colors.qml index 0f64757..a86fb44 100644 --- a/basic_bar/Data/Colors.qml +++ b/basic_bar/Data/Colors.qml @@ -3,61 +3,6 @@ import Quickshell import QtQuick Singleton { - - // light theme for testing purposes - // feel free to uncomment to get flash banged lol - - // readonly property color background: "#f4fafb" - // readonly property color error: "#ba1a1a" - // readonly property color error_container: "#ffdad6" - // readonly property color inverse_on_surface: "#ecf2f2" - // readonly property color inverse_primary: "#80d4da" - // readonly property color inverse_surface: "#2b3232" - // readonly property color on_background: "#161d1d" - // readonly property color on_error: "#ffffff" - // readonly property color on_error_container: "#410002" - // readonly property color on_primary: "#ffffff" - // readonly property color on_primary_container: "#002022" - // readonly property color on_primary_fixed: "#002022" - // readonly property color on_primary_fixed_variant: "#004f53" - // readonly property color on_secondary: "#ffffff" - // readonly property color on_secondary_container: "#041f21" - // readonly property color on_secondary_fixed: "#041f21" - // readonly property color on_secondary_fixed_variant: "#324b4d" - // readonly property color on_surface: "#161d1d" - // readonly property color on_surface_variant: "#3f4949" - // readonly property color on_tertiary: "#ffffff" - // readonly property color on_tertiary_container: "#091b36" - // readonly property color on_tertiary_fixed: "#091b36" - // readonly property color on_tertiary_fixed_variant: "#374764" - // readonly property color outline: "#6f7979" - // readonly property color outline_variant: "#bec8c9" - // readonly property color primary: "#00696e" - // readonly property color primary_container: "#9cf0f6" - // readonly property color primary_fixed: "#9cf0f6" - // readonly property color primary_fixed_dim: "#80d4da" - // readonly property color scrim: "#000000" - // readonly property color secondary: "#4a6365" - // readonly property color secondary_container: "#cce8e9" - // readonly property color secondary_fixed: "#cce8e9" - // readonly property color secondary_fixed_dim: "#b1cccd" - // readonly property color shadow: "#000000" - // readonly property color source_color: "#478185" - // readonly property color surface: "#f4fafb" - // readonly property color surface_bright: "#f4fafb" - // readonly property color surface_container: "#e9efef" - // readonly property color surface_container_high: "#e3e9e9" - // readonly property color surface_container_highest: "#dde4e4" - // readonly property color surface_container_low: "#eff5f5" - // readonly property color surface_container_lowest: "#ffffff" - // readonly property color surface_dim: "#d5dbdb" - // readonly property color surface_tint: "#00696e" - // readonly property color surface_variant: "#dae4e5" - // readonly property color tertiary: "#4e5f7d" - // readonly property color tertiary_container: "#d6e3ff" - // readonly property color tertiary_fixed: "#d6e3ff" - // readonly property color tertiary_fixed_dim: "#b6c7e9" - readonly property color background: "#121318" readonly property color error: "#ffb4ab" readonly property color error_container: "#93000a" diff --git a/basic_bar/Generics/MouseArea.qml b/basic_bar/Generics/MouseArea.qml index dd5295d..a7c6315 100644 --- a/basic_bar/Generics/MouseArea.qml +++ b/basic_bar/Generics/MouseArea.qml @@ -1,5 +1,4 @@ import QtQuick -import "../Data/" as Dat MouseArea { id: area diff --git a/basic_bar/Generics/Notification.qml b/basic_bar/Generics/Notification.qml deleted file mode 100644 index 32ad703..0000000 --- a/basic_bar/Generics/Notification.qml +++ /dev/null @@ -1,181 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import QtQuick.Effects -import Quickshell -import Quickshell.Services.Notifications -import Quickshell.Hyprland - -import "../Data/" as Dat -import "../Generics/" as Gen - -Rectangle { - id: root - - required property Notification notif - - color: "transparent" - height: bodyNActionCol.height - - Behavior on x { - SmoothedAnimation { - } - } - - onXChanged: { - root.opacity = 1 - (Math.abs(root.x) / width); - } - - MouseArea { - id: dragArea - - anchors.fill: parent - - drag { - axis: Drag.XAxis - target: parent - - onActiveChanged: { - if (dragArea.drag.active) { - return; - } - if (Math.abs(root.x) > (root.width / 2)) { - root.notif.dismiss(); - } else { - root.x = 0; - } - } - } - } - - ColumnLayout { - id: bodyNActionCol - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - spacing: 0 - - Rectangle { - Layout.fillWidth: true - Layout.margins: 10 - color: "transparent" - implicitHeight: sumText.contentHeight + bodText.contentHeight - topLeftRadius: 20 - topRightRadius: 20 - - RowLayout { - id: infoRow - - anchors.top: parent.top - height: sumText.contentHeight - width: parent.width - - Text { - id: sumText - - Layout.maximumWidth: root.width * 0.8 - color: Dat.Colors.primary - elide: Text.ElideRight - text: root.notif?.summary ?? "summary" - } - - Rectangle { - Layout.alignment: Qt.AlignRight - color: "transparent" - implicitHeight: appText.contentHeight + 2 - implicitWidth: appText.contentWidth + 10 - radius: 20 - - Text { - id: appText - - anchors.centerIn: parent - color: Dat.Colors.tertiary - font.bold: true - font.pointSize: 8 - text: root.notif?.appName ?? "idk" - } - } - } - - Text { - id: bodText - - anchors.top: infoRow.bottom - color: Dat.Colors.on_surface - font.pointSize: 11 - text: root.notif?.body ?? "very cool body that is missing" - textFormat: Text.MarkdownText - width: parent.width - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - - MouseArea { - id: bodMArea - - acceptedButtons: Qt.LeftButton - anchors.fill: parent - - // thanks end_4 for this <3 - onClicked: { - const hovLink = bodText.hoveredLink; - if (hovLink == "") { - return; - } - Hyprland.dispatch("exec xdg-open " + hovLink); - } - } - } - } - - Flickable { - id: flick - - Layout.alignment: Qt.AlignRight - Layout.bottomMargin: 10 - Layout.leftMargin: this.Layout.rightMargin - Layout.rightMargin: 10 - boundsBehavior: Flickable.StopAtBounds - clip: true - contentWidth: actionRow.width - implicitHeight: 23 - // thanks to Aureus :> - implicitWidth: Math.min(bodyNActionCol.width - 20, actionRow.width) - - RowLayout { - id: actionRow - - anchors.right: parent.right - height: parent.height - - Repeater { - model: root.notif?.actions - - Rectangle { - required property NotificationAction modelData - - Layout.fillHeight: true - color: Dat.Colors.secondary - implicitWidth: actionText.contentWidth + 14 - radius: 20 - - Text { - id: actionText - - anchors.centerIn: parent - color: Dat.Colors.on_secondary - font.pointSize: 11 - text: parent.modelData?.text ?? "activate" - } - - Gen.MouseArea { - layerColor: actionText.color - - onClicked: parent.modelData.invoke() - } - } - } - } - } - } -} diff --git a/basic_bar/Layers/Top.qml b/basic_bar/Layers/Top.qml index 845463e..618a6d5 100644 --- a/basic_bar/Layers/Top.qml +++ b/basic_bar/Layers/Top.qml @@ -2,8 +2,6 @@ import QtQuick import QtQuick.Layouts import Quickshell import Quickshell.Wayland - -import "../Data/" as Dat import "../Containers/" as Con Scope { diff --git a/basic_bar/Widgets/Clock.qml b/basic_bar/Widgets/Clock.qml index 301ddce..9a32f1d 100644 --- a/basic_bar/Widgets/Clock.qml +++ b/basic_bar/Widgets/Clock.qml @@ -1,7 +1,5 @@ import QtQuick import QtQuick.Layouts -import Quickshell -import Quickshell.Wayland import "../Data/" as Dat import "../Generics/" as Gen diff --git a/basic_bar/Widgets/OsText.qml b/basic_bar/Widgets/OsText.qml index 00f787f..142f5f0 100644 --- a/basic_bar/Widgets/OsText.qml +++ b/basic_bar/Widgets/OsText.qml @@ -1,7 +1,5 @@ import QtQuick import QtQuick.Layouts -import Quickshell -import Quickshell.Wayland import "../Data/" as Dat import "../Generics/" as Gen diff --git a/basic_bar/Widgets/PowerProfs.qml b/basic_bar/Widgets/PowerProfs.qml index 08d40d3..ac74168 100644 --- a/basic_bar/Widgets/PowerProfs.qml +++ b/basic_bar/Widgets/PowerProfs.qml @@ -1,7 +1,6 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts -import Quickshell.Hyprland import Quickshell.Services.UPower import "../Data/" as Dat diff --git a/basic_bar/Widgets/Session.qml b/basic_bar/Widgets/Session.qml index 4335c60..4724eaa 100644 --- a/basic_bar/Widgets/Session.qml +++ b/basic_bar/Widgets/Session.qml @@ -1,7 +1,6 @@ import QtQuick import QtQuick.Layouts import Quickshell -import Quickshell.Wayland import "../Data/" as Dat import "../Generics/" as Gen diff --git a/basic_bar/Widgets/WorkspaceName.qml b/basic_bar/Widgets/WorkspaceName.qml index 1e7f127..b121176 100644 --- a/basic_bar/Widgets/WorkspaceName.qml +++ b/basic_bar/Widgets/WorkspaceName.qml @@ -1,10 +1,7 @@ import QtQuick import QtQuick.Layouts -import Quickshell import Quickshell.Wayland - import "../Data/" as Dat -import "../Generics/" as Gen Rectangle { id: root diff --git a/basic_bar/Widgets/Workspaces.qml b/basic_bar/Widgets/Workspaces.qml index 209a8d6..2564239 100644 --- a/basic_bar/Widgets/Workspaces.qml +++ b/basic_bar/Widgets/Workspaces.qml @@ -1,7 +1,6 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts -import Quickshell import Quickshell.Hyprland import "../Data/" as Dat From db59f325710a4080e3a9cbfa88d5e65496fd8d95 Mon Sep 17 00:00:00 2001 From: Rexiel Scarlet <37258415+Rexcrazy804@users.noreply.github.com> Date: Mon, 16 Jun 2025 17:21:36 +0400 Subject: [PATCH 3/4] create source and sink widgets + fix the dumb code in Audio.qml --- basic_bar/Containers/Right.qml | 8 +++++ basic_bar/Data/Audio.qml | 10 +++++-- basic_bar/Widgets/OsText.qml | 1 + basic_bar/Widgets/Sound.qml | 54 ++++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 basic_bar/Widgets/Sound.qml diff --git a/basic_bar/Containers/Right.qml b/basic_bar/Containers/Right.qml index a97d1c2..4b705d4 100644 --- a/basic_bar/Containers/Right.qml +++ b/basic_bar/Containers/Right.qml @@ -1,5 +1,6 @@ import QtQuick import QtQuick.Layouts +import Quickshell.Services.Pipewire import "../Widgets/" as Wid Item { @@ -14,5 +15,12 @@ Item { Wid.PowerProfs { } + + Wid.Sound { + } + + Wid.Sound { + node: Pipewire.defaultAudioSource + } } } diff --git a/basic_bar/Data/Audio.qml b/basic_bar/Data/Audio.qml index bfcf11f..4de32d0 100644 --- a/basic_bar/Data/Audio.qml +++ b/basic_bar/Data/Audio.qml @@ -7,12 +7,16 @@ import Quickshell.Services.Pipewire Singleton { id: root + function getIcon(node: PwNode): string { + return (node.isSink) ? getSinkIcon(node) : getSourceIcon(node); + } + function getSinkIcon(node: PwNode): string { - return (node.muted) ? "󰝟" : (node.volume > 0.5) ? "󰕾" : (node.volume > 0.01) ? "󰖀" : "󰕿"; + return (node.audio.muted) ? "󰝟" : (node.audio.volume > 0.5) ? "󰕾" : (node.audio.volume > 0.01) ? "󰖀" : "󰕿"; } function getSourceIcon(node: PwNode): string { - return (node.muted) ? "󰍭" : "󰍬"; + return (node.audio.muted) ? "󰍭" : "󰍬"; } function toggleMute(node: PwNode) { @@ -29,7 +33,7 @@ Singleton { if (node.audio.volume > 1.3) { node.audio.volume = 1.3; } - if (root.sink.audio.volume < 0) { + if (node.audio.volume < 0) { node.audio.volume = 0.0; } } diff --git a/basic_bar/Widgets/OsText.qml b/basic_bar/Widgets/OsText.qml index 142f5f0..ce2bd0e 100644 --- a/basic_bar/Widgets/OsText.qml +++ b/basic_bar/Widgets/OsText.qml @@ -20,6 +20,7 @@ Rectangle { font.family: Dat.Fonts.caskaydia text: "󱄅" } + text { color: Dat.Colors.tertiary text: "NixOS" diff --git a/basic_bar/Widgets/Sound.qml b/basic_bar/Widgets/Sound.qml new file mode 100644 index 0000000..f036ba1 --- /dev/null +++ b/basic_bar/Widgets/Sound.qml @@ -0,0 +1,54 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell.Services.Pipewire + +import "../Data/" as Dat +import "../Generics/" as Gen + +Rectangle { + id: root + + property string icon: Dat.Audio.getIcon(root.node) + property PwNode node: Pipewire.defaultAudioSink + property int padding: 20 + + Layout.fillHeight: true + color: Dat.Colors.withAlpha(Dat.Colors.background, 0.79) + implicitWidth: container.width + padding + radius: 5 + + Behavior on implicitWidth { + NumberAnimation { + duration: 200 + easing.type: Easing.InOutQuad + } + } + + PwObjectTracker { + objects: [root.node] + } + + Gen.WaybarItem { + id: container + + spacing: 10 + + icon { + color: Dat.Colors.on_background + text: root.icon + } + + text { + color: Dat.Colors.on_background + text: (node.audio.volume * 100).toFixed(0) + "%" + } + } + + MouseArea { + acceptedButtons: Qt.MiddleButton + anchors.fill: parent + + onClicked: mevent => Dat.Audio.toggleMute(root.node) + onWheel: mevent => Dat.Audio.wheelAction(mevent, root.node) + } +} From 7a75b0f395587041c7c695e75c0d065a88bf8b4e Mon Sep 17 00:00:00 2001 From: Rexiel Scarlet <37258415+Rexcrazy804@users.noreply.github.com> Date: Mon, 16 Jun 2025 17:33:43 +0400 Subject: [PATCH 4/4] inclusion of battery widget --- basic_bar/Containers/Right.qml | 3 ++ basic_bar/Widgets/Battery.qml | 54 ++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 basic_bar/Widgets/Battery.qml diff --git a/basic_bar/Containers/Right.qml b/basic_bar/Containers/Right.qml index 4b705d4..489321c 100644 --- a/basic_bar/Containers/Right.qml +++ b/basic_bar/Containers/Right.qml @@ -22,5 +22,8 @@ Item { Wid.Sound { node: Pipewire.defaultAudioSource } + + Wid.Battery { + } } } diff --git a/basic_bar/Widgets/Battery.qml b/basic_bar/Widgets/Battery.qml new file mode 100644 index 0000000..0b5f388 --- /dev/null +++ b/basic_bar/Widgets/Battery.qml @@ -0,0 +1,54 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell.Services.UPower + +import "../Data/" as Dat +import "../Generics/" as Gen + +Rectangle { + id: root + + readonly property bool batCharging: UPower.displayDevice.state == UPowerDeviceState.Charging + readonly property string batIcon: { + (batPercentage > 0.98) ? batIcons[0] : (batPercentage > 0.90) ? batIcons[1] : (batPercentage > 0.80) ? batIcons[2] : (batPercentage > 0.70) ? batIcons[3] : (batPercentage > 0.60) ? batIcons[4] : (batPercentage > 0.50) ? batIcons[5] : (batPercentage > 0.40) ? batIcons[6] : (batPercentage > 0.30) ? batIcons[7] : (batPercentage > 0.20) ? batIcons[8] : (batPercentage > 0.10) ? batIcons[9] : batIcons[10]; + } + readonly property list batIcons: ["󰁹", "󰂂", "󰂁", "󰂀", "󰁿", "󰁾", "󰁽", "󰁼", "󰁻", "󰁺", "󰂃"] + readonly property real batPercentage: UPower.displayDevice.percentage + readonly property string chargeIcon: batIcons[10 - chargeIconIndex] + property int chargeIconIndex: 0 + property int padding: 16 + + Layout.fillHeight: true + color: Dat.Colors.withAlpha(Dat.Colors.background, 0.79) + implicitWidth: container.width + padding + radius: 5 + + Gen.WaybarItem { + id: container + + spacing: 10 + + icon { + color: Dat.Colors.tertiary + font.family: Dat.Fonts.caskaydia + text: (batCharging) ? root.chargeIcon : root.batIcon + } + + text { + color: Dat.Colors.tertiary + text: (UPower.displayDevice.percentage * 100).toFixed(0) + "%" + } + } + + Timer { + interval: 600 + repeat: true + running: root.batCharging + triggeredOnStart: true + + onTriggered: () => { + root.chargeIconIndex = root.chargeIconIndex % 10; + root.chargeIconIndex += 1; + } + } +}