Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Assets/Translations/en-GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"display-mode-icon-always": "Icon - Always show %",
"display-mode-icon-hover": "Icon - Show on hover",
"display-mode-icon-only": "Icon only",
"display-mode-android-16": "Android 16 style",
"hide-if-idle-description": "Hide the widget when the battery is not charging or discharging.",
"hide-if-idle-label": "Hide when idle",
"hide-if-not-detected-description": "Hide the widget when no battery is detected on the system.",
Expand Down
1 change: 1 addition & 0 deletions Assets/Translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"display-mode-icon-always": "Icon - Always show %",
"display-mode-icon-hover": "Icon - Show on hover",
"display-mode-icon-only": "Icon only",
"display-mode-android-16": "Android 16 style",
"hide-if-idle-description": "Hide the widget when the battery is not charging or discharging.",
"hide-if-idle-label": "Hide when idle",
"hide-if-not-detected-description": "Hide the widget when no battery is detected on the system.",
Expand Down
51 changes: 49 additions & 2 deletions Modules/Bar/Widgets/ActiveWindow.qml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import Quickshell.Widgets
import qs.Commons
Expand Down Expand Up @@ -59,6 +60,9 @@ Item {
readonly property string windowTitle: CompositorService.getFocusedWindowTitle() || "No active window"
readonly property string fallbackIcon: "user-desktop"

// Memory usage tooltip
property string memoryUsage: ""

readonly property int iconSize: Style.toOdd(capsuleHeight * 0.75)
readonly property int verticalSize: Style.toOdd(capsuleHeight * 0.85)

Expand Down Expand Up @@ -334,6 +338,41 @@ Item {
}
}

// Process to query active window PID and memory usage
Process {
id: memoryQueryProcess
running: false
command: ["sh", "-c", "PID=$(hyprctl activewindow -j 2>/dev/null | grep '\"pid\":' | head -1 | sed 's/[^0-9]//g'); if [ -n \"$PID\" ]; then pstree -p $PID 2>/dev/null | tr '(' '\\n' | grep -oE '^[0-9]+' | xargs ps -o rss= -p 2>/dev/null | awk '{sum+=$1} END {if(sum>0) print int(sum)}'; fi"]

property string outputLine: ""

stdout: SplitParser {
onRead: function(line) {
memoryQueryProcess.outputLine = line.trim();
}
}

onExited: function(exitCode) {
var kbStr = outputLine;
outputLine = "";
if (kbStr && !isNaN(kbStr)) {
var kb = parseInt(kbStr);
if (kb >= 1024) {
root.memoryUsage = Math.round(kb / 1024) + " MB";
} else {
root.memoryUsage = kb + " kB";
}
// Re-show tooltip with updated content (show() handles same-target update)
if (mainMouseArea.containsMouse && root.memoryUsage !== "") {
var content = ((windowTitle !== "") && isVerticalBar || (scrollingMode === "never"))
? windowTitle + "\nMemory: " + root.memoryUsage
: "Memory: " + root.memoryUsage;
TooltipService.show(root, content, BarService.getTooltipDirection(root.screen?.name));
}
}
}
}

