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 "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: S.Theme.moduleSpacing spacing: S.Theme.moduleSpacing
opacity: S.Modules.battery.enable && S.BatteryService.available ? 1 : 0 opacity: S.Modules.battery.enable && S.BatteryService.available ? 1 : 0
visible: opacity > 0 visible: opacity > 0
tooltip: "" _panelHovered: hoverPanel.panelHovered
property real _blinkOpacity: 1 property real _blinkOpacity: 1
@ -34,24 +34,6 @@ M.BarSection {
root._blinkOpacity = 1 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 // Bar widgets
M.BarIcon { M.BarIcon {
icon: { icon: {

View file

@ -4,29 +4,12 @@ import "." as M
import "../services" as S import "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: S.Theme.moduleSpacing spacing: S.Theme.moduleSpacing
opacity: S.Modules.bluetooth.enable && S.BluetoothService.state !== "unavailable" ? 1 : 0 opacity: S.Modules.bluetooth.enable && S.BluetoothService.state !== "unavailable" ? 1 : 0
visible: opacity > 0 visible: opacity > 0
tooltip: "" _panelHovered: hoverPanel.panelHovered
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 { M.BarIcon {
icon: "\uF294" icon: "\uF294"

View file

@ -4,33 +4,16 @@ import "." as M
import "../services" as S import "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: S.Theme.moduleSpacing spacing: S.Theme.moduleSpacing
tooltip: "" _panelHovered: hoverPanel.panelHovered
SystemClock { SystemClock {
id: clock id: clock
precision: SystemClock.Seconds 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 { M.BarLabel {
font.pixelSize: S.Theme.fontSize + 1 font.pixelSize: S.Theme.fontSize + 1
label: Qt.formatDateTime(clock.date, "ddd, dd. MMM HH:mm") label: Qt.formatDateTime(clock.date, "ddd, dd. MMM HH:mm")

View file

@ -4,19 +4,15 @@ import "." as M
import "../services" as S import "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: Math.max(1, S.Theme.moduleSpacing - 2) spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: "" _panelHovered: hoverPanel.panelHovered
readonly property var _cores: S.SystemStats.cpuCores readonly property var _cores: S.SystemStats.cpuCores
readonly property var _coreMaxFreq: S.SystemStats.cpuCoreMaxFreq readonly property var _coreMaxFreq: S.SystemStats.cpuCoreMaxFreq
readonly property var _coreTypes: S.SystemStats.cpuCoreTypes 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 property bool _coreConsumerActive: false
on_ShowPanelChanged: { on_ShowPanelChanged: {
@ -35,19 +31,6 @@ M.BarSection {
onProcessesChanged: hoverPanel.keepOpen(300) 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 { M.BarIcon {
icon: "\uF2DB" icon: "\uF2DB"
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter

View file

@ -4,10 +4,10 @@ import "." as M
import "../services" as S import "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: Math.max(1, S.Theme.moduleSpacing - 2) spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: "" _panelHovered: hoverPanel.panelHovered
property var _mounts: S.SystemStats.diskMounts property var _mounts: S.SystemStats.diskMounts
property int _rootPct: S.SystemStats.diskRootPct property int _rootPct: S.SystemStats.diskRootPct
@ -19,23 +19,6 @@ M.BarSection {
return false; 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 { M.BarIcon {
icon: "\uF0C9" icon: "\uF0C9"
color: root._anyWarn ? S.Theme.base09 : root.accentColor color: root._anyWarn ? S.Theme.base09 : root.accentColor

View file

@ -4,28 +4,11 @@ import "." as M
import "../services" as S import "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: Math.max(1, S.Theme.moduleSpacing - 2) spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: ""
visible: S.Modules.gpu.enable && S.SystemStats.gpuAvailable visible: S.Modules.gpu.enable && S.SystemStats.gpuAvailable
_panelHovered: hoverPanel.panelHovered
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 { M.BarIcon {
icon: "\uEB4C" icon: "\uEB4C"

View file

@ -4,10 +4,10 @@ import "." as M
import "../services" as S import "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: Math.max(1, S.Theme.moduleSpacing - 2) spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: "" _panelHovered: hoverPanel.panelHovered
property int percent: S.SystemStats.memPercent property int percent: S.SystemStats.memPercent
property real usedGb: S.SystemStats.memUsedGb property real usedGb: S.SystemStats.memUsedGb
@ -16,29 +16,12 @@ M.BarSection {
property real cachedGb: S.SystemStats.memCachedGb property real cachedGb: S.SystemStats.memCachedGb
property real buffersGb: S.SystemStats.memBuffersGb 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 { property M.ProcessList _procs: M.ProcessList {
sortBy: "mem" sortBy: "mem"
active: root._showPanel active: root._showPanel
onProcessesChanged: hoverPanel.keepOpen(300) 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 { M.BarIcon {
icon: "\uEFC5" icon: "\uEFC5"
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter

View file

@ -6,12 +6,12 @@ import "." as M
import "../services" as S import "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: S.Theme.moduleSpacing spacing: S.Theme.moduleSpacing
opacity: S.Modules.mpris.enable && player !== null ? 1 : 0 opacity: S.Modules.mpris.enable && player !== null ? 1 : 0
visible: opacity > 0 visible: opacity > 0
tooltip: "" _panelHovered: hoverPanel.panelHovered
readonly property var _players: S.MprisService.players readonly property var _players: S.MprisService.players
readonly property MprisPlayer player: S.MprisService.player readonly property MprisPlayer player: S.MprisService.player
@ -71,23 +71,6 @@ M.BarSection {
required property var bar 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 { M.BarIcon {
icon: root.playing ? "\uF04B" : (root.player?.playbackState === MprisPlaybackState.Paused ? "\uDB80\uDFE4" : "\uDB81\uDCDB") icon: root.playing ? "\uF04B" : (root.player?.playbackState === MprisPlaybackState.Paused ? "\uDB80\uDFE4" : "\uDB81\uDCDB")
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter

View file

@ -4,30 +4,13 @@ import "." as M
import "../services" as S import "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: S.Theme.moduleSpacing spacing: S.Theme.moduleSpacing
tooltip: "" _panelHovered: hoverPanel.panelHovered
readonly property string state: S.NetworkService.state 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 { M.BarIcon {
icon: { icon: {
if (root.state === "wifi") if (root.state === "wifi")

View file

@ -5,30 +5,13 @@ import "." as M
import "../services" as S import "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: S.Theme.moduleSpacing spacing: S.Theme.moduleSpacing
tooltip: "" _panelHovered: hoverPanel.panelHovered
readonly property bool hasUrgent: S.NotifService.list.some(n => n.urgency === NotificationUrgency.Critical && n.state !== "dismissed") 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 { M.BarIcon {
icon: { icon: {
if (S.NotifService.dnd) 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 "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: Math.max(1, S.Theme.moduleSpacing - 2) spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: "" _panelHovered: hoverPanel.panelHovered
readonly property int _warm: S.Modules.temperature.warm || 80 readonly property int _warm: S.Modules.temperature.warm || 80
readonly property int _hot: S.Modules.temperature.hot || 90 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 { M.BarIcon {
icon: "\uF2C9" icon: "\uF2C9"
color: root._stateColor color: root._stateColor

View file

@ -4,28 +4,11 @@ import "." as M
import "../services" as S import "../services" as S
import "../applets" as C import "../applets" as C
M.BarSection { M.PinnableSection {
id: root id: root
spacing: S.Theme.moduleSpacing spacing: S.Theme.moduleSpacing
tooltip: ""
visible: S.Modules.weather.enable && S.WeatherService.available visible: S.Modules.weather.enable && S.WeatherService.available
_panelHovered: hoverPanel.panelHovered
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 { M.BarIcon {
icon: S.WeatherService.icon icon: S.WeatherService.icon

View file

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