move Theme, SystemStats, Modules to shell/services/

This commit is contained in:
Damocles 2026-04-17 22:07:00 +02:00
commit 989182d603
59 changed files with 432 additions and 388 deletions

View file

@ -25,7 +25,7 @@ stdenvNoCC.mkDerivation {
runHook preInstall runHook preInstall
mkdir -p $out/share/nova-shell mkdir -p $out/share/nova-shell
cp -r shell/shell.qml shell/modules shell/applets shell/lock shell/assets $out/share/nova-shell/ cp -r shell/shell.qml shell/modules shell/services shell/applets shell/lock shell/assets $out/share/nova-shell/
# Compile fragment shader to Qt RHI format # Compile fragment shader to Qt RHI format
qsb --qt6 \ qsb --qt6 \

View file

@ -1,5 +1,5 @@
import QtQuick import QtQuick
import "../modules" as M import "../services" as M
Column { Column {
id: root id: root

View file

@ -1,5 +1,5 @@
import QtQuick import QtQuick
import "../modules" as M import "../services" as M
Column { Column {
id: root id: root

View file

@ -1,6 +1,6 @@
import QtQuick import QtQuick
import Quickshell import Quickshell
import "../modules" as M import "../services" as M
Item { Item {
id: root id: root

View file

@ -1,5 +1,5 @@
import QtQuick import QtQuick
import "../modules" as M import "../services" as M
Column { Column {
id: root id: root

View file

@ -1,6 +1,6 @@
import QtQuick import QtQuick
import Quickshell.Services.Mpris import Quickshell.Services.Mpris
import "../modules" as M import "../services" as M
Column { Column {
id: root id: root

View file

@ -1,5 +1,5 @@
import QtQuick import QtQuick
import "../modules" as M import "../services" as M
Column { Column {
id: root id: root

View file

@ -1,6 +1,6 @@
import QtQuick import QtQuick
import Quickshell.Services.Pipewire import Quickshell.Services.Pipewire
import "../modules" as M import "../services" as M
Column { Column {
id: root id: root

View file

@ -2,7 +2,7 @@ import QtQuick
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
import Quickshell.Wayland import Quickshell.Wayland
import "../modules" as M import "../services" as M
Scope { Scope {
id: root id: root

View file

@ -1,5 +1,5 @@
import QtQuick import QtQuick
import "../modules" as M import "../services" as M
Item { Item {
id: root id: root

View file

@ -4,7 +4,7 @@ import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Services.Mpris import Quickshell.Services.Mpris
import Quickshell.Services.Pipewire import Quickshell.Services.Pipewire
import "../modules" as M import "../services" as M
import "../applets" as C import "../applets" as C
WlSessionLockSurface { WlSessionLockSurface {

View file

@ -3,6 +3,7 @@ import QtQuick.Effects
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import "." as M import "." as M
import "../services" as S
PanelWindow { PanelWindow {
id: root id: root
@ -44,9 +45,9 @@ PanelWindow {
Text { Text {
text: Qt.formatDateTime(clock.date, "HH") text: Qt.formatDateTime(clock.date, "HH")
color: M.Theme.base0D color: S.Theme.base0D
font.pixelSize: 72 font.pixelSize: 72
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
font.bold: true font.bold: true
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@ -54,22 +55,22 @@ PanelWindow {
text: ":" text: ":"
color: colon._colors[colon._colorIdx % colon._colors.length] color: colon._colors[colon._colorIdx % colon._colors.length]
Behavior on color { Behavior on color {
enabled: !M.Theme.reducedMotion enabled: !S.Theme.reducedMotion
ColorAnimation { ColorAnimation {
duration: 500 duration: 500
} }
} }
font.pixelSize: 72 font.pixelSize: 72
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
font.bold: true font.bold: true
opacity: colon.opacity opacity: colon.opacity
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
Text { Text {
text: Qt.formatDateTime(clock.date, "mm") text: Qt.formatDateTime(clock.date, "mm")
color: M.Theme.base0E color: S.Theme.base0E
font.pixelSize: 72 font.pixelSize: 72
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
font.bold: true font.bold: true
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@ -79,7 +80,7 @@ PanelWindow {
source: glowSource source: glowSource
anchors.fill: glowSource anchors.fill: glowSource
shadowEnabled: true shadowEnabled: true
shadowColor: M.Theme.base0D shadowColor: S.Theme.base0D
shadowBlur: 1.0 shadowBlur: 1.0
shadowVerticalOffset: 0 shadowVerticalOffset: 0
shadowHorizontalOffset: 0 shadowHorizontalOffset: 0
@ -92,10 +93,10 @@ PanelWindow {
Text { Text {
text: Qt.formatDateTime(clock.date, "HH") text: Qt.formatDateTime(clock.date, "HH")
color: M.Theme.base0D color: S.Theme.base0D
opacity: 0.85 opacity: 0.85
font.pixelSize: 72 font.pixelSize: 72
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
font.bold: true font.bold: true
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@ -103,16 +104,16 @@ PanelWindow {
id: colon id: colon
text: ":" text: ":"
font.pixelSize: 72 font.pixelSize: 72
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
font.bold: true font.bold: true
opacity: 0.85 opacity: 0.85
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
property int _colorIdx: 0 property int _colorIdx: 0
readonly property var _colors: [M.Theme.base08, M.Theme.base09, M.Theme.base0A, M.Theme.base0B, M.Theme.base0C, M.Theme.base0D, M.Theme.base0E, M.Theme.base05] readonly property var _colors: [S.Theme.base08, S.Theme.base09, S.Theme.base0A, S.Theme.base0B, S.Theme.base0C, S.Theme.base0D, S.Theme.base0E, S.Theme.base05]
color: _colors[_colorIdx % _colors.length] color: _colors[_colorIdx % _colors.length]
Behavior on color { Behavior on color {
enabled: !M.Theme.reducedMotion enabled: !S.Theme.reducedMotion
ColorAnimation { ColorAnimation {
duration: 500 duration: 500
} }
@ -140,7 +141,7 @@ PanelWindow {
Connections { Connections {
target: clock target: clock
function onDateChanged() { function onDateChanged() {
if (M.Theme.reducedMotion) if (S.Theme.reducedMotion)
return; return;
colon._colorIdx++; colon._colorIdx++;
colonAnim.restart(); colonAnim.restart();
@ -149,10 +150,10 @@ PanelWindow {
} }
Text { Text {
text: Qt.formatDateTime(clock.date, "mm") text: Qt.formatDateTime(clock.date, "mm")
color: M.Theme.base0E color: S.Theme.base0E
opacity: 0.85 opacity: 0.85
font.pixelSize: 72 font.pixelSize: 72
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
font.bold: true font.bold: true
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@ -164,16 +165,16 @@ PanelWindow {
id: dateText id: dateText
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: Qt.formatDateTime(clock.date, "dddd, dd MMMM yyyy") text: Qt.formatDateTime(clock.date, "dddd, dd MMMM yyyy")
color: M.Theme.base05 color: S.Theme.base05
opacity: 0.5 opacity: 0.5
font.pixelSize: 18 font.pixelSize: 18
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
font.letterSpacing: 4 font.letterSpacing: 4
layer.enabled: true layer.enabled: true
layer.effect: MultiEffect { layer.effect: MultiEffect {
shadowEnabled: true shadowEnabled: true
shadowColor: M.Theme.base0D shadowColor: S.Theme.base0D
shadowBlur: 0.4 shadowBlur: 0.4
shadowVerticalOffset: 0 shadowVerticalOffset: 0
shadowHorizontalOffset: 0 shadowHorizontalOffset: 0
@ -188,7 +189,7 @@ PanelWindow {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: M.Theme.base02 color: S.Theme.base02
radius: 1 radius: 1
opacity: 0.3 opacity: 0.3
} }
@ -197,7 +198,7 @@ PanelWindow {
height: parent.height height: parent.height
color: colon._colors[colon._colorIdx % colon._colors.length] color: colon._colors[colon._colorIdx % colon._colors.length]
Behavior on color { Behavior on color {
enabled: !M.Theme.reducedMotion enabled: !S.Theme.reducedMotion
ColorAnimation { ColorAnimation {
duration: 500 duration: 500
} }
@ -206,7 +207,7 @@ PanelWindow {
opacity: 0.6 opacity: 0.6
Behavior on width { Behavior on width {
enabled: !M.Theme.reducedMotion enabled: !S.Theme.reducedMotion
NumberAnimation { NumberAnimation {
duration: 50 duration: 50
} }

View file

@ -2,11 +2,12 @@ import QtQuick
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
import "." as M import "." as M
import "../services" as S
M.BarSection { M.BarSection {
id: root id: root
spacing: M.Theme.moduleSpacing spacing: S.Theme.moduleSpacing
opacity: M.Modules.backlight.enable && percent > 0 ? 1 : 0 opacity: S.Modules.backlight.enable && percent > 0 ? 1 : 0
visible: opacity > 0 visible: opacity > 0
tooltip: "" tooltip: ""
@ -44,7 +45,7 @@ M.BarSection {
} }
function adjust(delta) { function adjust(delta) {
const step = M.Modules.backlight.step || 5; const step = S.Modules.backlight.step || 5;
adjProc.cmd = delta > 0 ? "light -A " + step : "light -U " + step; adjProc.cmd = delta > 0 ? "light -A " + step : "light -U " + step;
adjProc.running = true; adjProc.running = true;
} }
@ -123,8 +124,8 @@ M.BarSection {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: "\uF185" text: "\uF185"
color: root.accentColor color: root.accentColor
font.pixelSize: M.Theme.fontSize + 2 font.pixelSize: S.Theme.fontSize + 2
font.family: M.Theme.iconFontFamily font.family: S.Theme.iconFontFamily
} }
Item { Item {
@ -138,7 +139,7 @@ M.BarSection {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: M.Theme.base02 color: S.Theme.base02
radius: 3 radius: 3
} }
@ -176,9 +177,9 @@ M.BarSection {
anchors.rightMargin: 12 anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: root.percent + "%" text: root.percent + "%"
color: M.Theme.base05 color: S.Theme.base05
font.pixelSize: M.Theme.fontSize font.pixelSize: S.Theme.fontSize
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
width: 30 width: 30
} }
} }

View file

@ -3,6 +3,7 @@ import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import "." as M import "." as M
import "../services" as S
PanelWindow { PanelWindow {
id: bar id: bar
@ -18,13 +19,13 @@ PanelWindow {
right: true right: true
} }
implicitHeight: M.Theme.barHeight implicitHeight: S.Theme.barHeight
exclusiveZone: implicitHeight exclusiveZone: implicitHeight
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: M.Theme.base00 color: S.Theme.base00
opacity: M.Theme.barOpacity opacity: S.Theme.barOpacity
} }
Canvas { Canvas {
@ -34,7 +35,7 @@ PanelWindow {
const ctx = getContext("2d"); const ctx = getContext("2d");
const w = width; const w = width;
const h = height; const h = height;
const r = M.Theme.screenRadius; const r = S.Theme.screenRadius;
const lw = 3; const lw = 3;
const hw = lw / 2; const hw = lw / 2;
@ -42,8 +43,8 @@ PanelWindow {
// Glow wash behind the border // Glow wash behind the border
const glowGrad = ctx.createLinearGradient(0, 0, w, 0); const glowGrad = ctx.createLinearGradient(0, 0, w, 0);
glowGrad.addColorStop(0, M.Theme.base0C.toString()); glowGrad.addColorStop(0, S.Theme.base0C.toString());
glowGrad.addColorStop(1, M.Theme.base09.toString()); glowGrad.addColorStop(1, S.Theme.base09.toString());
ctx.globalAlpha = 0.25; ctx.globalAlpha = 0.25;
ctx.fillStyle = glowGrad; ctx.fillStyle = glowGrad;
ctx.fillRect(0, 0, w, h); ctx.fillRect(0, 0, w, h);
@ -60,8 +61,8 @@ PanelWindow {
// Horizontal gradient for the border // Horizontal gradient for the border
const grad = ctx.createLinearGradient(0, 0, w, 0); const grad = ctx.createLinearGradient(0, 0, w, 0);
grad.addColorStop(0, M.Theme.base0C.toString()); grad.addColorStop(0, S.Theme.base0C.toString());
grad.addColorStop(1, M.Theme.base09.toString()); grad.addColorStop(1, S.Theme.base09.toString());
ctx.strokeStyle = grad; ctx.strokeStyle = grad;
ctx.lineWidth = lw; ctx.lineWidth = lw;
@ -96,25 +97,25 @@ PanelWindow {
Item { Item {
anchors.fill: parent anchors.fill: parent
anchors.topMargin: M.Theme.groupSpacing anchors.topMargin: S.Theme.groupSpacing
anchors.leftMargin: M.Theme.groupSpacing anchors.leftMargin: S.Theme.groupSpacing
anchors.rightMargin: M.Theme.groupSpacing anchors.rightMargin: S.Theme.groupSpacing
// ---- center (declared first so left/right can anchor to it) ---- // ---- center (declared first so left/right can anchor to it) ----
RowLayout { RowLayout {
id: centerSection id: centerSection
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: M.Theme.groupSpacing spacing: S.Theme.groupSpacing
M.BarGroup { M.BarGroup {
M.Privacy {} M.Privacy {}
M.Clock { M.Clock {
visible: M.Modules.clock.enable visible: S.Modules.clock.enable
} }
M.Notifications { M.Notifications {
bar: bar bar: bar
visible: M.Modules.notifications.enable visible: S.Modules.notifications.enable
} }
} }
} }
@ -124,14 +125,14 @@ PanelWindow {
anchors.left: parent.left anchors.left: parent.left
anchors.right: centerSection.left anchors.right: centerSection.left
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: M.Theme.groupSpacing spacing: S.Theme.groupSpacing
M.BarGroup { M.BarGroup {
id: workspacesGroup id: workspacesGroup
leftEdge: true leftEdge: true
M.Workspaces { M.Workspaces {
bar: bar bar: bar
visible: M.Modules.workspaces.enable visible: S.Modules.workspaces.enable
} }
} }
M.BarGroup { M.BarGroup {
@ -144,10 +145,10 @@ PanelWindow {
id: _windowTitleGroup id: _windowTitleGroup
Layout.minimumWidth: 0 Layout.minimumWidth: 0
clip: true clip: true
visible: M.Modules.windowTitle.enable && M.NiriIpc.focusedTitle !== "" visible: S.Modules.windowTitle.enable && M.NiriIpc.focusedTitle !== ""
M.WindowTitle { M.WindowTitle {
id: _windowTitle id: _windowTitle
readonly property real _maxWidth: Math.max(0, centerSection.x - _windowTitleGroup.x - 2 * M.Theme.groupPadding - M.Theme.groupSpacing) readonly property real _maxWidth: Math.max(0, centerSection.x - _windowTitleGroup.x - 2 * S.Theme.groupPadding - S.Theme.groupSpacing)
width: Math.min(naturalWidth, _maxWidth) width: Math.min(naturalWidth, _maxWidth)
} }
} }
@ -161,7 +162,7 @@ PanelWindow {
anchors.left: centerSection.right anchors.left: centerSection.right
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: M.Theme.groupSpacing spacing: S.Theme.groupSpacing
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
@ -173,7 +174,7 @@ PanelWindow {
bar: bar bar: bar
} }
M.Volume { M.Volume {
visible: M.Modules.volume.enable visible: S.Modules.volume.enable
} }
} }
@ -181,7 +182,7 @@ PanelWindow {
M.BarGroup { M.BarGroup {
M.Network { M.Network {
bar: bar bar: bar
visible: M.Modules.network.enable visible: S.Modules.network.enable
} }
M.Bluetooth { M.Bluetooth {
bar: bar bar: bar
@ -192,30 +193,30 @@ PanelWindow {
M.BarGroup { M.BarGroup {
M.Backlight {} M.Backlight {}
M.PowerProfile { M.PowerProfile {
visible: M.Modules.powerProfile.enable visible: S.Modules.powerProfile.enable
} }
M.IdleInhibitor { M.IdleInhibitor {
visible: M.Modules.idleInhibitor.enable visible: S.Modules.idleInhibitor.enable
} }
} }
// Stats // Stats
M.BarGroup { M.BarGroup {
M.Cpu { M.Cpu {
visible: M.Modules.cpu.enable visible: S.Modules.cpu.enable
} }
M.Memory { M.Memory {
visible: M.Modules.memory.enable visible: S.Modules.memory.enable
} }
M.Gpu {} M.Gpu {}
M.Temperature { M.Temperature {
visible: M.Modules.temperature.enable visible: S.Modules.temperature.enable
} }
M.Weather { M.Weather {
visible: M.Modules.weather.enable visible: S.Modules.weather.enable
} }
M.Disk { M.Disk {
visible: M.Modules.disk.enable visible: S.Modules.disk.enable
} }
} }
@ -225,7 +226,7 @@ PanelWindow {
M.Battery {} M.Battery {}
M.Power { M.Power {
bar: bar bar: bar
visible: M.Modules.power.enable visible: S.Modules.power.enable
} }
} }
} }

View file

@ -2,6 +2,7 @@ import QtQuick
import QtQuick.Effects import QtQuick.Effects
import Quickshell import Quickshell
import "." as M import "." as M
import "../services" as S
Item { Item {
id: root id: root
@ -16,21 +17,21 @@ Item {
const gx = mapToGlobal(width / 2, 0).x - scr.x; const gx = mapToGlobal(width / 2, 0).x - scr.x;
return Math.max(0, Math.min(1, gx / scr.width)); return Math.max(0, Math.min(1, gx / scr.width));
} }
property color borderColor: Qt.rgba(M.Theme.base0C.r + (M.Theme.base09.r - M.Theme.base0C.r) * _posFrac, M.Theme.base0C.g + (M.Theme.base09.g - M.Theme.base0C.g) * _posFrac, M.Theme.base0C.b + (M.Theme.base09.b - M.Theme.base0C.b) * _posFrac, 1) property color borderColor: Qt.rgba(S.Theme.base0C.r + (S.Theme.base09.r - S.Theme.base0C.r) * _posFrac, S.Theme.base0C.g + (S.Theme.base09.g - S.Theme.base0C.g) * _posFrac, S.Theme.base0C.b + (S.Theme.base09.b - S.Theme.base0C.b) * _posFrac, 1)
property bool leftEdge: false property bool leftEdge: false
property bool rightEdge: false property bool rightEdge: false
readonly property real _tlr: leftEdge ? M.Theme.screenRadius : M.Theme.radius readonly property real _tlr: leftEdge ? S.Theme.screenRadius : S.Theme.radius
readonly property real _trr: rightEdge ? M.Theme.screenRadius : M.Theme.radius readonly property real _trr: rightEdge ? S.Theme.screenRadius : S.Theme.radius
readonly property real _blr: M.Theme.radius readonly property real _blr: S.Theme.radius
readonly property real _brr: M.Theme.radius readonly property real _brr: S.Theme.radius
visible: row.visibleChildren.length > 0 visible: row.visibleChildren.length > 0
implicitWidth: row.implicitWidth + _pad * 2 implicitWidth: row.implicitWidth + _pad * 2
implicitHeight: M.Theme.barHeight - 3 - _pad implicitHeight: S.Theme.barHeight - 3 - _pad
readonly property int _pad: M.Theme.groupPadding readonly property int _pad: S.Theme.groupPadding
property bool _hovered: false property bool _hovered: false
HoverHandler { HoverHandler {
@ -44,7 +45,7 @@ Item {
topRightRadius: root._trr topRightRadius: root._trr
bottomLeftRadius: root._blr bottomLeftRadius: root._blr
bottomRightRadius: root._brr bottomRightRadius: root._brr
color: Qt.rgba(M.Theme.base01.r, M.Theme.base01.g, M.Theme.base01.b, 0.55) color: Qt.rgba(S.Theme.base01.r, S.Theme.base01.g, S.Theme.base01.b, 0.55)
} }
// Frost sheen — subtle white highlight, top-heavy // Frost sheen — subtle white highlight, top-heavy
@ -143,7 +144,7 @@ Item {
id: row id: row
property color accentColor: root.borderColor property color accentColor: root.borderColor
anchors.centerIn: parent anchors.centerIn: parent
spacing: M.Theme.moduleSpacing + 2 spacing: S.Theme.moduleSpacing + 2
} }
// Separator lines overlaid between visible row children // Separator lines overlaid between visible row children

View file

@ -1,13 +1,14 @@
import QtQuick import QtQuick
import Quickshell import Quickshell
import "." as M import "." as M
import "../services" as S
Text { Text {
id: root id: root
property string icon: "" property string icon: ""
property string tooltip: "" property string tooltip: ""
property string minIcon: "" property string minIcon: ""
property color accentColor: parent?.accentColor ?? M.Theme.base05 property color accentColor: parent?.accentColor ?? S.Theme.base05
property bool _hovered: false property bool _hovered: false
property string _displayIcon: icon property string _displayIcon: icon
property string _pendingIcon: "" property string _pendingIcon: ""
@ -43,8 +44,8 @@ Text {
width: minIcon ? Math.max(implicitWidth, _minIconMetrics.width) : implicitWidth width: minIcon ? Math.max(implicitWidth, _minIconMetrics.width) : implicitWidth
horizontalAlignment: minIcon ? Text.AlignHCenter : Text.AlignLeft horizontalAlignment: minIcon ? Text.AlignHCenter : Text.AlignLeft
color: root.accentColor color: root.accentColor
font.pixelSize: M.Theme.fontSize + 1 font.pixelSize: S.Theme.fontSize + 1
font.family: M.Theme.iconFontFamily font.family: S.Theme.iconFontFamily
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
TextMetrics { TextMetrics {

View file

@ -1,21 +1,22 @@
import QtQuick import QtQuick
import Quickshell import Quickshell
import "." as M import "." as M
import "../services" as S
Text { Text {
id: root id: root
property string label: "" property string label: ""
property string tooltip: "" property string tooltip: ""
property string minText: "" property string minText: ""
property color accentColor: parent?.accentColor ?? M.Theme.base05 property color accentColor: parent?.accentColor ?? S.Theme.base05
property bool _hovered: false property bool _hovered: false
text: label text: label
width: minText ? Math.max(implicitWidth, _minMetrics.width) : implicitWidth width: minText ? Math.max(implicitWidth, _minMetrics.width) : implicitWidth
horizontalAlignment: minText ? Text.AlignHCenter : Text.AlignLeft horizontalAlignment: minText ? Text.AlignHCenter : Text.AlignLeft
color: root.accentColor color: root.accentColor
font.pixelSize: M.Theme.fontSize font.pixelSize: S.Theme.fontSize
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
TextMetrics { TextMetrics {

View file

@ -1,12 +1,13 @@
import QtQuick import QtQuick
import Quickshell import Quickshell
import "." as M import "." as M
import "../services" as S
Row { Row {
id: root id: root
property string tooltip: "" property string tooltip: ""
property bool _hovered: false property bool _hovered: false
property color accentColor: parent?.accentColor ?? M.Theme.base05 property color accentColor: parent?.accentColor ?? S.Theme.base05
Behavior on opacity { Behavior on opacity {
NumberAnimation { NumberAnimation {

View file

@ -3,21 +3,22 @@ import Quickshell
import Quickshell.Io import Quickshell.Io
import Quickshell.Services.UPower import Quickshell.Services.UPower
import "." as M import "." as M
import "../services" as S
M.BarSection { M.BarSection {
id: root id: root
spacing: M.Theme.moduleSpacing spacing: S.Theme.moduleSpacing
opacity: M.Modules.battery.enable && (UPower.displayDevice?.isLaptopBattery ?? false) ? 1 : 0 opacity: S.Modules.battery.enable && (UPower.displayDevice?.isLaptopBattery ?? false) ? 1 : 0
visible: opacity > 0 visible: opacity > 0
tooltip: "" tooltip: ""
readonly property var dev: UPower.displayDevice readonly property var dev: UPower.displayDevice
readonly property real pct: (dev?.percentage ?? 0) * 100 readonly property real pct: (dev?.percentage ?? 0) * 100
readonly property bool charging: dev?.state === UPowerDeviceState.Charging readonly property bool charging: dev?.state === UPowerDeviceState.Charging
readonly property int _critThresh: M.Modules.battery.critical || 15 readonly property int _critThresh: S.Modules.battery.critical || 15
readonly property int _warnThresh: M.Modules.battery.warning || 25 readonly property int _warnThresh: S.Modules.battery.warning || 25
readonly property bool _critical: pct < _critThresh && !charging readonly property bool _critical: pct < _critThresh && !charging
property color _stateColor: charging ? M.Theme.base0B : _critical ? M.Theme.base09 : pct < _warnThresh ? M.Theme.base0A : root.accentColor property color _stateColor: charging ? S.Theme.base0B : _critical ? S.Theme.base09 : pct < _warnThresh ? S.Theme.base0A : root.accentColor
property real _blinkOpacity: 1 property real _blinkOpacity: 1
SequentialAnimation { SequentialAnimation {
@ -118,7 +119,7 @@ M.BarSection {
} }
color: root._stateColor color: root._stateColor
opacity: root._blinkOpacity opacity: root._blinkOpacity
font.pixelSize: M.Theme.fontSize + 2 font.pixelSize: S.Theme.fontSize + 2
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
TapHandler { TapHandler {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
@ -163,8 +164,8 @@ M.BarSection {
return Math.round(root.pct) + "%" + (ts ? " " + ts : ""); return Math.round(root.pct) + "%" + (ts ? " " + ts : "");
} }
color: root._stateColor color: root._stateColor
font.pixelSize: M.Theme.fontSize font.pixelSize: S.Theme.fontSize
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
font.bold: true font.bold: true
} }
} }
@ -184,7 +185,7 @@ M.BarSection {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: M.Theme.base02 color: S.Theme.base02
radius: 3 radius: 3
} }
@ -208,7 +209,7 @@ M.BarSection {
width: 1 width: 1
height: parent.height + 4 height: parent.height + 4
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: M.Theme.base0A color: S.Theme.base0A
opacity: 0.6 opacity: 0.6
} }
@ -218,7 +219,7 @@ M.BarSection {
width: 1 width: 1
height: parent.height + 4 height: parent.height + 4
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: M.Theme.base08 color: S.Theme.base08
opacity: 0.6 opacity: 0.6
} }
} }
@ -268,7 +269,7 @@ M.BarSection {
// Warning threshold line // Warning threshold line
const warnY = height - height * (root._warnThresh / 100); const warnY = height - height * (root._warnThresh / 100);
ctx.strokeStyle = M.Theme.base0A.toString(); ctx.strokeStyle = S.Theme.base0A.toString();
ctx.globalAlpha = 0.3; ctx.globalAlpha = 0.3;
ctx.lineWidth = 1; ctx.lineWidth = 1;
ctx.setLineDash([3, 3]); ctx.setLineDash([3, 3]);
@ -279,7 +280,7 @@ M.BarSection {
// Critical threshold line // Critical threshold line
const critY = height - height * (root._critThresh / 100); const critY = height - height * (root._critThresh / 100);
ctx.strokeStyle = M.Theme.base08.toString(); ctx.strokeStyle = S.Theme.base08.toString();
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(0, critY); ctx.moveTo(0, critY);
ctx.lineTo(width, critY); ctx.lineTo(width, critY);
@ -327,9 +328,9 @@ M.BarSection {
anchors.leftMargin: 12 anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: "warn " + root._warnThresh + "% crit " + root._critThresh + "%" text: "warn " + root._warnThresh + "% crit " + root._critThresh + "%"
color: M.Theme.base03 color: S.Theme.base03
font.pixelSize: M.Theme.fontSize - 3 font.pixelSize: S.Theme.fontSize - 3
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
font.letterSpacing: 0.5 font.letterSpacing: 0.5
} }
@ -338,9 +339,9 @@ M.BarSection {
anchors.rightMargin: 12 anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: "24h" text: "24h"
color: M.Theme.base03 color: S.Theme.base03
font.pixelSize: M.Theme.fontSize - 3 font.pixelSize: S.Theme.fontSize - 3
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
} }
} }
@ -349,7 +350,7 @@ M.BarSection {
width: parent.width - 16 width: parent.width - 16
height: 1 height: 1
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
color: M.Theme.base03 color: S.Theme.base03
} }
// Rate + health rows // Rate + health rows
@ -363,9 +364,9 @@ M.BarSection {
anchors.leftMargin: 12 anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: root.charging ? "Charging" : "Discharging" text: root.charging ? "Charging" : "Discharging"
color: M.Theme.base04 color: S.Theme.base04
font.pixelSize: M.Theme.fontSize - 2 font.pixelSize: S.Theme.fontSize - 2
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
} }
Text { Text {
@ -377,8 +378,8 @@ M.BarSection {
return r > 0 ? r.toFixed(1) + " W" : ""; return r > 0 ? r.toFixed(1) + " W" : "";
} }
color: root._stateColor color: root._stateColor
font.pixelSize: M.Theme.fontSize - 2 font.pixelSize: S.Theme.fontSize - 2
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
} }
} }
@ -392,9 +393,9 @@ M.BarSection {
anchors.leftMargin: 12 anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: "Health" text: "Health"
color: M.Theme.base04 color: S.Theme.base04
font.pixelSize: M.Theme.fontSize - 2 font.pixelSize: S.Theme.fontSize - 2
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
} }
Text { Text {
@ -404,10 +405,10 @@ M.BarSection {
text: Math.round((root.dev?.healthPercentage ?? 0) * 100) + "%" text: Math.round((root.dev?.healthPercentage ?? 0) * 100) + "%"
color: { color: {
const h = (root.dev?.healthPercentage ?? 1) * 100; const h = (root.dev?.healthPercentage ?? 1) * 100;
return h < 50 ? M.Theme.base08 : h < 75 ? M.Theme.base0A : M.Theme.base0B; return h < 50 ? S.Theme.base08 : h < 75 ? S.Theme.base0A : S.Theme.base0B;
} }
font.pixelSize: M.Theme.fontSize - 2 font.pixelSize: S.Theme.fontSize - 2
font.family: M.Theme.fontFamily font.family: S.Theme.fontFamily
} }
} }

View file

@ -2,11 +2,12 @@ import QtQuick
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
import "." as M import "." as M
import "../services" as S
M.BarSection { M.BarSection {
id: root id: root
spacing: M.Theme.moduleSpacing spacing: S.Theme.moduleSpacing
opacity: M.Modules.bluetooth.enable && root.state !== "unavailable" ? 1 : 0 opacity: S.Modules.bluetooth.enable && root.state !== "unavailable" ? 1 : 0
visible: opacity > 0 visible: opacity > 0
tooltip: { tooltip: {
if (root.state === "off") if (root.state === "off")
@ -35,7 +36,7 @@ M.BarSection {
Process { Process {
id: proc id: proc
running: M.Modules.bluetooth.enable running: S.Modules.bluetooth.enable
command: ["sh", "-c", "s=$(bluetoothctl show 2>/dev/null); " + "[ -z \"$s\" ] && echo unavailable && exit; " + "echo \"$s\" | grep -q 'Powered: yes' || { echo off:; exit; }; " + "info=$(bluetoothctl info 2>/dev/null); " + "d=$(echo \"$info\" | awk -F': ' '/\\tName:/{n=$2}/Connected: yes/{c=1}END{if(c)print n}'); " + "[ -n \"$d\" ] && echo \"connected:$d\" || { echo on:; exit; }; " + "bat=$(echo \"$info\" | awk -F': ' '/Battery Percentage.*\\(/{gsub(/[^0-9]/,\"\",$2);print $2}'); " + "[ -n \"$bat\" ] && echo \"bat:$bat\""] command: ["sh", "-c", "s=$(bluetoothctl show 2>/dev/null); " + "[ -z \"$s\" ] && echo unavailable && exit; " + "echo \"$s\" | grep -q 'Powered: yes' || { echo off:; exit; }; " + "info=$(bluetoothctl info 2>/dev/null); " + "d=$(echo \"$info\" | awk -F': ' '/\\tName:/{n=$2}/Connected: yes/{c=1}END{if(c)print n}'); " + "[ -n \"$d\" ] && echo \"connected:$d\" || { echo on:; exit; }; " + "bat=$(echo \"$info\" | awk -F': ' '/Battery Percentage.*\\(/{gsub(/[^0-9]/,\"\",$2);print $2}'); " + "[ -n \"$bat\" ] && echo \"bat:$bat\""]
stdout: StdioCollector { stdout: StdioCollector {
onStreamFinished: root._parse(text) onStreamFinished: root._parse(text)
@ -44,7 +45,7 @@ M.BarSection {
// Event-driven: watch BlueZ DBus property changes // Event-driven: watch BlueZ DBus property changes
Process { Process {
id: btMonitor id: btMonitor
running: M.Modules.bluetooth.enable running: S.Modules.bluetooth.enable
command: ["sh", "-c", "dbus-monitor --system \"interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path_namespace='/org/bluez'\" 2>/dev/null"] command: ["sh", "-c", "dbus-monitor --system \"interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path_namespace='/org/bluez'\" 2>/dev/null"]
stdout: SplitParser { stdout: SplitParser {
splitMarker: "\n" splitMarker: "\n"
@ -58,14 +59,14 @@ M.BarSection {
} }
Timer { Timer {
interval: 60000 interval: 60000
running: M.Modules.bluetooth.enable running: S.Modules.bluetooth.enable
repeat: true repeat: true
onTriggered: proc.running = true onTriggered: proc.running = true
} }
M.BarIcon { M.BarIcon {
icon: "\uF294" icon: "\uF294"
color: root.state === "off" ? M.Theme.base04 : root.accentColor color: root.state === "off" ? S.Theme.base04 : root.accentColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
TapHandler { TapHandler {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor

Some files were not shown because too many files have changed in this diff Show more