diff --git a/.config/quickshell/ii/modules/bar/BatteryIndicator.qml b/.config/quickshell/ii/modules/bar/BatteryIndicator.qml index fa5d5daf4..e437f1d42 100644 --- a/.config/quickshell/ii/modules/bar/BatteryIndicator.qml +++ b/.config/quickshell/ii/modules/bar/BatteryIndicator.qml @@ -3,8 +3,9 @@ import qs.modules.common.widgets import qs.services import QtQuick import QtQuick.Layouts +import Quickshell -Item { +MouseArea { id: root property bool borderless: Config.options.bar.borderless readonly property var chargeState: Battery.chargeState @@ -18,6 +19,8 @@ Item { implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2 implicitHeight: 32 + hoverEnabled: true + RowLayout { id: rowLayout @@ -55,9 +58,7 @@ Item { iconSize: Appearance.font.pixelSize.normal color: (isLow && !isCharging) ? batteryLowOnBackground : Appearance.m3colors.m3onSecondaryContainer } - } - } Loader { @@ -69,7 +70,8 @@ Item { Connections { target: root function onIsChargingChanged() { - if (isCharging) boltIconLoader.active = true + if (isCharging) + boltIconLoader.active = true; } } @@ -82,14 +84,18 @@ Item { visible: opacity > 0 // Only show when charging opacity: isCharging ? 1 : 0 // Keep opacity for visibility onVisibleChanged: { - if (!visible) boltIconLoader.active = false + if (!visible) + boltIconLoader.active = false; } Behavior on opacity { animation: Appearance.animation.elementMove.numberAnimation.createObject(this) } - } } + BatteryPopup { + id: batteryPopup + hoverTarget: root + } } diff --git a/.config/quickshell/ii/modules/bar/BatteryPopup.qml b/.config/quickshell/ii/modules/bar/BatteryPopup.qml new file mode 100644 index 000000000..c697bfbda --- /dev/null +++ b/.config/quickshell/ii/modules/bar/BatteryPopup.qml @@ -0,0 +1,132 @@ +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import qs +import QtQuick +import QtQuick.Layouts + +StyledPopup { + id: root + + ColumnLayout { + id: columnLayout + anchors.centerIn: parent + spacing: 4 + + // Header + RowLayout { + id: header + spacing: 5 + + MaterialSymbol { + fill: 0 + font.weight: Font.Medium + text: "battery_android_full" + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnSurfaceVariant + } + + StyledText { + text: "Battery" + font { + weight: Font.Medium + pixelSize: Appearance.font.pixelSize.normal + } + color: Appearance.colors.colOnSurfaceVariant + } + } + + // 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.colors.colOnSurfaceVariant + iconSize: Appearance.font.pixelSize.large + } + StyledText { + text: Battery.isCharging ? Translation.tr("Time to full:") : Translation.tr("Time to empty:") + color: Appearance.colors.colOnSurfaceVariant + } + StyledText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignRight + color: Appearance.colors.colOnSurfaceVariant + 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: "bolt" + color: Appearance.colors.colOnSurfaceVariant + iconSize: Appearance.font.pixelSize.large + } + + 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.colOnSurfaceVariant + } + + StyledText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignRight + color: Appearance.colors.colOnSurfaceVariant + text: { + if (Battery.chargeState == 4) { + return ""; + } else { + return `${Battery.energyRate.toFixed(2)}W`; + } + } + } + } + } +} diff --git a/.config/quickshell/ii/modules/bar/ClockWidget.qml b/.config/quickshell/ii/modules/bar/ClockWidget.qml index 9f45aa0af..6f335de23 100644 --- a/.config/quickshell/ii/modules/bar/ClockWidget.qml +++ b/.config/quickshell/ii/modules/bar/ClockWidget.qml @@ -1,8 +1,10 @@ +import qs import qs.modules.common import qs.modules.common.widgets import qs.services import QtQuick import QtQuick.Layouts +import Quickshell Item { id: root @@ -35,7 +37,16 @@ Item { color: Appearance.colors.colOnLayer1 text: DateTime.date } - } + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.NoButton + + ClockWidgetTooltip { + hoverTarget: mouseArea + } + } } diff --git a/.config/quickshell/ii/modules/bar/ClockWidgetTooltip.qml b/.config/quickshell/ii/modules/bar/ClockWidgetTooltip.qml new file mode 100644 index 000000000..ea11336a9 --- /dev/null +++ b/.config/quickshell/ii/modules/bar/ClockWidgetTooltip.qml @@ -0,0 +1,109 @@ +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import QtQuick +import QtQuick.Layouts + +StyledPopup { + id: root + property string formattedDate: Qt.locale().toString(DateTime.clock.date, "dddd, MMMM dd, yyyy") + property string formattedTime: DateTime.time + property string formattedUptime: DateTime.uptime + property string todosSection: getUpcomingTodos() + + function getUpcomingTodos() { + const unfinishedTodos = Todo.list.filter(function (item) { + return !item.done; + }); + if (unfinishedTodos.length === 0) { + return Translation.tr("No pending tasks"); + } + + // Limit to first 5 todos to keep popup manageable + const limitedTodos = unfinishedTodos.slice(0, 5); + let todoText = limitedTodos.map(function (item, index) { + return `${index + 1}. ${item.content}`; + }).join('\n'); + + if (unfinishedTodos.length > 5) { + todoText += `\n${Translation.tr("... and %1 more").arg(unfinishedTodos.length - 5)}`; + } + + return todoText; + } + + ColumnLayout { + id: columnLayout + anchors.centerIn: parent + spacing: 4 + + // Date + Time row + RowLayout { + spacing: 5 + + MaterialSymbol { + fill: 0 + font.weight: Font.Medium + text: "calendar_month" + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnSurfaceVariant + } + StyledText { + horizontalAlignment: Text.AlignLeft + color: Appearance.colors.colOnSurfaceVariant + text: `${root.formattedDate} • ${root.formattedTime}` + font.weight: Font.Medium + } + } + + // Uptime row + RowLayout { + spacing: 5 + Layout.fillWidth: true + MaterialSymbol { + text: "timelapse" + color: Appearance.colors.colOnSurfaceVariant + font.pixelSize: Appearance.font.pixelSize.large + } + StyledText { + text: Translation.tr("System uptime:") + color: Appearance.colors.colOnSurfaceVariant + } + StyledText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignRight + color: Appearance.colors.colOnSurfaceVariant + text: root.formattedUptime + } + } + + // Tasks + ColumnLayout { + spacing: 0 + Layout.fillWidth: true + + RowLayout { + spacing: 4 + Layout.fillWidth: true + MaterialSymbol { + text: "checklist" + color: Appearance.colors.colOnSurfaceVariant + font.pixelSize: Appearance.font.pixelSize.large + } + StyledText { + text: Translation.tr("To Do:") + color: Appearance.colors.colOnSurfaceVariant + } + } + + StyledText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignLeft + wrapMode: Text.Wrap + color: Appearance.colors.colOnSurfaceVariant + text: root.todosSection + } + } + } +} diff --git a/.config/quickshell/ii/modules/bar/Resource.qml b/.config/quickshell/ii/modules/bar/Resource.qml index 12c799111..65b22e15d 100644 --- a/.config/quickshell/ii/modules/bar/Resource.qml +++ b/.config/quickshell/ii/modules/bar/Resource.qml @@ -1,20 +1,38 @@ +import qs import qs.modules.common import qs.modules.common.widgets +import qs.services import QtQuick import QtQuick.Layouts +import Quickshell Item { + id: root required property string iconName required property double percentage + property var tooltipData: [ + { + icon: "info", + label: "System resource", + value: "" + } + ] + property var tooltipHeaderIcon + property var tooltipHeaderText property bool shown: true clip: true visible: width > 0 && height > 0 - implicitWidth: resourceRowLayout.x < 0 ? 0 : childrenRect.width - implicitHeight: childrenRect.height + implicitWidth: resourceRowLayout.x < 0 ? 0 : resourceRowLayout.implicitWidth + implicitHeight: resourceRowLayout.implicitHeight + + // Helper function to format KB to GB + function formatKB(kb) { + return (kb / (1024 * 1024)).toFixed(1) + " GB"; + } RowLayout { - spacing: 4 id: resourceRowLayout + spacing: 4 x: shown ? 0 : -resourceRowLayout.width CircularProgress { @@ -30,10 +48,9 @@ Item { anchors.centerIn: parent fill: 1 text: iconName - iconSize: Appearance.font.pixelSize.normal + iconSize: Appearance.font.pixelSize.large color: Appearance.m3colors.m3onSecondaryContainer } - } StyledText { @@ -45,7 +62,73 @@ Item { Behavior on x { animation: Appearance.animation.elementMove.numberAnimation.createObject(this) } + } + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.NoButton + enabled: resourceRowLayout.x >= 0 && root.width > 0 && root.visible + } + + StyledPopup { + hoverTarget: mouseArea + + ColumnLayout { + id: columnLayout + anchors.centerIn: parent + spacing: 4 + + // Header + RowLayout { + id: header + spacing: 5 + + MaterialSymbol { + fill: 0 + font.weight: Font.Medium + text: root.tooltipHeaderIcon + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnSurfaceVariant + } + + StyledText { + text: root.tooltipHeaderText + font { + weight: Font.Medium + pixelSize: Appearance.font.pixelSize.normal + } + color: Appearance.colors.colOnSurfaceVariant + } + } + + // Info rows + Repeater { + model: root.tooltipData + delegate: RowLayout { + spacing: 5 + Layout.fillWidth: true + + MaterialSymbol { + text: modelData.icon + color: Appearance.colors.colOnSurfaceVariant + iconSize: Appearance.font.pixelSize.large + } + StyledText { + text: modelData.label + color: Appearance.colors.colOnSurfaceVariant + } + StyledText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignRight + visible: modelData.value !== "" + color: Appearance.colors.colOnSurfaceVariant + text: modelData.value + } + } + } + } } Behavior on implicitWidth { @@ -55,4 +138,4 @@ Item { easing.bezierCurve: Appearance.animation.elementMove.bezierCurve } } -} \ No newline at end of file +} diff --git a/.config/quickshell/ii/modules/bar/ResourcePopup.qml b/.config/quickshell/ii/modules/bar/ResourcePopup.qml new file mode 100644 index 000000000..71fd02443 --- /dev/null +++ b/.config/quickshell/ii/modules/bar/ResourcePopup.qml @@ -0,0 +1,65 @@ +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import QtQuick +import QtQuick.Layouts + +StyledPopup { + hoverTarget: mouseArea + + ColumnLayout { + id: columnLayout + anchors.centerIn: parent + spacing: 4 + + // Header + RowLayout { + id: header + spacing: 5 + + MaterialSymbol { + fill: 0 + font.weight: Font.Medium + text: root.tooltipHeaderIcon + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnSurfaceVariant + } + + StyledText { + text: root.tooltipHeaderText + font { + weight: Font.Medium + pixelSize: Appearance.font.pixelSize.normal + } + color: Appearance.colors.colOnSurfaceVariant + } + } + + // Info rows + Repeater { + model: root.tooltipData + delegate: RowLayout { + spacing: 5 + Layout.fillWidth: true + + MaterialSymbol { + text: modelData.icon + color: Appearance.colors.colOnSurfaceVariant + iconSize: Appearance.font.pixelSize.large + } + StyledText { + text: modelData.label + color: Appearance.colors.colOnSurfaceVariant + } + StyledText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignRight + visible: modelData.value !== "" + color: Appearance.colors.colOnSurfaceVariant + text: modelData.value + } + } + } + } +} \ No newline at end of file diff --git a/.config/quickshell/ii/modules/bar/Resources.qml b/.config/quickshell/ii/modules/bar/Resources.qml index f57372a18..8d39de037 100644 --- a/.config/quickshell/ii/modules/bar/Resources.qml +++ b/.config/quickshell/ii/modules/bar/Resources.qml @@ -1,6 +1,7 @@ import qs.modules.common import qs.modules.common.widgets import qs.services +import qs import QtQuick import QtQuick.Layouts @@ -22,6 +23,14 @@ Item { Resource { iconName: "memory" percentage: ResourceUsage.memoryUsedPercentage + + tooltipHeaderIcon: "memory" + tooltipHeaderText: Translation.tr("Memory usage") + tooltipData: [ + { icon: "clock_loader_60", label: Translation.tr("Used:"), value: formatKB(ResourceUsage.memoryUsed) }, + { icon: "check_circle", label: Translation.tr("Free:"), value: formatKB(ResourceUsage.memoryFree) }, + { icon: "empty_dashboard", label: Translation.tr("Total:"), value: formatKB(ResourceUsage.memoryTotal) }, + ] } Resource { @@ -31,6 +40,16 @@ Item { (MprisController.activePlayer?.trackTitle == null) || root.alwaysShowAllResources Layout.leftMargin: shown ? 4 : 0 + + tooltipHeaderIcon: "swap_horiz" + tooltipHeaderText: Translation.tr("Swap usage") + tooltipData: ResourceUsage.swapTotal > 0 ? [ + { icon: "clock_loader_60", label: Translation.tr("Used:"), value: formatKB(ResourceUsage.swapUsed) }, + { icon: "check_circle", label: Translation.tr("Free:"), value: formatKB(ResourceUsage.swapFree) }, + { icon: "empty_dashboard", label: Translation.tr("Total:"), value: formatKB(ResourceUsage.swapTotal) }, + ] : [ + { icon: "swap_horiz", label: Translation.tr("Swap:"), value: Translation.tr("Not configured") } + ] } Resource { @@ -40,6 +59,16 @@ Item { !(MprisController.activePlayer?.trackTitle?.length > 0) || root.alwaysShowAllResources Layout.leftMargin: shown ? 4 : 0 + + tooltipHeaderIcon: "settings_slow_motion" + tooltipHeaderText: Translation.tr("CPU usage") + tooltipData: [ + { icon: "bolt", label: Translation.tr("Load:"), value: (ResourceUsage.cpuUsage > 0.8 ? + Translation.tr("High") : + ResourceUsage.cpuUsage > 0.4 ? Translation.tr("Medium") : Translation.tr("Low")) + + ` (${Math.round(ResourceUsage.cpuUsage * 100)}%)` + } + ] } } diff --git a/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml b/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml index 933750f9a..63fd1f5d4 100644 --- a/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml @@ -18,10 +18,10 @@ MouseArea { RowLayout { id: rowLayout anchors.centerIn: parent - + MaterialSymbol { fill: 0 - text: WeatherIcons.codeToName[Weather.data?.wCode] ?? "question_mark" + text: WeatherIcons.codeToName[Weather.data.wCode] ?? "cloud" iconSize: Appearance.font.pixelSize.large color: Appearance.colors.colOnLayer1 Layout.alignment: Qt.AlignVCenter @@ -36,25 +36,8 @@ MouseArea { } } - LazyLoader { - id: popupLoader - active: root.containsMouse - - component: PopupWindow { - id: popupWindow - visible: true - implicitWidth: weatherPopup.implicitWidth - implicitHeight: weatherPopup.implicitHeight - anchor.item: root - anchor.edges: Edges.Top - anchor.rect.x: (root.implicitWidth - popupWindow.implicitWidth) / 2 - anchor.rect.y: Config.options.bar.bottom ? - (-weatherPopup.implicitHeight - 15) : - (root.implicitHeight + 15 ) - color: "transparent" - WeatherPopup { - id: weatherPopup - } - } + WeatherPopup { + id: weatherPopup + hoverTarget: root } } diff --git a/.config/quickshell/ii/modules/bar/weather/WeatherCard.qml b/.config/quickshell/ii/modules/bar/weather/WeatherCard.qml index a85ed8ca3..e75dda32f 100644 --- a/.config/quickshell/ii/modules/bar/weather/WeatherCard.qml +++ b/.config/quickshell/ii/modules/bar/weather/WeatherCard.qml @@ -7,9 +7,9 @@ import qs.modules.common.widgets Rectangle { id: root radius: Appearance.rounding.small - color: Appearance.colors.colLayer1 - implicitWidth: columnLayout.implicitWidth * 2 - implicitHeight: columnLayout.implicitHeight * 2 + color: Appearance.colors.colSurfaceContainerHigh + implicitWidth: columnLayout.implicitWidth + 14 * 2 + implicitHeight: columnLayout.implicitHeight + 14 * 2 Layout.fillWidth: parent property alias title: title.text @@ -26,18 +26,19 @@ Rectangle { id: symbol fill: 0 iconSize: Appearance.font.pixelSize.normal + color: Appearance.colors.colOnSurfaceVariant } StyledText { id: title font.pixelSize: Appearance.font.pixelSize.smaller - color: Appearance.colors.colOnLayer1 + color: Appearance.colors.colOnSurfaceVariant } } StyledText { id: value Layout.alignment: Qt.AlignHCenter - font.pixelSize: Appearance.font.pixelSize.normal - color: Appearance.colors.colOnLayer1 + font.pixelSize: Appearance.font.pixelSize.small + color: Appearance.colors.colOnSurfaceVariant } } } diff --git a/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml b/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml index 827abea4f..aa61359d7 100644 --- a/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml +++ b/.config/quickshell/ii/modules/bar/weather/WeatherPopup.qml @@ -6,41 +6,37 @@ import qs.modules.common.widgets import QtQuick import QtQuick.Layouts -Rectangle { +StyledPopup { 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 - spacing: 5 - anchors.centerIn: root + anchors.centerIn: parent implicitWidth: Math.max(header.implicitWidth, gridLayout.implicitWidth) implicitHeight: gridLayout.implicitHeight + spacing: 5 // Header RowLayout { id: header spacing: 5 - Layout.fillWidth: parent Layout.alignment: Qt.AlignHCenter + MaterialSymbol { fill: 0 + font.weight: Font.Medium text: "location_on" - iconSize: Appearance.font.pixelSize.huge + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnSurfaceVariant } StyledText { text: Weather.data.city - font.pixelSize: Appearance.font.pixelSize.title - font.family: Appearance.font.family.title - color: Appearance.colors.colOnLayer0 + font { + weight: Font.Medium + pixelSize: Appearance.font.pixelSize.normal + } + color: Appearance.colors.colOnSurfaceVariant } } @@ -94,4 +90,4 @@ Rectangle { } } } -} +} \ No newline at end of file diff --git a/.config/quickshell/ii/modules/common/Appearance.qml b/.config/quickshell/ii/modules/common/Appearance.qml index 64f76b96b..f7e3a9eb2 100644 --- a/.config/quickshell/ii/modules/common/Appearance.qml +++ b/.config/quickshell/ii/modules/common/Appearance.qml @@ -162,6 +162,8 @@ Singleton { property color colSurfaceContainerHighest: ColorUtils.transparentize(m3colors.m3surfaceContainerHighest, root.contentTransparency) property color colSurfaceContainerHighestHover: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.95) property color colSurfaceContainerHighestActive: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.85) + property color colOnSurface: m3colors.m3onSurface + property color colOnSurfaceVariant: m3colors.m3onSurfaceVariant property color colTooltip: m3colors.m3inverseSurface property color colOnTooltip: m3colors.m3inverseOnSurface property color colScrim: ColorUtils.transparentize(m3colors.m3scrim, 0.5) diff --git a/.config/quickshell/ii/modules/common/widgets/StyledPopup.qml b/.config/quickshell/ii/modules/common/widgets/StyledPopup.qml new file mode 100644 index 000000000..baa37cce9 --- /dev/null +++ b/.config/quickshell/ii/modules/common/widgets/StyledPopup.qml @@ -0,0 +1,66 @@ +import qs +import qs.modules.common +import qs.modules.common.widgets +import qs.services +import QtQuick +import QtQuick.Layouts +import QtQuick.Effects +import Quickshell +import Quickshell.Wayland + +LazyLoader { + id: root + + property MouseArea hoverTarget + default property Item contentItem + + active: hoverTarget && hoverTarget.containsMouse + + component: PanelWindow { + id: popupWindow + visible: true + color: "transparent" + exclusiveZone: 0 + + anchors.left: true + anchors.top: !Config.options.bar.bottom + anchors.bottom: Config.options.bar.bottom + + implicitWidth: popupBackground.implicitWidth + Appearance.sizes.hyprlandGapsOut * 2 + implicitHeight: popupBackground.implicitHeight + Appearance.sizes.hyprlandGapsOut * 2 + + margins { + left: root.QsWindow?.mapFromItem( + root.hoverTarget, + (root.hoverTarget.width - popupBackground.implicitWidth) / 2, 0 + ).x + } + WlrLayershell.namespace: "quickshell:popup" + WlrLayershell.layer: WlrLayer.Overlay + + RectangularShadow { + property var target: popupBackground + anchors.fill: target + radius: target.radius + blur: 0.9 * Appearance.sizes.hyprlandGapsOut + offset: Qt.vector2d(0.0, 1.0) + spread: 0.7 + color: Appearance.colors.colShadow + cached: true + } + + Rectangle { + id: popupBackground + readonly property real margin: 10 + anchors.centerIn: parent + implicitWidth: root.contentItem.implicitWidth + margin * 2 + implicitHeight: root.contentItem.implicitHeight + margin * 2 + color: Appearance.colors.colSurfaceContainer + radius: Appearance.rounding.small + children: [root.contentItem] + + border.width: 1 + border.color: Appearance.colors.colLayer0Border + } + } +} diff --git a/.config/quickshell/ii/services/Battery.qml b/.config/quickshell/ii/services/Battery.qml index 8a3cf3160..3674cb287 100644 --- a/.config/quickshell/ii/services/Battery.qml +++ b/.config/quickshell/ii/services/Battery.qml @@ -4,6 +4,8 @@ import qs import qs.modules.common import Quickshell import Quickshell.Services.UPower +import QtQuick +import Quickshell.Io Singleton { property bool available: UPower.displayDevice.isLaptopBattery @@ -21,6 +23,10 @@ Singleton { 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", diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index fe8c64533..215aeca02 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -310,5 +310,29 @@ "Sunrise": "Sunrise", "Pressure": "Pressure", "Visibility": "Visibility", - "Precipitation": "Precipitation" + "Precipitation": "Precipitation", + "Time to full:": "Time to full:", + "Time to empty:": "Time to empty:", + "Fully charged": "Fully charged", + "Charging:": "Charging:", + "Discharging:": "Discharging:", + "Uptime:": "Uptime:", + "Upcoming Tasks:": "Upcoming Tasks:", + "No pending tasks": "No pending tasks", + "... and %1 more": "... and %1 more", + "Memory Usage": "Memory Usage", + "Used:": "Used:", + "Free:": "Free:", + "Total:": "Total:", + "Usage:": "Usage:", + "Swap Usage": "Swap Usage", + "Swap:": "Swap:", + "Not configured": "Not configured", + "CPU Usage": "CPU Usage", + "Current:": "Current:", + "Load:": "Load:", + "High": "High", + "Medium": "Medium", + "Low": "Low", + "System Resource": "System Resource" } \ No newline at end of file diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index cfaf50e9b..4d80b222c 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -302,6 +302,30 @@ "Humidity": "湿度", "Wind": "风", "Precipitation": "降水量", + "Time to full:": "距离充满:", + "Time to empty:": "距离耗尽:", + "Fully charged": "已充满电", + "Charging:": "充电功率:", + "Discharging:": "放电功率:", + "Uptime:": "运行时间:", + "Upcoming Tasks:": "待办任务:", + "No pending tasks": "没有待办任务", + "... and %1 more": "... 还有 %1 个", + "Memory Usage": "内存使用情况", + "Used:": "已用:", + "Free:": "可用:", + "Total:": "总计:", + "Usage:": "占比:", + "Swap Usage": "交换区使用情况", + "Swap:": "交换区:", + "Not configured": "未配置", + "CPU Usage": "CPU 使用情况", + "Current:": "当前占比:", + "Load:": "负载:", + "High": "高", + "Medium": "中", + "Low": "低", + "System Resource": "系统资源", "Tint icons": "图标着色", "Performance Profile toggle": "性能配置文件切换", "**Instructions**: Log into Mistral account, go to Keys on the sidebar, click Create new key": "**说明**:登录 Mistral 账户,在侧边栏中选择 Keys,点击创建新密钥", @@ -345,4 +369,4 @@ "Invalid tool. Supported tools:\n- %1": "无效工具。支持的工具:\n- %1", "Keep right sidebar loaded": "保持右侧边栏加载", "Reject": "拒绝" -} \ No newline at end of file +}