extract PinnableSection base component from 12 bar modules

This commit is contained in:
Damocles 2026-04-23 00:48:07 +02:00
parent deb3fc0a12
commit aa0f7bb5ef
14 changed files with 55 additions and 229 deletions

View file

@ -4,12 +4,12 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: S.Theme.moduleSpacing
opacity: S.Modules.battery.enable && S.BatteryService.available ? 1 : 0
visible: opacity > 0
tooltip: ""
_panelHovered: hoverPanel.panelHovered
property real _blinkOpacity: 1
@ -34,24 +34,6 @@ M.BarSection {
root._blinkOpacity = 1
}
// Panel state
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
// Bar widgets
M.BarIcon {
icon: {

View file

@ -4,29 +4,12 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: S.Theme.moduleSpacing
opacity: S.Modules.bluetooth.enable && S.BluetoothService.state !== "unavailable" ? 1 : 0
visible: opacity > 0
tooltip: ""
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
_panelHovered: hoverPanel.panelHovered
M.BarIcon {
icon: "\uF294"

View file

@ -4,33 +4,16 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: S.Theme.moduleSpacing
tooltip: ""
_panelHovered: hoverPanel.panelHovered
SystemClock {
id: clock
precision: SystemClock.Seconds
}
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
M.BarLabel {
font.pixelSize: S.Theme.fontSize + 1
label: Qt.formatDateTime(clock.date, "ddd, dd. MMM HH:mm")

View file

@ -4,19 +4,15 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: ""
_panelHovered: hoverPanel.panelHovered
readonly property var _cores: S.SystemStats.cpuCores
readonly property var _coreMaxFreq: S.SystemStats.cpuCoreMaxFreq
readonly property var _coreTypes: S.SystemStats.cpuCoreTypes
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
property bool _coreConsumerActive: false
on_ShowPanelChanged: {
@ -35,19 +31,6 @@ M.BarSection {
onProcessesChanged: hoverPanel.keepOpen(300)
}
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
M.BarIcon {
icon: "\uF2DB"
anchors.verticalCenter: parent.verticalCenter

View file

@ -4,10 +4,10 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: ""
_panelHovered: hoverPanel.panelHovered
property var _mounts: S.SystemStats.diskMounts
property int _rootPct: S.SystemStats.diskRootPct
@ -19,23 +19,6 @@ M.BarSection {
return false;
}
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
M.BarIcon {
icon: "\uF0C9"
color: root._anyWarn ? S.Theme.base09 : root.accentColor

View file

@ -4,28 +4,11 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: ""
visible: S.Modules.gpu.enable && S.SystemStats.gpuAvailable
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
_panelHovered: hoverPanel.panelHovered
M.BarIcon {
icon: "\uEB4C"

View file

@ -4,10 +4,10 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: ""
_panelHovered: hoverPanel.panelHovered
property int percent: S.SystemStats.memPercent
property real usedGb: S.SystemStats.memUsedGb
@ -16,29 +16,12 @@ M.BarSection {
property real cachedGb: S.SystemStats.memCachedGb
property real buffersGb: S.SystemStats.memBuffersGb
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
property M.ProcessList _procs: M.ProcessList {
sortBy: "mem"
active: root._showPanel
onProcessesChanged: hoverPanel.keepOpen(300)
}
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
M.BarIcon {
icon: "\uEFC5"
anchors.verticalCenter: parent.verticalCenter

View file

@ -6,12 +6,12 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: S.Theme.moduleSpacing
opacity: S.Modules.mpris.enable && player !== null ? 1 : 0
visible: opacity > 0
tooltip: ""
_panelHovered: hoverPanel.panelHovered
readonly property var _players: S.MprisService.players
readonly property MprisPlayer player: S.MprisService.player
@ -71,23 +71,6 @@ M.BarSection {
required property var bar
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
M.BarIcon {
icon: root.playing ? "\uF04B" : (root.player?.playbackState === MprisPlaybackState.Paused ? "\uDB80\uDFE4" : "\uDB81\uDCDB")
anchors.verticalCenter: parent.verticalCenter

View file

@ -4,30 +4,13 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: S.Theme.moduleSpacing
tooltip: ""
_panelHovered: hoverPanel.panelHovered
readonly property string state: S.NetworkService.state
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
M.BarIcon {
icon: {
if (root.state === "wifi")

View file

@ -5,30 +5,13 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: S.Theme.moduleSpacing
tooltip: ""
_panelHovered: hoverPanel.panelHovered
readonly property bool hasUrgent: S.NotifService.list.some(n => n.urgency === NotificationUrgency.Critical && n.state !== "dismissed")
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
M.BarIcon {
icon: {
if (S.NotifService.dnd)

View file

@ -0,0 +1,30 @@
import QtQuick
import Quickshell
import "." as M
import "../services" as S
// Base component for bar modules with a pinnable hover panel.
// Provides the _pinned/_anyHover/_showPanel/_unpinTimer boilerplate.
// Modules bind _panelHovered to their HoverPanel's panelHovered property.
M.BarSection {
id: root
tooltip: ""
property bool _pinned: false
property bool _panelHovered: false
readonly property bool _anyHover: root._hovered || _panelHovered
readonly property bool _showPanel: _anyHover || _pinned
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
}

View file

@ -4,10 +4,10 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: ""
_panelHovered: hoverPanel.panelHovered
readonly property int _warm: S.Modules.temperature.warm || 80
readonly property int _hot: S.Modules.temperature.hot || 90
@ -30,23 +30,6 @@ M.BarSection {
}
}
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
M.BarIcon {
icon: "\uF2C9"
color: root._stateColor

View file

@ -4,28 +4,11 @@ import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
M.PinnableSection {
id: root
spacing: S.Theme.moduleSpacing
tooltip: ""
visible: S.Modules.weather.enable && S.WeatherService.available
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
_panelHovered: hoverPanel.panelHovered
M.BarIcon {
icon: S.WeatherService.icon

View file

@ -23,6 +23,7 @@ NotifCard 1.0 NotifCard.qml
NotifPopup 1.0 NotifPopup.qml
NotificationsModule 1.0 NotificationsModule.qml
OverviewBackdrop 1.0 OverviewBackdrop.qml
PinnableSection 1.0 PinnableSection.qml
PopupBackground 1.0 PopupBackground.qml
PowerMenu 1.0 PowerMenu.qml
PowerModule 1.0 PowerModule.qml