From 06c51553ba5636edce9a67fe1d817763b6c3dde8 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 6 Nov 2025 21:35:31 +0100 Subject: [PATCH] refractor bar tooltips --- .../ii/modules/bar/BatteryPopup.qml | 161 +++++------------- .../quickshell/ii/modules/bar/ClockWidget.qml | 2 +- .../ii/modules/bar/ClockWidgetPopup.qml | 70 ++++++++ .../ii/modules/bar/ClockWidgetTooltip.qml | 110 ------------ .../ii/modules/bar/ResourcesPopup.qml | 73 ++------ .../ii/modules/bar/StyledPopupHeaderRow.qml | 30 ++++ .../ii/modules/bar/StyledPopupValueRow.qml | 29 ++++ .../verticalBar/VerticalClockWidget.qml | 2 +- .../ii/modules/verticalBar/VerticalMedia.qml | 25 +-- 9 files changed, 184 insertions(+), 318 deletions(-) create mode 100644 dots/.config/quickshell/ii/modules/bar/ClockWidgetPopup.qml delete mode 100644 dots/.config/quickshell/ii/modules/bar/ClockWidgetTooltip.qml create mode 100644 dots/.config/quickshell/ii/modules/bar/StyledPopupHeaderRow.qml create mode 100644 dots/.config/quickshell/ii/modules/bar/StyledPopupValueRow.qml diff --git a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml index 037313e3f..9e3dc49bd 100644 --- a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml +++ b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml @@ -13,143 +13,58 @@ StyledPopup { spacing: 4 // Header - Row { - id: header - spacing: 5 - - MaterialSymbol { - anchors.verticalCenter: parent.verticalCenter - fill: 0 - font.weight: Font.Medium - text: "battery_android_full" - iconSize: Appearance.font.pixelSize.large - color: Appearance.colors.colOnSurfaceVariant - } - - StyledText { - anchors.verticalCenter: parent.verticalCenter - text: "Battery" - font { - weight: Font.Medium - pixelSize: Appearance.font.pixelSize.normal - } - color: Appearance.colors.colOnSurfaceVariant - } + StyledPopupHeaderRow { + icon: "battery_android_full" + label: Translation.tr("Battery") } - // This row is hidden when the battery is full. - RowLayout { - spacing: 5 - Layout.fillWidth: true - property bool rowVisible: { + StyledPopupValueRow { + visible: { 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); + icon: "schedule" + label: Battery.isCharging ? Translation.tr("Time to full:") : Translation.tr("Time to empty:") + value: { + 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 formatTime(Battery.timeToEmpty); + return `${m}m`; } + if (Battery.isCharging) + return formatTime(Battery.timeToFull); + else + return formatTime(Battery.timeToEmpty); } } - RowLayout { - spacing: 5 - visible: Battery.health > 0 - Layout.fillWidth: true + StyledPopupValueRow { + icon: "heart_check" + label: Translation.tr("Health:") + value: `${(Battery.health).toFixed(1)}%` + } - MaterialSymbol { - text: "heart_check" - color: Appearance.colors.colOnSurfaceVariant - iconSize: Appearance.font.pixelSize.large - } - - StyledText { - text: Translation.tr("Health:") - color: Appearance.colors.colOnSurfaceVariant - } - - StyledText { - Layout.fillWidth: true - horizontalAlignment: Text.AlignRight - color: Appearance.colors.colOnSurfaceVariant - text: `${(Battery.health).toFixed(1)}%` + StyledPopupValueRow { + visible: !(Battery.chargeState != 4 && Battery.energyRate == 0) + icon: "bolt" + label: { + if (Battery.chargeState == 4) { + return Translation.tr("Fully charged"); + } else if (Battery.chargeState == 1) { + return Translation.tr("Charging:"); + } else { + return Translation.tr("Discharging:"); } } - - 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`; - } + value: { + if (Battery.chargeState == 4) { + return ""; + } else { + return `${Battery.energyRate.toFixed(2)}W`; } } } diff --git a/dots/.config/quickshell/ii/modules/bar/ClockWidget.qml b/dots/.config/quickshell/ii/modules/bar/ClockWidget.qml index 4d6fb61f2..895ad9be0 100644 --- a/dots/.config/quickshell/ii/modules/bar/ClockWidget.qml +++ b/dots/.config/quickshell/ii/modules/bar/ClockWidget.qml @@ -43,7 +43,7 @@ Item { hoverEnabled: true acceptedButtons: Qt.NoButton - ClockWidgetTooltip { + ClockWidgetPopup { hoverTarget: mouseArea } } diff --git a/dots/.config/quickshell/ii/modules/bar/ClockWidgetPopup.qml b/dots/.config/quickshell/ii/modules/bar/ClockWidgetPopup.qml new file mode 100644 index 000000000..c23edb7b4 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/bar/ClockWidgetPopup.qml @@ -0,0 +1,70 @@ +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 + + StyledPopupHeaderRow { + icon: "calendar_month" + label: root.formattedDate + } + + StyledPopupValueRow { + icon: "timelapse" + label: Translation.tr("System uptime:") + value: root.formattedUptime + } + + // Tasks + Column { + spacing: 0 + Layout.fillWidth: true + + StyledPopupValueRow { + icon: "checklist" + label: Translation.tr("To Do:") + value: "" + } + + StyledText { + horizontalAlignment: Text.AlignLeft + wrapMode: Text.Wrap + color: Appearance.colors.colOnSurfaceVariant + text: root.todosSection + } + } + } +} diff --git a/dots/.config/quickshell/ii/modules/bar/ClockWidgetTooltip.qml b/dots/.config/quickshell/ii/modules/bar/ClockWidgetTooltip.qml deleted file mode 100644 index 734d89b22..000000000 --- a/dots/.config/quickshell/ii/modules/bar/ClockWidgetTooltip.qml +++ /dev/null @@ -1,110 +0,0 @@ -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 - Row { - spacing: 5 - - MaterialSymbol { - anchors.verticalCenter: parent.verticalCenter - fill: 0 - font.weight: Font.Medium - text: "calendar_month" - iconSize: Appearance.font.pixelSize.large - color: Appearance.colors.colOnSurfaceVariant - } - StyledText { - anchors.verticalCenter: parent.verticalCenter - horizontalAlignment: Text.AlignLeft - color: Appearance.colors.colOnSurfaceVariant - text: `${root.formattedDate}` - 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 - Column { - spacing: 0 - Layout.fillWidth: true - - Row { - spacing: 4 - MaterialSymbol { - anchors.verticalCenter: parent.verticalCenter - text: "checklist" - color: Appearance.colors.colOnSurfaceVariant - font.pixelSize: Appearance.font.pixelSize.large - } - StyledText { - anchors.verticalCenter: parent.verticalCenter - text: Translation.tr("To Do:") - color: Appearance.colors.colOnSurfaceVariant - } - } - - StyledText { - horizontalAlignment: Text.AlignLeft - wrapMode: Text.Wrap - color: Appearance.colors.colOnSurfaceVariant - text: root.todosSection - } - } - } -} diff --git a/dots/.config/quickshell/ii/modules/bar/ResourcesPopup.qml b/dots/.config/quickshell/ii/modules/bar/ResourcesPopup.qml index 1cac240d8..40ed72756 100644 --- a/dots/.config/quickshell/ii/modules/bar/ResourcesPopup.qml +++ b/dots/.config/quickshell/ii/modules/bar/ResourcesPopup.qml @@ -12,57 +12,6 @@ StyledPopup { return (kb / (1024 * 1024)).toFixed(1) + " GB"; } - component ResourceItem: RowLayout { - id: resourceItem - required property string icon - required property string label - required property string value - spacing: 4 - - MaterialSymbol { - text: resourceItem.icon - color: Appearance.colors.colOnSurfaceVariant - iconSize: Appearance.font.pixelSize.large - } - StyledText { - text: resourceItem.label - color: Appearance.colors.colOnSurfaceVariant - } - StyledText { - Layout.fillWidth: true - horizontalAlignment: Text.AlignRight - visible: resourceItem.value !== "" - color: Appearance.colors.colOnSurfaceVariant - text: resourceItem.value - } - } - - component ResourceHeaderItem: Row { - id: headerItem - required property var icon - required property var label - spacing: 5 - - MaterialSymbol { - anchors.verticalCenter: parent.verticalCenter - fill: 0 - font.weight: Font.Medium - text: headerItem.icon - iconSize: Appearance.font.pixelSize.large - color: Appearance.colors.colOnSurfaceVariant - } - - StyledText { - anchors.verticalCenter: parent.verticalCenter - text: headerItem.label - font { - weight: Font.Medium - pixelSize: Appearance.font.pixelSize.normal - } - color: Appearance.colors.colOnSurfaceVariant - } - } - Row { anchors.centerIn: parent spacing: 12 @@ -71,23 +20,23 @@ StyledPopup { anchors.top: parent.top spacing: 8 - ResourceHeaderItem { + StyledPopupHeaderRow { icon: "memory" label: "RAM" } Column { spacing: 4 - ResourceItem { + StyledPopupValueRow { icon: "clock_loader_60" label: Translation.tr("Used:") value: root.formatKB(ResourceUsage.memoryUsed) } - ResourceItem { + StyledPopupValueRow { icon: "check_circle" label: Translation.tr("Free:") value: root.formatKB(ResourceUsage.memoryFree) } - ResourceItem { + StyledPopupValueRow { icon: "empty_dashboard" label: Translation.tr("Total:") value: root.formatKB(ResourceUsage.memoryTotal) @@ -100,23 +49,23 @@ StyledPopup { anchors.top: parent.top spacing: 8 - ResourceHeaderItem { + StyledPopupHeaderRow { icon: "swap_horiz" label: "Swap" } Column { spacing: 4 - ResourceItem { + StyledPopupValueRow { icon: "clock_loader_60" label: Translation.tr("Used:") value: root.formatKB(ResourceUsage.swapUsed) } - ResourceItem { + StyledPopupValueRow { icon: "check_circle" label: Translation.tr("Free:") value: root.formatKB(ResourceUsage.swapFree) } - ResourceItem { + StyledPopupValueRow { icon: "empty_dashboard" label: Translation.tr("Total:") value: root.formatKB(ResourceUsage.swapTotal) @@ -128,16 +77,16 @@ StyledPopup { anchors.top: parent.top spacing: 8 - ResourceHeaderItem { + StyledPopupHeaderRow { icon: "planner_review" label: "CPU" } Column { spacing: 4 - ResourceItem { + StyledPopupValueRow { 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)}%)` + value: `${Math.round(ResourceUsage.cpuUsage * 100)}%` } } } diff --git a/dots/.config/quickshell/ii/modules/bar/StyledPopupHeaderRow.qml b/dots/.config/quickshell/ii/modules/bar/StyledPopupHeaderRow.qml new file mode 100644 index 000000000..f5c7ba445 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/bar/StyledPopupHeaderRow.qml @@ -0,0 +1,30 @@ +import QtQuick +import QtQuick.Layouts +import qs.modules.common +import qs.modules.common.widgets + +Row { + id: root + required property var icon + required property var label + spacing: 5 + + MaterialSymbol { + anchors.verticalCenter: parent.verticalCenter + fill: 0 + font.weight: Font.DemiBold + text: root.icon + iconSize: Appearance.font.pixelSize.large + color: Appearance.colors.colOnSurfaceVariant + } + + StyledText { + anchors.verticalCenter: parent.verticalCenter + text: root.label + font { + weight: Font.DemiBold + pixelSize: Appearance.font.pixelSize.normal + } + color: Appearance.colors.colOnSurfaceVariant + } +} \ No newline at end of file diff --git a/dots/.config/quickshell/ii/modules/bar/StyledPopupValueRow.qml b/dots/.config/quickshell/ii/modules/bar/StyledPopupValueRow.qml new file mode 100644 index 000000000..de8ac579e --- /dev/null +++ b/dots/.config/quickshell/ii/modules/bar/StyledPopupValueRow.qml @@ -0,0 +1,29 @@ +import QtQuick +import QtQuick.Layouts +import qs.modules.common +import qs.modules.common.widgets + +RowLayout { + id: root + required property string icon + required property string label + required property string value + spacing: 4 + + MaterialSymbol { + text: root.icon + color: Appearance.colors.colOnSurfaceVariant + iconSize: Appearance.font.pixelSize.large + } + StyledText { + text: root.label + color: Appearance.colors.colOnSurfaceVariant + } + StyledText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignRight + visible: root.value !== "" + color: Appearance.colors.colOnSurfaceVariant + text: root.value + } +} diff --git a/dots/.config/quickshell/ii/modules/verticalBar/VerticalClockWidget.qml b/dots/.config/quickshell/ii/modules/verticalBar/VerticalClockWidget.qml index 391d2e78c..921f63603 100644 --- a/dots/.config/quickshell/ii/modules/verticalBar/VerticalClockWidget.qml +++ b/dots/.config/quickshell/ii/modules/verticalBar/VerticalClockWidget.qml @@ -36,7 +36,7 @@ Item { hoverEnabled: true acceptedButtons: Qt.NoButton - Bar.ClockWidgetTooltip { + Bar.ClockWidgetPopup { hoverTarget: mouseArea } } diff --git a/dots/.config/quickshell/ii/modules/verticalBar/VerticalMedia.qml b/dots/.config/quickshell/ii/modules/verticalBar/VerticalMedia.qml index 7a512564a..677941d64 100644 --- a/dots/.config/quickshell/ii/modules/verticalBar/VerticalMedia.qml +++ b/dots/.config/quickshell/ii/modules/verticalBar/VerticalMedia.qml @@ -74,30 +74,13 @@ MouseArea { anchors.centerIn: parent spacing: 4 - Row { - spacing: 4 - - MaterialSymbol { - anchors.verticalCenter: parent.verticalCenter - fill: 0 - font.weight: Font.Medium - text: "music_note" - iconSize: Appearance.font.pixelSize.large - color: Appearance.colors.colOnSurfaceVariant - } - - StyledText { - anchors.verticalCenter: parent.verticalCenter - text: "Media" - font { - weight: Font.Medium - pixelSize: Appearance.font.pixelSize.normal - } - color: Appearance.colors.colOnSurfaceVariant - } + Bar.StyledPopupHeaderRow { + icon: "music_note" + label: Translation.tr("Media") } StyledText { + color: Appearance.colors.colOnSurfaceVariant text: `${cleanedTitle}${activePlayer?.trackArtist ? '\n' + activePlayer.trackArtist : ''}` } }