initial addition of battery display
JS/TS / fmt (pull_request) Successful in 7s
JS/TS / lint (pull_request) Successful in 9s
Python / fmt (pull_request) Successful in 15s
Python / lint (pull_request) Failing after 19s
Python / typecheck (pull_request) Failing after 1m5s
C++ / fmt (pull_request) Successful in 6s
Python / test (pull_request) Successful in 1m20s
Rust / fmt (pull_request) Successful in 1m42s
Python / buildcheck (pull_request) Successful in 2m23s
Rust / clippy (pull_request) Successful in 2m42s
Rust / build (pull_request) Successful in 2m53s
C++ / build (pull_request) Successful in 2m22s
C++ / clang-tidy (pull_request) Successful in 3m17s

This commit is contained in:
2026-07-12 17:47:25 +02:00
parent 93c6ac251e
commit 8789d2d322
6 changed files with 405 additions and 89 deletions
+84
View File
@@ -0,0 +1,84 @@
import QtQuick
import qs.Config
import qs.Components
import qs.Helpers
Row {
id: root
property real batHeight: Appearance.padding.smaller * 2
property real batWidth: Appearance.padding.larger * 2
required property string devState
property real nubHeight: Appearance.padding.small
property real nubWidth: 2
required property real percentage
property real radius: Appearance.rounding.smallest / 2
spacing: 1
CustomRect {
id: track
anchors.verticalCenter: parent.verticalCenter
color: Battery.getColors(root.percentage, root.devState).bg
height: root.batHeight
radius: root.radius
width: root.batWidth
CustomText {
color: Battery.getColors(root.percentage, root.devState).fg
font.pointSize: Appearance.font.size.larger / 1.5
font.weight: 800
height: track.height
horizontalAlignment: Text.AlignHCenter
text: Math.round(root.percentage * 100)
verticalAlignment: Text.AlignVCenter
width: track.width
}
Item {
clip: true
width: parent.width * root.percentage
anchors {
bottom: parent.bottom
left: parent.left
top: parent.top
}
CustomRect {
id: fill
color: Battery.getColors(root.percentage, root.devState).fg
height: track.height
radius: track.radius
width: track.width
CustomText {
id: batteryLabel
clip: true
color: Battery.getColors(root.percentage, root.devState).bg
font.pointSize: Appearance.font.size.larger / 1.5
font.weight: 800
height: track.height
horizontalAlignment: Text.AlignHCenter
text: Math.round(root.percentage * 100)
verticalAlignment: Text.AlignVCenter
width: track.width
}
}
}
}
CustomRect {
id: nub
anchors.verticalCenter: parent.verticalCenter
bottomRightRadius: 20
color: root.percentage < 0.99 ? track.color : fill.color
height: root.nubHeight
topRightRadius: 20
width: root.nubWidth
}
}
+27
View File
@@ -1,7 +1,9 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell.Services.UPower
import qs.Modules.SysTray.Common
import qs.Config
import qs.Helpers
import qs.Components
@@ -21,6 +23,31 @@ Column {
}
}
Repeater {
model: [...Battery.logiDevices] // ...Battery.upowerDevices]
RowLayout {
id: layout
required property var modelData
anchors.left: parent.left
anchors.leftMargin: Appearance.padding.normal
anchors.right: parent.right
anchors.rightMargin: Appearance.padding.normal
CustomText {
Layout.fillWidth: true
text: layout.modelData.name
}
BatteryIcon {
devState: layout.modelData.state
percentage: layout.modelData.percentage
}
}
}
CustomText {
function formatSeconds(s: int, fallback: string): string {
const day = Math.floor(s / 86400);
+17 -76
View File
@@ -1,6 +1,7 @@
import Quickshell.Services.UPower
import QtQuick
import QtQuick.Layouts
import qs.Modules.SysTray.Common
import qs.Components
import qs.Config
import qs.Helpers
@@ -8,12 +9,13 @@ import qs.Helpers
Item {
id: root
readonly property Item currentItem: batteryIconLoader?.item ?? peripheralIconLoader?.item ?? upowerIconLoader.item
readonly property bool shouldBeActive: Config.bar.tray.showPower
Layout.preferredHeight: shouldBeActive ? implicitHeight : 0
Layout.preferredWidth: shouldBeActive ? implicitWidth : 0
implicitHeight: Battery.isLaptop ? batteryIconLoader.item.implicitHeight : upowerIconLoader.item.implicitHeight
implicitWidth: Battery.isLaptop ? batteryIconLoader.item.implicitWidth : upowerIconLoader.item.implicitWidth
implicitHeight: currentItem?.implicitHeight ?? 0
implicitWidth: currentItem?.implicitWidth ?? 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0
visible: opacity > 0
@@ -41,89 +43,28 @@ Item {
active: Battery.isLaptop
anchors.centerIn: parent
sourceComponent: Row {
id: batteryIcon
sourceComponent: BatteryIcon {
devState: Battery.deviceStateString
percentage: Battery.currentPerc
}
}
property real batHeight: 16
property real batWidth: 30
property real nubHeight: 6
property real nubWidth: 2
property real radius: Appearance.rounding.smallest / 2
Loader {
id: peripheralIconLoader
spacing: 1
active: Battery.logiDevices.some(d => d.isPresent) && !batteryIconLoader.active
anchors.centerIn: parent
CustomRect {
id: track
anchors.verticalCenter: parent.verticalCenter
color: Battery.colors.bg
height: batteryIcon.batHeight
radius: batteryIcon.radius
width: batteryIcon.batWidth
CustomText {
color: Battery.colors.fg
font.pointSize: Appearance.font.size.larger / 1.5
font.weight: 800
height: track.height
horizontalAlignment: Text.AlignHCenter
text: Math.round(Battery.currentPerc * 100)
verticalAlignment: Text.AlignVCenter
width: track.width
}
Item {
clip: true
width: parent.width * Battery.currentPerc
anchors {
bottom: parent.bottom
left: parent.left
top: parent.top
}
CustomRect {
id: fill
color: Battery.colors.fg
height: track.height
radius: track.radius
width: track.width
CustomText {
id: batteryLabel
clip: true
color: Battery.colors.bg
font.pointSize: 7.5
font.weight: 800
height: track.height
horizontalAlignment: Text.AlignHCenter
text: Math.round(Battery.currentPerc * 100)
verticalAlignment: Text.AlignVCenter
width: track.width
}
}
}
}
CustomRect {
id: nub
anchors.verticalCenter: parent.verticalCenter
bottomRightRadius: 20
color: Battery.currentPerc < 0.99 ? track.color : fill.color
height: batteryIcon.nubHeight
topRightRadius: 20
width: batteryIcon.nubWidth
}
sourceComponent: BatteryIcon {
devState: Battery.logiDevices[0].state
percentage: Battery.logiDevices[0].percentage
}
}
Loader {
id: upowerIconLoader
active: !Battery.isLaptop
active: !batteryIconLoader.active && !peripheralIconLoader.active
anchors.centerIn: parent
sourceComponent: MaterialIcon {