diff --git a/modules/Backlight.qml b/modules/Backlight.qml index 46e9477..a0ccc90 100644 --- a/modules/Backlight.qml +++ b/modules/Backlight.qml @@ -1,12 +1,12 @@ import QtQuick import Quickshell.Io -import QtQuick.Controls import "." as M -Row { +M.BarSection { id: root spacing: 4 visible: percent > 0 + tooltip: "Brightness: " + root.percent + "%" property int percent: 0 @@ -53,9 +53,4 @@ Row { WheelHandler { onWheel: event => root.adjust(event.angleDelta.y) } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: "Brightness: " + root.percent + "%" - } } diff --git a/modules/BarIcon.qml b/modules/BarIcon.qml index 82a4df5..3d22c14 100644 --- a/modules/BarIcon.qml +++ b/modules/BarIcon.qml @@ -1,12 +1,20 @@ import QtQuick +import QtQuick.Controls import "." as M Text { property string icon: "" + property string tooltip: "" text: icon color: M.Theme.base05 font.pixelSize: M.Theme.fontSize + 1 font.family: M.Theme.iconFontFamily verticalAlignment: Text.AlignVCenter + + HoverHandler { id: _hover } + ToolTip { + visible: _hover.hovered && parent.tooltip !== "" + text: parent.tooltip + } } diff --git a/modules/BarSection.qml b/modules/BarSection.qml new file mode 100644 index 0000000..7c9b236 --- /dev/null +++ b/modules/BarSection.qml @@ -0,0 +1,12 @@ +import QtQuick +import QtQuick.Controls + +Row { + property string tooltip: "" + + HoverHandler { id: _hover } + ToolTip { + visible: _hover.hovered && parent.tooltip !== "" + text: parent.tooltip + } +} diff --git a/modules/Battery.qml b/modules/Battery.qml index 90397d4..11d6c1b 100644 --- a/modules/Battery.qml +++ b/modules/Battery.qml @@ -1,12 +1,18 @@ import QtQuick -import QtQuick.Controls import Quickshell.Services.UPower import "." as M -Row { +M.BarSection { id: root spacing: 4 visible: UPower.displayDevice?.isLaptopBattery ?? false + tooltip: { + const state = root.charging ? "Charging" : "Discharging"; + const t = root.charging ? root.dev?.timeToFull : root.dev?.timeToEmpty; + const mins = t ? Math.round(t / 60) : 0; + const timeStr = mins > 0 ? "\n" + Math.floor(mins / 60) + "h " + (mins % 60) + "m " + (root.charging ? "until full" : "remaining") : ""; + return state + " \u2014 " + Math.round(root.pct) + "%" + timeStr; + } readonly property var dev: UPower.displayDevice readonly property real pct: (dev?.percentage ?? 0) * 100 @@ -27,16 +33,4 @@ Row { color: root.pct < 15 ? M.Theme.base08 : M.Theme.base05 anchors.verticalCenter: parent.verticalCenter } - - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: { - const state = root.charging ? "Charging" : "Discharging"; - const t = root.charging ? root.dev?.timeToFull : root.dev?.timeToEmpty; - const mins = t ? Math.round(t / 60) : 0; - const timeStr = mins > 0 ? "\n" + Math.floor(mins / 60) + "h " + (mins % 60) + "m " + (root.charging ? "until full" : "remaining") : ""; - return state + " — " + Math.round(root.pct) + "%" + timeStr; - } - } } diff --git a/modules/Bluetooth.qml b/modules/Bluetooth.qml index 556d928..07e2c56 100644 --- a/modules/Bluetooth.qml +++ b/modules/Bluetooth.qml @@ -1,11 +1,11 @@ import QtQuick import Quickshell.Io -import QtQuick.Controls import "." as M -Row { +M.BarSection { id: root spacing: 4 + tooltip: root.status === "connected" ? "Bluetooth: " + root.device : "Bluetooth: on" property string status: "off" property string device: "" @@ -42,9 +42,4 @@ Row { font.family: M.Theme.fontFamily anchors.verticalCenter: parent.verticalCenter } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: root.status === "connected" ? "Bluetooth: " + root.device : "Bluetooth: on" - } } diff --git a/modules/Cpu.qml b/modules/Cpu.qml index 0cc3100..00a1eb6 100644 --- a/modules/Cpu.qml +++ b/modules/Cpu.qml @@ -1,15 +1,14 @@ import QtQuick import Quickshell.Io -import QtQuick.Controls import "." as M -Row { +M.BarSection { id: root spacing: 2 + tooltip: "CPU: " + root.usage + "%\n" + root.freqGhz.toFixed(2) + " GHz" property int usage: 0 property real freqGhz: 0 - property var _prev: null FileView { @@ -26,10 +25,7 @@ Row { if (dTotal > 0) root.usage = Math.round((1 - dIdle / dTotal) * 100); } - root._prev = { - idle, - total - }; + root._prev = { idle, total }; } } FileView { @@ -37,8 +33,7 @@ Row { path: "/proc/cpuinfo" onLoaded: { const lines = text().split("\n").filter(l => l.startsWith("cpu MHz")); - if (lines.length === 0) - return; + if (lines.length === 0) return; const sum = lines.reduce((a, l) => a + parseFloat(l.split(":")[1]), 0); root.freqGhz = sum / lines.length / 1000; } @@ -47,10 +42,7 @@ Row { interval: 1000 running: true repeat: true - onTriggered: { - stat.reload(); - cpuinfo.reload(); - } + onTriggered: { stat.reload(); cpuinfo.reload(); } } M.BarIcon { @@ -64,9 +56,4 @@ Row { font.family: M.Theme.fontFamily verticalAlignment: Text.AlignVCenter } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: "CPU: " + root.usage + "%\n" + root.freqGhz.toFixed(2) + " GHz" - } } diff --git a/modules/Disk.qml b/modules/Disk.qml index 0ac0758..df33abc 100644 --- a/modules/Disk.qml +++ b/modules/Disk.qml @@ -1,11 +1,11 @@ import QtQuick import Quickshell.Io -import QtQuick.Controls import "." as M -Row { +M.BarSection { id: root spacing: 2 + tooltip: root.freePct + "% free of " + root.totalTb.toFixed(1) + " TB" property int freePct: 0 property real totalTb: 0 @@ -43,9 +43,4 @@ Row { font.family: M.Theme.fontFamily verticalAlignment: Text.AlignVCenter } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: root.freePct + "% free of " + root.totalTb.toFixed(1) + " TB" - } } diff --git a/modules/IdleInhibitor.qml b/modules/IdleInhibitor.qml index 1ab30fd..d2b0fbe 100644 --- a/modules/IdleInhibitor.qml +++ b/modules/IdleInhibitor.qml @@ -1,10 +1,10 @@ import QtQuick import Quickshell.Io -import QtQuick.Controls import "." as M M.BarIcon { id: root + tooltip: "Idle inhibition: " + (root.active ? "active" : "inactive") property bool active: false @@ -23,9 +23,4 @@ M.BarIcon { toggle.running = true; } } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: "Idle inhibition: " + (root.active ? "active" : "inactive") - } } diff --git a/modules/Memory.qml b/modules/Memory.qml index 039f8ee..1faab25 100644 --- a/modules/Memory.qml +++ b/modules/Memory.qml @@ -1,11 +1,11 @@ import QtQuick import Quickshell.Io -import QtQuick.Controls import "." as M -Row { +M.BarSection { id: root spacing: 2 + tooltip: "Memory: " + root.percent + "% used" property int percent: 0 @@ -16,8 +16,7 @@ Row { const m = {}; text().split("\n").forEach(l => { const [k, v] = l.split(":"); - if (v) - m[k.trim()] = parseInt(v.trim()); + if (v) m[k.trim()] = parseInt(v.trim()); }); const total = m.MemTotal; const avail = m.MemAvailable; @@ -43,9 +42,4 @@ Row { font.family: M.Theme.fontFamily verticalAlignment: Text.AlignVCenter } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: "Memory: " + root.percent + "% used" - } } diff --git a/modules/Mpris.qml b/modules/Mpris.qml index 5e9412c..5ed5737 100644 --- a/modules/Mpris.qml +++ b/modules/Mpris.qml @@ -1,12 +1,20 @@ import QtQuick -import QtQuick.Controls import Quickshell.Services.Mpris import "." as M -Row { +M.BarSection { id: root spacing: 4 visible: player !== null + tooltip: { + const p = root.player; + if (!p) return ""; + const parts = []; + if (p.trackTitle) parts.push(p.trackTitle); + if (p.trackArtists?.length) parts.push(p.trackArtists.join(", ")); + if (p.trackAlbum) parts.push(p.trackAlbum); + return parts.join("\n") || p.identity; + } readonly property MprisPlayer player: Mpris.players.values[0] ?? null readonly property bool playing: player?.playbackState === MprisPlaybackState.Playing @@ -20,20 +28,6 @@ Row { anchors.verticalCenter: parent.verticalCenter } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: { - const p = root.player; - if (!p) return ""; - const parts = []; - if (p.trackTitle) parts.push(p.trackTitle); - if (p.trackArtists?.length) parts.push(p.trackArtists.join(", ")); - if (p.trackAlbum) parts.push(p.trackAlbum); - return parts.join("\n") || p.identity; - } - } - TapHandler { onTapped: root.player?.togglePlaying() } diff --git a/modules/Network.qml b/modules/Network.qml index dc7fb7c..e9451ef 100644 --- a/modules/Network.qml +++ b/modules/Network.qml @@ -1,11 +1,16 @@ import QtQuick -import QtQuick.Controls import Quickshell.Io import "." as M -Row { +M.BarSection { id: root spacing: 4 + tooltip: { + if (root.state === "wifi") return "WiFi: " + root.essid + (root.ifname ? "\nInterface: " + root.ifname : ""); + if (root.state === "eth") return "Ethernet: " + root.ifname; + if (root.state === "linked") return "Linked: " + root.ifname; + return "Disconnected"; + } property string ifname: "" property string essid: "" @@ -45,12 +50,9 @@ Row { M.BarIcon { icon: { - if (root.state === "wifi") - return "\uF1EB"; - if (root.state === "eth") - return "\uDB80\uDE00"; - if (root.state === "linked") - return "\uDB85\uDE16"; + if (root.state === "wifi") return "\uF1EB"; + if (root.state === "eth") return "\uDB80\uDE00"; + if (root.state === "linked") return "\uDB85\uDE16"; return "\uDB82\uDCFD"; } anchors.verticalCenter: parent.verticalCenter @@ -63,15 +65,4 @@ Row { font.family: M.Theme.fontFamily anchors.verticalCenter: parent.verticalCenter } - - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: { - if (root.state === "wifi") return "WiFi: " + root.essid + (root.ifname ? "\nInterface: " + root.ifname : ""); - if (root.state === "eth") return "Ethernet: " + root.ifname; - if (root.state === "linked") return "Linked: " + root.ifname; - return "Disconnected"; - } - } } diff --git a/modules/Notifications.qml b/modules/Notifications.qml index ba15fe2..fdca87d 100644 --- a/modules/Notifications.qml +++ b/modules/Notifications.qml @@ -1,11 +1,16 @@ import QtQuick -import QtQuick.Controls import Quickshell.Io import "." as M -Row { +M.BarSection { id: root spacing: 4 + tooltip: { + const parts = [root.count + " notification" + (root.count !== 1 ? "s" : "")]; + if (root.dnd) parts.push("Do not disturb"); + if (root.inhibited) parts.push("Inhibited"); + return parts.join("\n"); + } property int count: 0 property bool dnd: false @@ -56,18 +61,5 @@ Row { clicker.running = true; } } - Process { - id: clicker - } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: { - const parts = []; - parts.push(root.count + " notification" + (root.count !== 1 ? "s" : "")); - if (root.dnd) parts.push("Do not disturb"); - if (root.inhibited) parts.push("Inhibited"); - return parts.join("\n"); - } - } + Process { id: clicker } } diff --git a/modules/PowerProfile.qml b/modules/PowerProfile.qml index f15542d..e3c0bb0 100644 --- a/modules/PowerProfile.qml +++ b/modules/PowerProfile.qml @@ -1,10 +1,10 @@ import QtQuick import Quickshell.Io -import QtQuick.Controls import "." as M M.BarIcon { id: root + tooltip: "Power profile: " + (root.profile || "unknown") property string profile: "" @@ -45,9 +45,4 @@ M.BarIcon { setter.running = true; } } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: "Power profile: " + (root.profile || "unknown") - } } diff --git a/modules/Temperature.qml b/modules/Temperature.qml index facee92..c302962 100644 --- a/modules/Temperature.qml +++ b/modules/Temperature.qml @@ -1,11 +1,11 @@ import QtQuick import Quickshell.Io -import QtQuick.Controls import "." as M -Row { +M.BarSection { id: root spacing: 2 + tooltip: "Temperature: " + root.celsius + "\u00B0C" property int celsius: 0 @@ -27,15 +27,10 @@ Row { anchors.verticalCenter: parent.verticalCenter } Text { - text: root.celsius + "°C" + text: root.celsius + "\u00B0C" color: root.celsius > 80 ? M.Theme.base08 : M.Theme.base05 font.pixelSize: M.Theme.fontSize font.family: M.Theme.fontFamily verticalAlignment: Text.AlignVCenter } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: "Temperature: " + root.celsius + "\u00B0C" - } } diff --git a/modules/Volume.qml b/modules/Volume.qml index c82a960..f17d676 100644 --- a/modules/Volume.qml +++ b/modules/Volume.qml @@ -1,11 +1,13 @@ import QtQuick -import QtQuick.Controls import Quickshell.Services.Pipewire import "." as M -Row { +M.BarSection { id: root spacing: 4 + tooltip: (root.sink?.description ?? root.sink?.name ?? "Unknown sink") + + "\nVolume: " + Math.round(root.volume * 100) + "%" + + (root.muted ? "\nMuted" : "") PwObjectTracker { objects: [Pipewire.defaultAudioSink] @@ -24,14 +26,6 @@ Row { anchors.verticalCenter: parent.verticalCenter } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: (root.sink?.description ?? root.sink?.name ?? "Unknown sink") + - "\nVolume: " + Math.round(root.volume * 100) + "%" + - (root.muted ? "\nMuted" : "") - } - TapHandler { onTapped: if (root.sink?.audio) root.sink.audio.muted = !root.sink.audio.muted } diff --git a/modules/Wlogout.qml b/modules/Wlogout.qml index 47bc260..48825f3 100644 --- a/modules/Wlogout.qml +++ b/modules/Wlogout.qml @@ -1,10 +1,10 @@ import QtQuick import Quickshell.Io -import QtQuick.Controls import "." as M M.BarIcon { icon: "\uF011" + tooltip: "Open logout menu" Process { id: proc @@ -16,9 +16,4 @@ M.BarIcon { cursorShape: Qt.PointingHandCursor onClicked: proc.running = true } - HoverHandler { id: hover } - ToolTip { - visible: hover.hovered - text: "Open logout menu" - } } diff --git a/modules/qmldir b/modules/qmldir index f0c494e..77815c6 100644 --- a/modules/qmldir +++ b/modules/qmldir @@ -1,6 +1,7 @@ module modules singleton Theme 1.0 Theme.qml Bar 1.0 Bar.qml +BarSection 1.0 BarSection.qml Workspaces 1.0 Workspaces.qml WindowTitle 1.0 WindowTitle.qml Clock 1.0 Clock.qml