forked from Shinonome/dots-hyprland
Added a small battery popup to show information
This commit is contained in:
@@ -3,8 +3,9 @@ import qs.modules.common.widgets
|
|||||||
import qs.services
|
import qs.services
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
|
||||||
Item {
|
MouseArea {
|
||||||
id: root
|
id: root
|
||||||
property bool borderless: Config.options.bar.borderless
|
property bool borderless: Config.options.bar.borderless
|
||||||
readonly property var chargeState: Battery.chargeState
|
readonly property var chargeState: Battery.chargeState
|
||||||
@@ -18,6 +19,8 @@ Item {
|
|||||||
implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2
|
implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2
|
||||||
implicitHeight: 32
|
implicitHeight: 32
|
||||||
|
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: rowLayout
|
id: rowLayout
|
||||||
|
|
||||||
@@ -92,4 +95,25 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LazyLoader {
|
||||||
|
id: popupLoader
|
||||||
|
active: root.containsMouse
|
||||||
|
|
||||||
|
component: PopupWindow {
|
||||||
|
id: popupWindow
|
||||||
|
visible: true
|
||||||
|
implicitWidth: batteryPopup.implicitWidth
|
||||||
|
implicitHeight: batteryPopup.implicitHeight
|
||||||
|
anchor.item: root
|
||||||
|
anchor.rect.x: (root.implicitWidth - popupWindow.implicitWidth) / 2
|
||||||
|
anchor.rect.y: Config.options.bar.bottom
|
||||||
|
? (-batteryPopup.implicitHeight - 15)
|
||||||
|
: (root.implicitHeight + 15)
|
||||||
|
color: "transparent"
|
||||||
|
BatteryPopup {
|
||||||
|
id: batteryPopup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
import qs.modules.common
|
||||||
|
import qs.modules.common.widgets
|
||||||
|
import qs.services
|
||||||
|
import qs
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
readonly property real margin: 10
|
||||||
|
implicitWidth: columnLayout.implicitWidth + margin * 2
|
||||||
|
implicitHeight: columnLayout.implicitHeight + margin * 2
|
||||||
|
color: Appearance.colors.colLayer0
|
||||||
|
radius: Appearance.rounding.small
|
||||||
|
border.width: 1
|
||||||
|
border.color: Appearance.colors.colLayer0Border
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: columnLayout
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: 5
|
||||||
|
Layout.fillWidth: true
|
||||||
|
MaterialSymbol { text: "thermostat"; color: Appearance.m3colors.m3onSecondaryContainer }
|
||||||
|
StyledText { text: Translation.tr("Temperature:"); color: Appearance.colors.colOnLayer1 }
|
||||||
|
StyledText { Layout.fillWidth: true; horizontalAlignment: Text.AlignRight; color: Appearance.colors.colOnLayer1; text: `${Battery.temperature}°C` }
|
||||||
|
}
|
||||||
|
|
||||||
|
// This row is hidden when the battery is full.
|
||||||
|
RowLayout {
|
||||||
|
spacing: 5
|
||||||
|
Layout.fillWidth: true
|
||||||
|
property bool rowVisible: {
|
||||||
|
let timeValue = Battery.isCharging ? Battery.timeToFull : Battery.timeToEmpty;
|
||||||
|
let power = Battery.energyRate;
|
||||||
|
return !(Battery.chargeState == 4 || timeValue <= 0 || power <= 0.01);
|
||||||
|
}
|
||||||
|
visible: rowVisible
|
||||||
|
opacity: rowVisible ? 1 : 0
|
||||||
|
Behavior on opacity { NumberAnimation { duration: 500 } }
|
||||||
|
|
||||||
|
MaterialSymbol { text: "schedule"; color: Appearance.m3colors.m3onSecondaryContainer }
|
||||||
|
StyledText { text: Battery.isCharging ? Translation.tr("Time to full:") : Translation.tr("Time to empty:"); color: Appearance.colors.colOnLayer1 }
|
||||||
|
StyledText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
color: Appearance.colors.colOnLayer1
|
||||||
|
text: {
|
||||||
|
function formatTime(seconds) {
|
||||||
|
var h = Math.floor(seconds / 3600);
|
||||||
|
var m = Math.floor((seconds % 3600) / 60);
|
||||||
|
if (h > 0)
|
||||||
|
return `${h}h ${m}m`;
|
||||||
|
else
|
||||||
|
return `${m}m`;
|
||||||
|
}
|
||||||
|
if (Battery.isCharging)
|
||||||
|
return formatTime(Battery.timeToFull);
|
||||||
|
else
|
||||||
|
return formatTime(Battery.timeToEmpty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: 5
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
property bool rowVisible: !(Battery.chargeState != 4 && Battery.energyRate == 0)
|
||||||
|
visible: rowVisible
|
||||||
|
opacity: rowVisible ? 1 : 0
|
||||||
|
Behavior on opacity { NumberAnimation { duration: 500 } }
|
||||||
|
|
||||||
|
MaterialSymbol {
|
||||||
|
text: {
|
||||||
|
if (Battery.isCharging) {
|
||||||
|
return "power";
|
||||||
|
} else if (Battery.percentage >= 0.8) {
|
||||||
|
return "battery_full";
|
||||||
|
} else if (Battery.percentage >= 0.6) {
|
||||||
|
return "battery_5_bar";
|
||||||
|
} else if (Battery.percentage >= 0.4) {
|
||||||
|
return "battery_4_bar";
|
||||||
|
} else if (Battery.percentage >= 0.2) {
|
||||||
|
return "battery_2_bar";
|
||||||
|
} else {
|
||||||
|
return "battery_0_bar";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
color: Appearance.m3colors.m3onSecondaryContainer
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: {
|
||||||
|
if (Battery.chargeState == 4) {
|
||||||
|
return Translation.tr("Fully charged");
|
||||||
|
} else if (Battery.chargeState == 1) {
|
||||||
|
return Translation.tr("Charging:");
|
||||||
|
} else {
|
||||||
|
return Translation.tr("Discharging:");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
color: Appearance.colors.colOnLayer1
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
color: Appearance.colors.colOnLayer1
|
||||||
|
text: {
|
||||||
|
if (Battery.chargeState == 4) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return `${Battery.energyRate.toFixed(2)}W`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ import qs
|
|||||||
import qs.modules.common
|
import qs.modules.common
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.UPower
|
import Quickshell.Services.UPower
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell.Io
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
property bool available: UPower.displayDevice.isLaptopBattery
|
property bool available: UPower.displayDevice.isLaptopBattery
|
||||||
@@ -21,6 +23,43 @@ Singleton {
|
|||||||
property bool isCriticalAndNotCharging: isCritical && !isCharging
|
property bool isCriticalAndNotCharging: isCritical && !isCharging
|
||||||
property bool isSuspendingAndNotCharging: allowAutomaticSuspend && isSuspending && !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
|
||||||
|
property real temperature: 0
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: tempProcess
|
||||||
|
command: ["bash", "-c", "cat /sys/class/thermal/thermal_zone0/temp"]
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
if (text && text.trim() !== "") {
|
||||||
|
Battery.temperature = parseInt(text.trim()) / 1000
|
||||||
|
} else {
|
||||||
|
Battery.temperature = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
interval: 3000
|
||||||
|
repeat: true
|
||||||
|
running: true
|
||||||
|
onTriggered: {
|
||||||
|
if (!tempProcess.running) {
|
||||||
|
tempProcess.running = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (!tempProcess.running) {
|
||||||
|
tempProcess.running = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
onIsLowAndNotChargingChanged: {
|
onIsLowAndNotChargingChanged: {
|
||||||
if (available && isLowAndNotCharging) Quickshell.execDetached([
|
if (available && isLowAndNotCharging) Quickshell.execDetached([
|
||||||
"notify-send",
|
"notify-send",
|
||||||
|
|||||||
@@ -310,5 +310,11 @@
|
|||||||
"Sunrise": "Sunrise",
|
"Sunrise": "Sunrise",
|
||||||
"Pressure": "Pressure",
|
"Pressure": "Pressure",
|
||||||
"Visibility": "Visibility",
|
"Visibility": "Visibility",
|
||||||
"Precipitation": "Precipitation"
|
"Precipitation": "Precipitation",
|
||||||
|
"Temperature:": "Temperature:",
|
||||||
|
"Time to full:": "Time to full:",
|
||||||
|
"Time to empty:": "Time to empty:",
|
||||||
|
"Fully charged": "Fully charged",
|
||||||
|
"Charging:": "Charging:",
|
||||||
|
"Discharging:": "Discharging:"
|
||||||
}
|
}
|
||||||
@@ -310,5 +310,11 @@
|
|||||||
"Sunset": "日落",
|
"Sunset": "日落",
|
||||||
"Humidity": "湿度",
|
"Humidity": "湿度",
|
||||||
"Wind": "风",
|
"Wind": "风",
|
||||||
"Precipitation": "降水量"
|
"Precipitation": "降水量",
|
||||||
|
"Temperature:": "温度:",
|
||||||
|
"Time to full:": "距离充满:",
|
||||||
|
"Time to empty:": "距离耗尽:",
|
||||||
|
"Fully charged": "已充满电",
|
||||||
|
"Charging:": "充电功率:",
|
||||||
|
"Discharging:": "放电功率:"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user