diff --git a/quickshell/Modules/DankBar/Widgets/RamMonitor.qml b/quickshell/Modules/DankBar/Widgets/RamMonitor.qml index 06cdcdbc..f5d6de59 100644 --- a/quickshell/Modules/DankBar/Widgets/RamMonitor.qml +++ b/quickshell/Modules/DankBar/Widgets/RamMonitor.qml @@ -14,6 +14,7 @@ BasePill { property var widgetData: null property bool minimumWidth: (widgetData && widgetData.minimumWidth !== undefined) ? widgetData.minimumWidth : true property bool showSwap: (widgetData && widgetData.showSwap !== undefined) ? widgetData.showSwap : false + property bool showInGb: (widgetData && widgetData.showInGb !== undefined) ? widgetData.showInGb : false readonly property real swapUsage: DgopService.totalSwapKB > 0 ? (DgopService.usedSwapKB / DgopService.totalSwapKB) * 100 : 0 signal ramClicked @@ -59,6 +60,10 @@ BasePill { return "--"; } + if (root.showInGb) { + return (DgopService.usedMemoryMB / 1024).toFixed(1); + } + return DgopService.memoryUsage.toFixed(0); } font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText) @@ -113,13 +118,14 @@ BasePill { id: ramBaseline font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText) text: { + let baseText = root.showInGb ? "88.8 GB" : "88%"; if (!root.showSwap) { - return "88%"; + return baseText; } if (root.swapUsage < 10) { - return "88% · 0%"; + return baseText + " · 0%"; } - return "88% · 88%"; + return baseText + " · 88%"; } } @@ -127,10 +133,16 @@ BasePill { id: ramText text: { if (DgopService.memoryUsage === undefined || DgopService.memoryUsage === null || DgopService.memoryUsage === 0) { - return "--%"; + return root.showInGb ? "-- GB" : "--%"; + } + + let ramText = ""; + if (root.showInGb) { + ramText = (DgopService.usedMemoryMB / 1024).toFixed(1) + " GB"; + } else { + ramText = DgopService.memoryUsage.toFixed(0) + "%"; } - let ramText = DgopService.memoryUsage.toFixed(0) + "%"; if (root.showSwap && DgopService.totalSwapKB > 0) { return ramText + " · " + root.swapUsage.toFixed(0) + "%"; } diff --git a/quickshell/Modules/Settings/Widgets/SystemMonitorVariantCard.qml b/quickshell/Modules/Settings/Widgets/SystemMonitorVariantCard.qml index 6d65fadb..1ecd4518 100644 --- a/quickshell/Modules/Settings/Widgets/SystemMonitorVariantCard.qml +++ b/quickshell/Modules/Settings/Widgets/SystemMonitorVariantCard.qml @@ -216,6 +216,15 @@ Rectangle { onToggled: checked => root.updateConfig("showMemoryGraph", checked) } + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show Memory in GB") + visible: root.cfg.showMemory + checked: root.cfg.showInGb ?? false + onToggled: checked => root.updateConfig("showInGb", checked) + } + SettingsDivider {} DankToggle { diff --git a/quickshell/Modules/Settings/WidgetsTab.qml b/quickshell/Modules/Settings/WidgetsTab.qml index b7eb66e5..acc6fa36 100644 --- a/quickshell/Modules/Settings/WidgetsTab.qml +++ b/quickshell/Modules/Settings/WidgetsTab.qml @@ -402,6 +402,8 @@ Item { widgetObj.mountPath = "/"; if (widgetId === "cpuUsage" || widgetId === "memUsage" || widgetId === "cpuTemp" || widgetId === "gpuTemp") widgetObj.minimumWidth = true; + if (widgetId === "memUsage") + widgetObj.showInGb = false; var widgets = getWidgetsForSection(targetSection).slice(); widgets.push(widgetObj); @@ -425,7 +427,7 @@ Item { "id": widget.id, "enabled": widget.enabled }; - var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"]; + var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"]; for (var i = 0; i < keys.length; i++) { if (widget[keys[i]] !== undefined) result[keys[i]] = widget[keys[i]]; @@ -536,6 +538,18 @@ Item { setWidgetsForSection(sectionId, widgets); } + function handleShowInGbChanged(sectionId, widgetIndex, enabled) { + var widgets = getWidgetsForSection(sectionId).slice(); + if (widgetIndex < 0 || widgetIndex >= widgets.length) { + setWidgetsForSection(sectionId, widgets); + return; + } + var newWidget = cloneWidgetData(widgets[widgetIndex]); + newWidget.showInGb = enabled; + widgets[widgetIndex] = newWidget; + setWidgetsForSection(sectionId, widgets); + } + function handleOverflowSettingChanged(sectionId, widgetIndex, settingName, value) { var widgets = getWidgetsForSection(sectionId).slice(); if (widgetIndex < 0 || widgetIndex >= widgets.length) { @@ -629,6 +643,8 @@ Item { item.minimumWidth = widget.minimumWidth; if (widget.showSwap !== undefined) item.showSwap = widget.showSwap; + if (widget.showInGb !== undefined) + item.showInGb = widget.showInGb; if (widget.mediaSize !== undefined) item.mediaSize = widget.mediaSize; if (widget.clockCompactMode !== undefined) @@ -925,6 +941,9 @@ Item { onShowSwapChanged: (sectionId, index, enabled) => { widgetsTab.handleShowSwapChanged(sectionId, index, enabled); } + onShowInGbChanged: (sectionId, index, enabled) => { + widgetsTab.handleShowInGbChanged(sectionId, index, enabled); + } onCompactModeChanged: (widgetId, value) => { widgetsTab.handleCompactModeChanged(sectionId, widgetId, value); } @@ -983,6 +1002,9 @@ Item { onShowSwapChanged: (sectionId, index, enabled) => { widgetsTab.handleShowSwapChanged(sectionId, index, enabled); } + onShowInGbChanged: (sectionId, index, enabled) => { + widgetsTab.handleShowInGbChanged(sectionId, index, enabled); + } onCompactModeChanged: (widgetId, value) => { widgetsTab.handleCompactModeChanged(sectionId, widgetId, value); } @@ -1041,6 +1063,9 @@ Item { onShowSwapChanged: (sectionId, index, enabled) => { widgetsTab.handleShowSwapChanged(sectionId, index, enabled); } + onShowInGbChanged: (sectionId, index, enabled) => { + widgetsTab.handleShowInGbChanged(sectionId, index, enabled); + } onCompactModeChanged: (widgetId, value) => { widgetsTab.handleCompactModeChanged(sectionId, widgetId, value); } diff --git a/quickshell/Modules/Settings/WidgetsTabSection.qml b/quickshell/Modules/Settings/WidgetsTabSection.qml index 5e23e1f6..4812258b 100644 --- a/quickshell/Modules/Settings/WidgetsTabSection.qml +++ b/quickshell/Modules/Settings/WidgetsTabSection.qml @@ -30,6 +30,7 @@ Column { signal privacySettingChanged(string sectionId, int widgetIndex, string settingName, bool value) signal minimumWidthChanged(string sectionId, int widgetIndex, bool enabled) signal showSwapChanged(string sectionId, int widgetIndex, bool enabled) + signal showInGbChanged(string sectionId, int widgetIndex, bool enabled) signal overflowSettingChanged(string sectionId, int widgetIndex, string settingName, var value) function cloneWidgetData(widget) { @@ -37,7 +38,7 @@ Column { "id": widget.id, "enabled": widget.enabled }; - var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"]; + var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"]; for (var i = 0; i < keys.length; i++) { if (widget[keys[i]] !== undefined) result[keys[i]] = widget[keys[i]]; @@ -67,53 +68,6 @@ Column { color: Theme.surfaceText Layout.alignment: Qt.AlignVCenter } - - Item { - height: 1 - Layout.fillWidth: true - } - - RowLayout { - spacing: Theme.spacingXS - Layout.alignment: Qt.AlignVCenter - visible: root.sectionId === "center" - - DankActionButton { - id: indexCenterButton - buttonSize: 28 - iconName: "format_list_numbered" - iconSize: 16 - iconColor: SettingsData.centeringMode === "index" ? Theme.primary : Theme.outline - onClicked: { - console.log("Centering mode changed to: index"); - SettingsData.set("centeringMode", "index"); - } - onEntered: { - sharedTooltip.show("Index Centering", indexCenterButton, 0, 0, "bottom"); - } - onExited: { - sharedTooltip.hide(); - } - } - - DankActionButton { - id: geometricCenterButton - buttonSize: 28 - iconName: "center_focus_weak" - iconSize: 16 - iconColor: SettingsData.centeringMode === "geometric" ? Theme.primary : Theme.outline - onClicked: { - console.log("Centering mode changed to: geometric"); - SettingsData.set("centeringMode", "geometric"); - } - onEntered: { - sharedTooltip.show("Geometric Centering", geometricCenterButton, 0, 0, "bottom"); - } - onExited: { - sharedTooltip.hide(); - } - } - } } Column { @@ -135,6 +89,7 @@ Column { height: 70 z: held ? 2 : 1 + Rectangle { id: itemBackground @@ -354,23 +309,36 @@ Column { } DankActionButton { - id: showSwapButton - buttonSize: 28 + id: memMenuButton visible: modelData.id === "memUsage" - iconName: "swap_horiz" - iconSize: 16 - iconColor: (modelData.showSwap !== undefined ? modelData.showSwap : false) ? Theme.primary : Theme.outline + buttonSize: 32 + iconName: "more_vert" + iconSize: 18 + iconColor: Theme.outline onClicked: { - var currentEnabled = modelData.showSwap !== undefined ? modelData.showSwap : false; - root.showSwapChanged(root.sectionId, index, !currentEnabled); - } - onEntered: { - var currentEnabled = modelData.showSwap !== undefined ? modelData.showSwap : false; - const tooltipText = currentEnabled ? "Hide Swap" : "Show Swap"; - sharedTooltip.show(tooltipText, showSwapButton, 0, 0, "bottom"); - } - onExited: { - sharedTooltip.hide(); + memUsageContextMenu.widgetData = modelData; + memUsageContextMenu.sectionId = root.sectionId; + memUsageContextMenu.widgetIndex = index; + + var buttonPos = memMenuButton.mapToItem(root, 0, 0); + var popupWidth = memUsageContextMenu.width; + var popupHeight = memUsageContextMenu.height; + + var xPos = buttonPos.x - popupWidth - Theme.spacingS; + if (xPos < 0) { + xPos = buttonPos.x + memMenuButton.width + Theme.spacingS; + } + + var yPos = buttonPos.y - popupHeight / 2 + memMenuButton.height / 2; + if (yPos < 0) { + yPos = Theme.spacingS; + } else if (yPos + popupHeight > root.height) { + yPos = root.height - popupHeight - Theme.spacingS; + } + + memUsageContextMenu.x = xPos; + memUsageContextMenu.y = yPos; + memUsageContextMenu.open(); } } @@ -799,6 +767,142 @@ Column { } } + Popup { + id: memUsageContextMenu + + property var widgetData: null + property string sectionId: "" + property int widgetIndex: -1 + + width: 200 + height: 80 + padding: 0 + modal: true + focus: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + + background: Rectangle { + color: Theme.surfaceContainer + radius: Theme.cornerRadius + border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) + border.width: 0 + } + + contentItem: Item { + Column { + anchors.fill: parent + anchors.margins: Theme.spacingS + spacing: 2 + + Rectangle { + width: parent.width + height: 32 + radius: Theme.cornerRadius + color: swapToggleArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" + + Row { + anchors.left: parent.left + anchors.leftMargin: Theme.spacingS + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingS + + DankIcon { + name: "swap_horiz" + size: 16 + color: Theme.surfaceText + anchors.verticalCenter: parent.verticalCenter + } + + StyledText { + text: I18n.tr("Show Swap") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + font.weight: Font.Normal + anchors.verticalCenter: parent.verticalCenter + } + } + + DankToggle { + id: swapToggle + anchors.right: parent.right + anchors.rightMargin: Theme.spacingS + anchors.verticalCenter: parent.verticalCenter + width: 40 + height: 20 + checked: memUsageContextMenu.widgetData?.showSwap ?? false + onToggled: { + root.showSwapChanged(memUsageContextMenu.sectionId, memUsageContextMenu.widgetIndex, toggled); + } + } + + MouseArea { + id: swapToggleArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onPressed: { + swapToggle.checked = !swapToggle.checked; + root.showSwapChanged(memUsageContextMenu.sectionId, memUsageContextMenu.widgetIndex, swapToggle.checked); + } + } + } + + Rectangle { + width: parent.width + height: 32 + radius: Theme.cornerRadius + color: gbToggleArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" + + Row { + anchors.left: parent.left + anchors.leftMargin: Theme.spacingS + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingS + + DankIcon { + name: "straighten" + size: 16 + color: Theme.surfaceText + anchors.verticalCenter: parent.verticalCenter + } + + StyledText { + text: I18n.tr("Show in GB") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + font.weight: Font.Normal + anchors.verticalCenter: parent.verticalCenter + } + } + + DankToggle { + id: gbToggle + anchors.right: parent.right + anchors.rightMargin: Theme.spacingS + anchors.verticalCenter: parent.verticalCenter + width: 40 + height: 20 + checked: memUsageContextMenu.widgetData?.showInGb ?? false + onToggled: { + root.showInGbChanged(memUsageContextMenu.sectionId, memUsageContextMenu.widgetIndex, toggled); + } + } + + MouseArea { + id: gbToggleArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onPressed: { + gbToggle.checked = !gbToggle.checked; + root.showInGbChanged(memUsageContextMenu.sectionId, memUsageContextMenu.widgetIndex, gbToggle.checked); + } + } + } + } + } + } + Popup { id: controlCenterContextMenu