// Mouse area for hover detection
MouseArea {
id: mainMouseArea
Expand All @@ -349,11 +388,19 @@ Item {
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onEntered: {
if ((windowTitle !== "") && isVerticalBar || (scrollingMode === "never")) {
TooltipService.show(root, windowTitle, BarService.getTooltipDirection(root.screen?.name));
root.memoryUsage = "";
if (hasFocusedWindow) {
if ((windowTitle !== "") && isVerticalBar || (scrollingMode === "never")) {
TooltipService.show(root, windowTitle + "\nMemory: ...", BarService.getTooltipDirection(root.screen?.name));
} else {
TooltipService.show(root, "Memory: ...", BarService.getTooltipDirection(root.screen?.name));
}
// Trigger memory query
memoryQueryProcess.running = true;
}
}
onExited: {
root.memoryUsage = "";
TooltipService.hide();
}
onClicked: mouse => {
Expand Down
49 changes: 42 additions & 7 deletions Modules/Bar/Widgets/Battery.qml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import qs.Commons
import qs.Modules.Bar.Extras
import qs.Services.Hardware
import qs.Services.Networking
import qs.Services.Noctalia
import qs.Services.UI
import qs.Widgets

Expand Down Expand Up @@ -39,7 +40,9 @@ Item {
readonly property real capsuleHeight: Style.getCapsuleHeightForScreen(screenName)

readonly property string displayMode: widgetSettings.displayMode !== undefined ? widgetSettings.displayMode : widgetMetadata.displayMode
readonly property bool useGraphicMode: displayMode === "graphic" || displayMode === "graphic-clean"
readonly property bool useGraphicMode: displayMode === "graphic" || displayMode === "graphic-clean" || (displayMode === "android-16" && !pluginExists)
readonly property bool pluginExists: PluginRegistry.isPluginDownloaded("custom-battery")
readonly property bool usePluginMode: displayMode === "android-16" && pluginExists

readonly property bool hideIfNotDetected: widgetSettings.hideIfNotDetected !== undefined ? widgetSettings.hideIfNotDetected : widgetMetadata.hideIfNotDetected
readonly property bool hideIfIdle: widgetSettings.hideIfIdle !== undefined ? widgetSettings.hideIfIdle : widgetMetadata.hideIfIdle
Expand Down Expand Up @@ -122,8 +125,8 @@ Item {
visible: shouldShow
opacity: shouldShow ? 1.0 : 0.0

implicitWidth: useGraphicMode ? capsule.width : pill.width
implicitHeight: useGraphicMode ? capsule.height : pill.height
implicitWidth: usePluginMode ? (pluginLoader.item ? pluginLoader.item.implicitWidth : 0) : (useGraphicMode ? capsule.width : pill.width)
implicitHeight: usePluginMode ? (pluginLoader.item ? pluginLoader.item.implicitHeight : 0) : (useGraphicMode ? capsule.height : pill.height)

NPopupContextMenu {
id: contextMenu
Expand Down Expand Up @@ -151,7 +154,7 @@ Item {
// Capsule background (graphic mode only)
Rectangle {
id: capsule
visible: root.useGraphicMode
visible: root.useGraphicMode && !root.usePluginMode
anchors.centerIn: nBattery
width: root.isBarVertical ? root.capsuleHeight : nBattery.width + Style.margin2S
height: root.isBarVertical ? nBattery.height + Style.margin2S : root.capsuleHeight
Expand All @@ -171,7 +174,7 @@ Item {

NBattery {
id: nBattery
visible: root.useGraphicMode
visible: root.useGraphicMode && !root.usePluginMode
anchors.centerIn: parent
baseSize: (Style.getBarHeightForScreen(root.screenName) / root.capsuleHeight) * Style.fontSizeXXS
showPercentageText: root.displayMode !== "graphic-clean"
Expand All @@ -188,7 +191,7 @@ Item {

MouseArea {
id: graphicMouseArea
visible: root.useGraphicMode
visible: root.useGraphicMode && !root.usePluginMode
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
Expand Down Expand Up @@ -228,7 +231,7 @@ Item {

BarPill {
id: pill
visible: !root.useGraphicMode
visible: !root.useGraphicMode && !root.usePluginMode
screen: root.screen
oppositeDirection: BarService.getPillDirection(root)
icon: BatteryService.getIcon(root.percent, root.isCharging, root.isPluggedIn, root.isReady)
Expand All @@ -244,6 +247,38 @@ Item {
onRightClicked: PanelService.showContextMenu(contextMenu, pill, screen)
}

// ==================== PLUGIN MODE ====================

Loader {
id: pluginLoader
active: root.usePluginMode
visible: active
source: active ? "file://" + PluginRegistry.getPluginDir("custom-battery") + "/BarWidget.qml" : ""

onLoaded: {
item.screen = root.screen;
item.widgetId = root.widgetId;
item.section = root.section;
item.sectionWidgetIndex = root.sectionWidgetIndex;
item.sectionWidgetsCount = root.sectionWidgetsCount;
item.pluginApi = PluginService.loadedPlugins["custom-battery"] ? PluginService.loadedPlugins["custom-battery"].api : null;
}

anchors.fill: parent
}

MouseArea {
id: pluginMouseArea
anchors.fill: parent
visible: root.usePluginMode
acceptedButtons: Qt.RightButton
onClicked: mouse => {
if (mouse.button === Qt.RightButton) {
PanelService.showContextMenu(contextMenu, pluginLoader.item || this, screen);
}
}
}

// ==================== SHARED ====================

function getBatteryPanel() {
Expand Down
39 changes: 17 additions & 22 deletions Modules/Panels/Settings/Bar/WidgetSettings/BatterySettings.qml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import qs.Commons
import qs.Services.Hardware
import qs.Services.Noctalia
import qs.Widgets

ColumnLayout {
Expand All @@ -24,6 +25,21 @@ ColumnLayout {
property bool valueHideIfNotDetected: widgetData.hideIfNotDetected !== undefined ? widgetData.hideIfNotDetected : widgetMetadata.hideIfNotDetected
property bool valueHideIfIdle: widgetData.hideIfIdle !== undefined ? widgetData.hideIfIdle : widgetMetadata.hideIfIdle

readonly property var displayModeModel: {
var m = [
{ "key": "graphic", "name": I18n.tr("bar.battery.display-mode-graphic") },
{ "key": "graphic-clean", "name": I18n.tr("bar.battery.display-mode-graphic-clean") },
{ "key": "icon-hover", "name": I18n.tr("bar.battery.display-mode-icon-hover") },
{ "key": "icon-always", "name": I18n.tr("bar.battery.display-mode-icon-always") },
{ "key": "icon-only", "name": I18n.tr("bar.battery.display-mode-icon-only") }
];

if (PluginRegistry.isPluginDownloaded("custom-battery")) {
m.push({ "key": "android-16", "name": I18n.tr("bar.battery.display-mode-android-16") });
}
return m;
}

function saveSettings() {
var settings = Object.assign({}, widgetData || {});
if (widgetData && widgetData.id) {
Expand Down Expand Up @@ -58,28 +74,7 @@ ColumnLayout {
label: I18n.tr("common.display-mode")
description: I18n.tr("bar.battery.display-mode-description")
minimumWidth: 240
model: [
{
"key": "graphic",
"name": I18n.tr("bar.battery.display-mode-graphic")
},
{
"key": "graphic-clean",
"name": I18n.tr("bar.battery.display-mode-graphic-clean")
},
{
"key": "icon-hover",
"name": I18n.tr("bar.battery.display-mode-icon-hover")
},
{
"key": "icon-always",
"name": I18n.tr("bar.battery.display-mode-icon-always")
},
{
"key": "icon-only",
"name": I18n.tr("bar.battery.display-mode-icon-only")
}
]
model: root.displayModeModel
currentKey: root.valueDisplayMode
onSelected: key => {
root.valueDisplayMode = key;
Expand Down