move Theme, SystemStats, Modules to shell/services/

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

View file

@ -25,7 +25,7 @@ stdenvNoCC.mkDerivation {
runHook preInstall
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
qsb --qt6 \

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,6 +2,7 @@ import QtQuick
import QtQuick.Effects
import Quickshell
import "." as M
import "../services" as S
Item {
id: root
@ -16,21 +17,21 @@ Item {
const gx = mapToGlobal(width / 2, 0).x - scr.x;
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 rightEdge: false
readonly property real _tlr: leftEdge ? M.Theme.screenRadius : M.Theme.radius
readonly property real _trr: rightEdge ? M.Theme.screenRadius : M.Theme.radius
readonly property real _blr: M.Theme.radius
readonly property real _brr: M.Theme.radius
readonly property real _tlr: leftEdge ? S.Theme.screenRadius : S.Theme.radius
readonly property real _trr: rightEdge ? S.Theme.screenRadius : S.Theme.radius
readonly property real _blr: S.Theme.radius
readonly property real _brr: S.Theme.radius
visible: row.visibleChildren.length > 0
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
HoverHandler {
@ -44,7 +45,7 @@ Item {
topRightRadius: root._trr
bottomLeftRadius: root._blr
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
@ -143,7 +144,7 @@ Item {
id: row
property color accentColor: root.borderColor
anchors.centerIn: parent
spacing: M.Theme.moduleSpacing + 2
spacing: S.Theme.moduleSpacing + 2
}
// Separator lines overlaid between visible row children

View file

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

View file

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

View file

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

View file

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

View file

@ -2,11 +2,12 @@ import QtQuick
import Quickshell
import Quickshell.Io
import "." as M
import "../services" as S
M.BarSection {
id: root
spacing: M.Theme.moduleSpacing
opacity: M.Modules.bluetooth.enable && root.state !== "unavailable" ? 1 : 0
spacing: S.Theme.moduleSpacing
opacity: S.Modules.bluetooth.enable && root.state !== "unavailable" ? 1 : 0
visible: opacity > 0
tooltip: {
if (root.state === "off")
@ -35,7 +36,7 @@ M.BarSection {
Process {
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\""]
stdout: StdioCollector {
onStreamFinished: root._parse(text)
@ -44,7 +45,7 @@ M.BarSection {
// Event-driven: watch BlueZ DBus property changes
Process {
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"]
stdout: SplitParser {
splitMarker: "\n"
@ -58,14 +59,14 @@ M.BarSection {
}
Timer {
interval: 60000
running: M.Modules.bluetooth.enable
running: S.Modules.bluetooth.enable
repeat: true
onTriggered: proc.running = true
}
M.BarIcon {
icon: "\uF294"
color: root.state === "off" ? M.Theme.base04 : root.accentColor
color: root.state === "off" ? S.Theme.base04 : root.accentColor
anchors.verticalCenter: parent.verticalCenter
TapHandler {
cursorShape: Qt.PointingHandCursor

View file

@ -2,6 +2,7 @@ import QtQuick
import Quickshell
import Quickshell.Io
import "." as M
import "../services" as S
M.HoverPanel {
id: menuWindow
@ -18,9 +19,9 @@ M.HoverPanel {
Text {
anchors.centerIn: parent
text: "\uF011"
color: menuWindow._btEnabled ? menuWindow.accentColor : M.Theme.base04
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.iconFontFamily
color: menuWindow._btEnabled ? menuWindow.accentColor : S.Theme.base04
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.iconFontFamily
Behavior on color {
ColorAnimation {
@ -119,8 +120,8 @@ M.HoverPanel {
anchors.fill: parent
anchors.leftMargin: 4
anchors.rightMargin: 4
color: entryHover.hovered ? M.Theme.base02 : "transparent"
radius: M.Theme.radius
color: entryHover.hovered ? S.Theme.base02 : "transparent"
radius: S.Theme.radius
}
Text {
@ -129,9 +130,9 @@ M.HoverPanel {
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "\uF294"
color: entry.modelData.connected ? menuWindow.accentColor : M.Theme.base04
font.pixelSize: M.Theme.fontSize + 1
font.family: M.Theme.iconFontFamily
color: entry.modelData.connected ? menuWindow.accentColor : S.Theme.base04
font.pixelSize: S.Theme.fontSize + 1
font.family: S.Theme.iconFontFamily
}
Text {
@ -141,9 +142,9 @@ M.HoverPanel {
anchors.rightMargin: 4
anchors.verticalCenter: parent.verticalCenter
text: entry.modelData.name
color: entry.modelData.connected ? menuWindow.accentColor : M.Theme.base05
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: entry.modelData.connected ? menuWindow.accentColor : S.Theme.base05
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
font.bold: entry.modelData.connected
elide: Text.ElideRight
}
@ -154,9 +155,9 @@ M.HoverPanel {
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: entry.modelData.battery >= 0 ? entry.modelData.battery + "%" : ""
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize - 1
font.family: M.Theme.fontFamily
color: S.Theme.base04
font.pixelSize: S.Theme.fontSize - 1
font.family: S.Theme.fontFamily
width: entry.modelData.battery >= 0 ? implicitWidth : 0
}
@ -181,8 +182,8 @@ M.HoverPanel {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: menuWindow._btEnabled ? "No paired devices" : "Bluetooth is off"
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: S.Theme.base04
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
}
}

View file

@ -1,6 +1,7 @@
import QtQuick
import Quickshell
import "." as M
import "../services" as S
M.BarLabel {
SystemClock {
@ -8,7 +9,7 @@ M.BarLabel {
precision: SystemClock.Seconds
}
font.pixelSize: M.Theme.fontSize + 1
font.pixelSize: S.Theme.fontSize + 1
label: Qt.formatDateTime(clock.date, "ddd, dd. MMM HH:mm")
tooltip: Qt.formatDateTime(clock.date, "dddd, dd. MMMM yyyy\nHH:mm:ss")
}

View file

@ -1,16 +1,17 @@
import QtQuick
import Quickshell
import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
id: root
spacing: Math.max(1, M.Theme.moduleSpacing - 2)
spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: ""
readonly property var _cores: M.SystemStats.cpuCores
readonly property var _coreMaxFreq: M.SystemStats.cpuCoreMaxFreq
readonly property var _coreTypes: M.SystemStats.cpuCoreTypes
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
@ -21,10 +22,10 @@ M.BarSection {
on_ShowPanelChanged: {
if (_showPanel && !_coreConsumerActive) {
_coreConsumerActive = true;
M.SystemStats.coreConsumers++;
S.SystemStats.coreConsumers++;
} else if (!_showPanel && _coreConsumerActive) {
_coreConsumerActive = false;
M.SystemStats.coreConsumers--;
S.SystemStats.coreConsumers--;
}
}
@ -56,7 +57,7 @@ M.BarSection {
}
}
M.BarLabel {
label: M.SystemStats.cpuUsage.toString().padStart(2) + "%@" + M.SystemStats.cpuFreqGhz.toFixed(2)
label: S.SystemStats.cpuUsage.toString().padStart(2) + "%@" + S.SystemStats.cpuFreqGhz.toFixed(2)
minText: "99%@9.99"
anchors.verticalCenter: parent.verticalCenter
TapHandler {

View file

@ -1,15 +1,16 @@
import QtQuick
import Quickshell
import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
id: root
spacing: Math.max(1, M.Theme.moduleSpacing - 2)
spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: ""
property var _mounts: M.SystemStats.diskMounts
property int _rootPct: M.SystemStats.diskRootPct
property var _mounts: S.SystemStats.diskMounts
property int _rootPct: S.SystemStats.diskRootPct
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered

View file

@ -2,6 +2,7 @@ import QtQuick
import Quickshell
import Quickshell.Wayland
import "." as M
import "../services" as S
PanelWindow {
id: root
@ -35,8 +36,8 @@ PanelWindow {
margins.top: 0
margins.left: Math.max(0, Math.min(Math.round(M.FlyoutState.itemX - implicitWidth / 2), screen.width - implicitWidth))
implicitWidth: label.implicitWidth + M.Theme.barPadding * 2
implicitHeight: label.implicitHeight + M.Theme.barPadding * 2
implicitWidth: label.implicitWidth + S.Theme.barPadding * 2
implicitHeight: label.implicitHeight + S.Theme.barPadding * 2
ParallelAnimation {
id: showAnim
@ -93,9 +94,9 @@ PanelWindow {
anchors.centerIn: parent
text: M.FlyoutState.text.replace(/\n/g, "<br>")
textFormat: Text.RichText
color: M.Theme.base05
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: S.Theme.base05
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
}
}
}

View file

@ -1,11 +1,12 @@
pragma Singleton
import QtQuick
import "." as M
import "../services" as S
QtObject {
property bool visible: false
property string text: ""
property real itemX: 0
property var screen: null
property color accentColor: M.Theme.base05
property color accentColor: S.Theme.base05
}

View file

@ -1,12 +1,13 @@
import QtQuick
import Quickshell
import "." as M
import "../services" as S
M.BarSection {
id: root
spacing: Math.max(1, M.Theme.moduleSpacing - 2)
spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: ""
visible: M.Modules.gpu.enable && M.SystemStats.gpuAvailable
visible: S.Modules.gpu.enable && S.SystemStats.gpuAvailable
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
@ -27,8 +28,8 @@ M.BarSection {
function _loadColor(pct) {
const t = Math.max(0, Math.min(100, pct)) / 100;
const a = t < 0.5 ? M.Theme.base0B : M.Theme.base0A;
const b = t < 0.5 ? M.Theme.base0A : M.Theme.base08;
const a = t < 0.5 ? S.Theme.base0B : S.Theme.base0A;
const b = t < 0.5 ? S.Theme.base0A : S.Theme.base08;
const u = t < 0.5 ? t * 2 : (t - 0.5) * 2;
return Qt.rgba(a.r + (b.r - a.r) * u, a.g + (b.g - a.g) * u, a.b + (b.b - a.b) * u, 1);
}
@ -39,7 +40,7 @@ M.BarSection {
M.BarIcon {
icon: "\uDB84\uDCB0"
color: root._loadColor(M.SystemStats.gpuUsage)
color: root._loadColor(S.SystemStats.gpuUsage)
anchors.verticalCenter: parent.verticalCenter
TapHandler {
cursorShape: Qt.PointingHandCursor
@ -47,9 +48,9 @@ M.BarSection {
}
}
M.BarLabel {
label: M.SystemStats.gpuUsage + "%"
label: S.SystemStats.gpuUsage + "%"
minText: "100%"
color: root._loadColor(M.SystemStats.gpuUsage)
color: root._loadColor(S.SystemStats.gpuUsage)
anchors.verticalCenter: parent.verticalCenter
TapHandler {
cursorShape: Qt.PointingHandCursor
@ -76,10 +77,10 @@ M.BarSection {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: M.SystemStats.gpuVendor.toUpperCase()
color: M.Theme.base03
font.pixelSize: M.Theme.fontSize - 3
font.family: M.Theme.fontFamily
text: S.SystemStats.gpuVendor.toUpperCase()
color: S.Theme.base03
font.pixelSize: S.Theme.fontSize - 3
font.family: S.Theme.fontFamily
font.letterSpacing: 1
}
@ -87,10 +88,10 @@ M.BarSection {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: M.SystemStats.gpuUsage + "%"
color: root._loadColor(M.SystemStats.gpuUsage)
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
text: S.SystemStats.gpuUsage + "%"
color: root._loadColor(S.SystemStats.gpuUsage)
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
font.bold: true
}
}
@ -110,14 +111,14 @@ M.BarSection {
Rectangle {
anchors.fill: parent
color: M.Theme.base02
color: S.Theme.base02
radius: 3
}
Rectangle {
width: parent.width * Math.min(1, M.SystemStats.gpuUsage / 100)
width: parent.width * Math.min(1, S.SystemStats.gpuUsage / 100)
height: parent.height
color: root._loadColor(M.SystemStats.gpuUsage)
color: root._loadColor(S.SystemStats.gpuUsage)
radius: 3
Behavior on width {
enabled: root._showPanel
@ -139,7 +140,7 @@ M.BarSection {
anchors.rightMargin: 12
height: 36
property var _hist: M.SystemStats.gpuHistory
property var _hist: S.SystemStats.gpuHistory
on_HistChanged: if (root._showPanel)
requestPaint()
@ -177,7 +178,7 @@ M.BarSection {
width: parent.width - 16
height: 1
anchors.horizontalCenter: parent.horizontalCenter
color: M.Theme.base03
color: S.Theme.base03
}
Item {
@ -189,9 +190,9 @@ M.BarSection {
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "VRAM"
color: M.Theme.base03
font.pixelSize: M.Theme.fontSize - 3
font.family: M.Theme.fontFamily
color: S.Theme.base03
font.pixelSize: S.Theme.fontSize - 3
font.family: S.Theme.fontFamily
font.letterSpacing: 1
}
@ -199,10 +200,10 @@ M.BarSection {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: root._fmt(M.SystemStats.gpuVramUsedGb) + " / " + root._fmt(M.SystemStats.gpuVramTotalGb)
text: root._fmt(S.SystemStats.gpuVramUsedGb) + " / " + root._fmt(S.SystemStats.gpuVramTotalGb)
color: root.accentColor
font.pixelSize: M.Theme.fontSize - 1
font.family: M.Theme.fontFamily
font.pixelSize: S.Theme.fontSize - 1
font.family: S.Theme.fontFamily
font.bold: true
}
}
@ -221,12 +222,12 @@ M.BarSection {
Rectangle {
anchors.fill: parent
color: M.Theme.base02
color: S.Theme.base02
radius: 2
}
Rectangle {
width: M.SystemStats.gpuVramTotalGb > 0 ? parent.width * Math.min(1, M.SystemStats.gpuVramUsedGb / M.SystemStats.gpuVramTotalGb) : 0
width: S.SystemStats.gpuVramTotalGb > 0 ? parent.width * Math.min(1, S.SystemStats.gpuVramUsedGb / S.SystemStats.gpuVramTotalGb) : 0
height: parent.height
color: root.accentColor
radius: 2
@ -245,26 +246,26 @@ M.BarSection {
Item {
width: parent.width
height: 22
visible: M.SystemStats.gpuTempC > 0
visible: S.SystemStats.gpuTempC > 0
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "Temp"
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
color: S.Theme.base04
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: M.SystemStats.gpuTempC + "\u00B0C"
color: M.SystemStats.gpuTempC > 85 ? M.Theme.base08 : M.SystemStats.gpuTempC > 70 ? M.Theme.base0A : M.Theme.base05
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
text: S.SystemStats.gpuTempC + "\u00B0C"
color: S.SystemStats.gpuTempC > 85 ? S.Theme.base08 : S.SystemStats.gpuTempC > 70 ? S.Theme.base0A : S.Theme.base05
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
}
}

View file

@ -2,6 +2,7 @@ import QtQuick
import Quickshell
import Quickshell.Wayland
import "." as M
import "../services" as S
// Unified bar panel fullscreen transparent window so content can resize
// freely without triggering Wayland surface resizes.
@ -236,7 +237,7 @@ PanelWindow {
y: panelContainer.y
width: panelContainer.width
height: panelContainer.height
opacity: panelContainer.opacity * Math.max(M.Theme.barOpacity, 0.85)
opacity: panelContainer.opacity * Math.max(S.Theme.barOpacity, 0.85)
accentColor: root.accentColor
}
@ -301,9 +302,9 @@ PanelWindow {
anchors.verticalCenter: parent.verticalCenter
text: root.panelTitle
color: root.accentColor
font.pixelSize: M.Theme.fontSize - 1
font.pixelSize: S.Theme.fontSize - 1
font.bold: true
font.family: M.Theme.fontFamily
font.family: S.Theme.fontFamily
}
// Action buttons anchored left of pin button slot
@ -337,9 +338,9 @@ PanelWindow {
Text {
anchors.centerIn: parent
text: root._pinned ? "\uDB81\uDC03" : "\uDB82\uDD31"
color: root._pinned ? root.accentColor : M.Theme.base04
font.pixelSize: M.Theme.fontSize - 1
font.family: M.Theme.iconFontFamily
color: root._pinned ? root.accentColor : S.Theme.base04
font.pixelSize: S.Theme.fontSize - 1
font.family: S.Theme.iconFontFamily
Behavior on color {
ColorAnimation {
@ -355,7 +356,7 @@ PanelWindow {
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 1
color: M.Theme.base03
color: S.Theme.base03
}
}
@ -375,7 +376,7 @@ PanelWindow {
color: "transparent"
border.color: root.accentColor
border.width: 1
radius: M.Theme.radius
radius: S.Theme.radius
opacity: panelContainer.opacity
}
}

View file

@ -2,10 +2,11 @@ import QtQuick
import Quickshell
import Quickshell.Io
import "." as M
import "../services" as S
M.BarIcon {
id: root
color: root.active ? M.Theme.base09 : root.accentColor
color: root.active ? S.Theme.base09 : root.accentColor
tooltip: {
const parts = ["Idle inhibition: " + (root.active ? "active" : "inactive")];
if (root._inhibitors)

View file

@ -1,19 +1,20 @@
import QtQuick
import Quickshell
import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
id: root
spacing: Math.max(1, M.Theme.moduleSpacing - 2)
spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: ""
property int percent: M.SystemStats.memPercent
property real usedGb: M.SystemStats.memUsedGb
property real totalGb: M.SystemStats.memTotalGb
property real availGb: M.SystemStats.memAvailGb
property real cachedGb: M.SystemStats.memCachedGb
property real buffersGb: M.SystemStats.memBuffersGb
property int percent: S.SystemStats.memPercent
property real usedGb: S.SystemStats.memUsedGb
property real totalGb: S.SystemStats.memTotalGb
property real availGb: S.SystemStats.memAvailGb
property real cachedGb: S.SystemStats.memCachedGb
property real buffersGb: S.SystemStats.memBuffersGb
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered

View file

@ -3,12 +3,13 @@ import Quickshell
import Quickshell.Io
import Quickshell.Services.Mpris
import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
id: root
spacing: M.Theme.moduleSpacing
opacity: M.Modules.mpris.enable && player !== null ? 1 : 0
spacing: S.Theme.moduleSpacing
opacity: S.Modules.mpris.enable && player !== null ? 1 : 0
visible: opacity > 0
tooltip: ""

View file

@ -2,10 +2,11 @@ import QtQuick
import Quickshell
import Quickshell.Io
import "." as M
import "../services" as S
M.BarSection {
id: root
spacing: M.Theme.moduleSpacing
spacing: S.Theme.moduleSpacing
tooltip: ""
property string ifname: ""
@ -16,7 +17,7 @@ M.BarSection {
Process {
id: proc
running: M.Modules.network.enable
running: S.Modules.network.enable
command: ["sh", "-c", "line=$(nmcli -t -f NAME,TYPE,DEVICE connection show --active 2>/dev/null | head -1); if [ -z \"$line\" ]; then dev=$(nmcli -t -f DEVICE,STATE device 2>/dev/null | grep ':connected' | grep -v ':unmanaged\\|:unavailable\\|:disconnected\\|:connecting' | head -1 | cut -d: -f1); [ -n \"$dev\" ] && line=\"linked:linked:$dev\"; fi; [ -z \"$line\" ] && exit 0; echo \"$line\"; dev=$(echo \"$line\" | cut -d: -f3); ip=$(nmcli -t -f IP4.ADDRESS device show \"$dev\" 2>/dev/null | head -1 | cut -d: -f2); echo \"ip:${ip:-}\"; sig=$(nmcli -t -f GENERAL.SIGNAL device show \"$dev\" 2>/dev/null | head -1 | cut -d: -f2); echo \"sig:${sig:-}\""]
stdout: StdioCollector {
onStreamFinished: {
@ -53,7 +54,7 @@ M.BarSection {
// Event-driven: re-poll on any network change
Process {
id: monitor
running: M.Modules.network.enable
running: S.Modules.network.enable
command: ["nmcli", "monitor"]
stdout: SplitParser {
splitMarker: "\n"
@ -71,7 +72,7 @@ M.BarSection {
// Fallback poll
Timer {
interval: 60000
running: M.Modules.network.enable
running: S.Modules.network.enable
repeat: true
onTriggered: proc.running = true
}
@ -86,13 +87,13 @@ M.BarSection {
return "\uDB85\uDE16";
return "\uDB82\uDCFD";
}
color: root.state === "disconnected" ? M.Theme.base08 : root.accentColor
color: root.state === "disconnected" ? S.Theme.base08 : root.accentColor
anchors.verticalCenter: parent.verticalCenter
}
M.BarLabel {
visible: root.state === "wifi"
label: root.essid
color: root.state === "disconnected" ? M.Theme.base08 : root.accentColor
color: root.state === "disconnected" ? S.Theme.base08 : root.accentColor
anchors.verticalCenter: parent.verticalCenter
}

View file

@ -2,6 +2,7 @@ import QtQuick
import Quickshell
import Quickshell.Io
import "." as M
import "../services" as S
M.HoverPanel {
id: menuWindow
@ -17,9 +18,9 @@ M.HoverPanel {
Text {
anchors.centerIn: parent
text: "\uF011"
color: menuWindow._wifiEnabled ? menuWindow.accentColor : M.Theme.base04
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.iconFontFamily
color: menuWindow._wifiEnabled ? menuWindow.accentColor : S.Theme.base04
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.iconFontFamily
Behavior on color {
ColorAnimation {
@ -156,8 +157,8 @@ M.HoverPanel {
anchors.fill: parent
anchors.leftMargin: 4
anchors.rightMargin: 4
color: entryHover.hovered ? M.Theme.base02 : "transparent"
radius: M.Theme.radius
color: entryHover.hovered ? S.Theme.base02 : "transparent"
radius: S.Theme.radius
}
Text {
@ -166,9 +167,9 @@ M.HoverPanel {
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: entry.modelData.isWifi ? "\uF1EB" : "\uDB80\uDE00"
color: entry.modelData.active ? menuWindow.accentColor : M.Theme.base05
font.pixelSize: M.Theme.fontSize + 1
font.family: M.Theme.iconFontFamily
color: entry.modelData.active ? menuWindow.accentColor : S.Theme.base05
font.pixelSize: S.Theme.fontSize + 1
font.family: S.Theme.iconFontFamily
}
Text {
@ -178,9 +179,9 @@ M.HoverPanel {
anchors.rightMargin: 4
anchors.verticalCenter: parent.verticalCenter
text: entry.modelData.name
color: entry.modelData.active ? menuWindow.accentColor : M.Theme.base05
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: entry.modelData.active ? menuWindow.accentColor : S.Theme.base05
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
font.bold: entry.modelData.active
elide: Text.ElideRight
}
@ -191,9 +192,9 @@ M.HoverPanel {
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: entry.modelData.signal >= 0 ? entry.modelData.signal + "%" : ""
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize - 1
font.family: M.Theme.fontFamily
color: S.Theme.base04
font.pixelSize: S.Theme.fontSize - 1
font.family: S.Theme.fontFamily
width: entry.modelData.signal >= 0 ? implicitWidth : 0
}
@ -222,8 +223,8 @@ M.HoverPanel {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: menuWindow._wifiEnabled ? "No networks available" : "Wi-Fi is off"
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: S.Theme.base04
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
}
}

View file

@ -2,6 +2,7 @@ import QtQuick
import Quickshell
import Quickshell.Services.Notifications
import "." as M
import "../services" as S
// Shared notification card: background, progress bar, urgency bar, icon, text, dismiss button.
// Does NOT include dismiss animation or dismiss logic emits dismissRequested() instead.
@ -14,7 +15,7 @@ Item {
property bool dismissOnAction: true
property int iconSize: 32
property int bodyMaxLines: 3
property color accentColor: M.Theme.base0D
property color accentColor: S.Theme.base0D
signal dismissRequested
@ -34,9 +35,9 @@ Item {
// Background: base01, base02 on hover
Rectangle {
anchors.fill: parent
color: _hover.hovered ? M.Theme.base02 : M.Theme.base01
opacity: _hover.hovered ? 1.0 : Math.max(M.Theme.barOpacity, 0.9)
radius: M.Theme.radius
color: _hover.hovered ? S.Theme.base02 : S.Theme.base01
opacity: _hover.hovered ? 1.0 : Math.max(S.Theme.barOpacity, 0.9)
radius: S.Theme.radius
Behavior on color {
ColorAnimation {
@ -51,7 +52,7 @@ Item {
anchors.bottom: parent.bottom
anchors.left: parent.left
width: parent.width * Math.min(1, Math.max(0, (root.notif?.hints?.value ?? 0) / 100))
color: M.Theme.base03
color: S.Theme.base03
radius: parent.radius
Behavior on width {
@ -71,7 +72,7 @@ Item {
radius: 1
color: {
const u = root.notif?.urgency ?? NotificationUrgency.Normal;
return u === NotificationUrgency.Critical ? M.Theme.base08 : u === NotificationUrgency.Low ? M.Theme.base04 : M.Theme.base0D;
return u === NotificationUrgency.Critical ? S.Theme.base08 : u === NotificationUrgency.Low ? S.Theme.base04 : S.Theme.base0D;
}
}
@ -107,9 +108,9 @@ Item {
anchors.top: parent.top
anchors.topMargin: 8
text: "\uF00D"
color: _dismissHover.hovered ? M.Theme.base08 : M.Theme.base03
font.pixelSize: M.Theme.fontSize - 1
font.family: M.Theme.iconFontFamily
color: _dismissHover.hovered ? S.Theme.base08 : S.Theme.base03
font.pixelSize: S.Theme.fontSize - 1
font.family: S.Theme.iconFontFamily
opacity: _hover.hovered ? 1 : 0
HoverHandler {
@ -163,9 +164,9 @@ Item {
Text {
text: root.notif?.appName ?? "Notification"
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
color: S.Theme.base04
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
width: parent.width - _timeText.implicitWidth - 4
elide: Text.ElideRight
}
@ -173,9 +174,9 @@ Item {
Text {
id: _timeText
text: root.notif?.timeStr ?? ""
color: M.Theme.base03
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
color: S.Theme.base03
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
}
}
@ -186,9 +187,9 @@ Item {
Text {
text: root.notif?.summary ?? ""
color: M.Theme.base05
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: S.Theme.base05
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
font.bold: true
elide: Text.ElideRight
width: parent.width - _inlineTime.implicitWidth - 4
@ -197,9 +198,9 @@ Item {
Text {
id: _inlineTime
text: root.notif?.timeStr ?? ""
color: M.Theme.base03
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
color: S.Theme.base03
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
anchors.verticalCenter: parent.verticalCenter
}
}
@ -208,9 +209,9 @@ Item {
visible: root.showAppName
width: parent.width
text: root.notif?.summary ?? ""
color: M.Theme.base05
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: S.Theme.base05
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
font.bold: true
elide: Text.ElideRight
wrapMode: Text.WordWrap
@ -220,9 +221,9 @@ Item {
Text {
width: parent.width
text: root.notif?.body ?? ""
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize - 1
font.family: M.Theme.fontFamily
color: S.Theme.base04
font.pixelSize: S.Theme.fontSize - 1
font.family: S.Theme.fontFamily
elide: Text.ElideRight
wrapMode: Text.WordWrap
maximumLineCount: root.bodyMaxLines
@ -243,9 +244,9 @@ Item {
required property var modelData
width: _actText.implicitWidth + 12
height: _actText.implicitHeight + 6
radius: M.Theme.radius
color: _actHover.hovered ? M.Theme.base03 : "transparent"
border.color: M.Theme.base03
radius: S.Theme.radius
color: _actHover.hovered ? S.Theme.base03 : "transparent"
border.color: S.Theme.base03
border.width: 1
Text {
@ -253,8 +254,8 @@ Item {
anchors.centerIn: parent
text: parent.modelData.text
color: root.accentColor
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
}
HoverHandler {

View file

@ -1,6 +1,7 @@
import QtQuick
import Quickshell
import "." as M
import "../services" as S
M.HoverPanel {
id: menuWindow
@ -18,9 +19,9 @@ M.HoverPanel {
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "Notifications"
color: M.Theme.base05
font.pixelSize: M.Theme.fontSize + 1
font.family: M.Theme.fontFamily
color: S.Theme.base05
font.pixelSize: S.Theme.fontSize + 1
font.family: S.Theme.fontFamily
font.bold: true
}
@ -33,9 +34,9 @@ M.HoverPanel {
// DND toggle
Text {
text: M.NotifService.dnd ? "\uDB82\uDE93" : "\uDB80\uDC9C"
color: M.NotifService.dnd ? M.Theme.base09 : M.Theme.base04
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.iconFontFamily
color: M.NotifService.dnd ? S.Theme.base09 : S.Theme.base04
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.iconFontFamily
anchors.verticalCenter: parent.verticalCenter
MouseArea {
@ -48,9 +49,9 @@ M.HoverPanel {
// Clear all
Text {
text: "\uF1F8"
color: clearArea.containsMouse ? M.Theme.base08 : M.Theme.base04
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.iconFontFamily
color: clearArea.containsMouse ? S.Theme.base08 : S.Theme.base04
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.iconFontFamily
anchors.verticalCenter: parent.verticalCenter
visible: M.NotifService.count > 0
@ -219,14 +220,14 @@ M.HoverPanel {
width: menuWindow.contentWidth - 16
height: 1
anchors.horizontalCenter: parent.horizontalCenter
color: M.Theme.base03
color: S.Theme.base03
}
// Notification list (scrollable)
ListView {
id: notifList
width: menuWindow.contentWidth
height: Math.min(contentHeight, 60 * (M.Modules.notifications.maxVisible || 10))
height: Math.min(contentHeight, 60 * (S.Modules.notifications.maxVisible || 10))
clip: true
boundsBehavior: Flickable.StopAtBounds
model: menuWindow._flatModel
@ -253,7 +254,7 @@ M.HoverPanel {
readonly property real _targetHeight: {
if (_type === "header")
return modelData.collapsed ? (28 + modelData.count * (M.Theme.fontSize + 4)) : 28;
return modelData.collapsed ? (28 + modelData.count * (S.Theme.fontSize + 4)) : 28;
return _notifCard.implicitHeight;
}
@ -323,8 +324,8 @@ M.HoverPanel {
anchors.leftMargin: 10
anchors.top: parent.top
anchors.topMargin: (28 - height) / 2
width: M.Theme.fontSize + 2
height: M.Theme.fontSize + 2
width: S.Theme.fontSize + 2
height: S.Theme.fontSize + 2
source: {
if (notifDelegate._type !== "header")
return "";
@ -335,7 +336,7 @@ M.HoverPanel {
}
visible: status === Image.Ready
fillMode: Image.PreserveAspectFit
sourceSize: Qt.size(M.Theme.fontSize + 2, M.Theme.fontSize + 2)
sourceSize: Qt.size(S.Theme.fontSize + 2, S.Theme.fontSize + 2)
asynchronous: true
}
@ -348,9 +349,9 @@ M.HoverPanel {
height: 28
verticalAlignment: Text.AlignVCenter
text: notifDelegate._type === "header" && notifDelegate.modelData.collapsed ? "\u25B8" : "\u25BE"
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
color: S.Theme.base04
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
opacity: _headerHover.hovered ? 1 : 0
}
@ -364,9 +365,9 @@ M.HoverPanel {
height: 28
verticalAlignment: Text.AlignVCenter
text: notifDelegate._type === "header" ? (notifDelegate.modelData.appName || "Unknown") : ""
color: M.Theme.base05
font.pixelSize: M.Theme.fontSize - 1
font.family: M.Theme.fontFamily
color: S.Theme.base05
font.pixelSize: S.Theme.fontSize - 1
font.family: S.Theme.fontFamily
font.bold: true
elide: Text.ElideRight
}
@ -380,9 +381,9 @@ M.HoverPanel {
height: 28
verticalAlignment: Text.AlignVCenter
text: "\uF1F8"
color: _groupDismissHover.hovered ? M.Theme.base08 : M.Theme.base04
font.pixelSize: M.Theme.fontSize - 1
font.family: M.Theme.iconFontFamily
color: _groupDismissHover.hovered ? S.Theme.base08 : S.Theme.base04
font.pixelSize: S.Theme.fontSize - 1
font.family: S.Theme.iconFontFamily
opacity: _headerHover.hovered ? 1 : 0
HoverHandler {
@ -409,14 +410,14 @@ M.HoverPanel {
anchors.leftMargin: 10
anchors.right: parent.right
anchors.rightMargin: 10
y: 28 + index * (M.Theme.fontSize + 4)
height: M.Theme.fontSize + 4
y: 28 + index * (S.Theme.fontSize + 4)
height: S.Theme.fontSize + 4
verticalAlignment: Text.AlignVCenter
text: modelData
elide: Text.ElideRight
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
color: M.Theme.base04
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
color: S.Theme.base04
}
}
}
@ -479,8 +480,8 @@ M.HoverPanel {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: "No notifications"
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: S.Theme.base04
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
}
}

View file

@ -1,6 +1,7 @@
import QtQuick
import Quickshell.Services.Notifications
import "." as M
import "../services" as S
QtObject {
id: root

View file

@ -3,6 +3,7 @@ import Quickshell
import Quickshell.Wayland
import Quickshell.Services.Notifications
import "." as M
import "../services" as S
PanelWindow {
id: root
@ -33,7 +34,7 @@ PanelWindow {
property var _knownIds: ({})
Repeater {
model: M.NotifService.popups.slice(0, M.Modules.notifications.maxPopups || 4)
model: M.NotifService.popups.slice(0, S.Modules.notifications.maxPopups || 4)
delegate: Item {
id: popupItem

View file

@ -4,6 +4,7 @@ import QtQuick
import Quickshell
import Quickshell.Services.Notifications
import "." as M
import "../services" as S
QtObject {
id: root
@ -96,7 +97,7 @@ QtObject {
});
// Trim excess popups
const max = M.Modules.notifications.maxPopups || 4;
const max = S.Modules.notifications.maxPopups || 4;
const currentPopups = root.list.filter(n => n.popup);
if (currentPopups.length > max) {
for (let i = max; i < currentPopups.length; i++)
@ -106,13 +107,13 @@ QtObject {
// Auto-expire popup (skip for critical)
if (item.popup && !isCritical) {
const timeout = notif.expireTimeout > 0 ? notif.expireTimeout : (M.Modules.notifications.timeout || 3000);
const timeout = notif.expireTimeout > 0 ? notif.expireTimeout : (S.Modules.notifications.timeout || 3000);
item._expireTimer.interval = timeout;
item._expireTimer.running = true;
}
// Trim history (-1 = unlimited)
const maxHistory = M.Modules.notifications.maxHistory ?? -1;
const maxHistory = S.Modules.notifications.maxHistory ?? -1;
while (maxHistory > 0 && root.list.length > maxHistory) {
const old = root.list.pop();
old.finishDismiss();

View file

@ -2,10 +2,11 @@ import QtQuick
import Quickshell
import Quickshell.Services.Notifications
import "." as M
import "../services" as S
M.BarSection {
id: root
spacing: M.Theme.moduleSpacing
spacing: S.Theme.moduleSpacing
tooltip: {
const parts = [M.NotifService.count + " notification" + (M.NotifService.count !== 1 ? "s" : "")];
if (M.NotifService.dnd)
@ -23,13 +24,13 @@ M.BarSection {
return M.NotifService.count > 0 ? "\uDB80\uDCA0" : "\uDB82\uDE93";
return M.NotifService.count > 0 ? "\uDB84\uDD6B" : "\uDB80\uDC9C";
}
color: M.NotifService.dnd ? M.Theme.base04 : root.accentColor
color: M.NotifService.dnd ? S.Theme.base04 : root.accentColor
anchors.verticalCenter: parent.verticalCenter
}
M.BarLabel {
id: countLabel
label: M.NotifService.count > 0 ? String(M.NotifService.count) + (root.hasUrgent ? "!" : "") : ""
color: root.hasUrgent ? M.Theme.base08 : root.accentColor
color: root.hasUrgent ? S.Theme.base08 : root.accentColor
anchors.verticalCenter: parent.verticalCenter
transform: Scale {

View file

@ -2,6 +2,7 @@ import QtQuick
import Quickshell
import Quickshell.Wayland
import "." as M
import "../services" as S
import "../applets" as C
PanelWindow {

View file

@ -1,12 +1,13 @@
import QtQuick
import "." as M
import "../services" as S
Rectangle {
property color accentColor: M.Theme.base05
property color accentColor: S.Theme.base05
color: M.Theme.base01
opacity: Math.max(M.Theme.barOpacity, 0.85)
radius: M.Theme.radius
color: S.Theme.base01
opacity: Math.max(S.Theme.barOpacity, 0.85)
radius: S.Theme.radius
border.color: accentColor
border.width: 1
}

View file

@ -2,6 +2,7 @@ import QtQuick
import Quickshell
import Quickshell.Io
import "." as M
import "../services" as S
M.BarIcon {
id: root

View file

@ -1,6 +1,7 @@
import QtQuick
import Quickshell
import "." as M
import "../services" as S
M.HoverPanel {
id: menuWindow
@ -23,31 +24,31 @@ M.HoverPanel {
label: "Lock",
icon: "\uF023",
cmd: ["loginctl", "lock-session"],
color: M.Theme.base0D
color: S.Theme.base0D
},
{
label: "Suspend",
icon: "\uF186",
cmd: ["systemctl", "suspend"],
color: M.Theme.base0E
color: S.Theme.base0E
},
{
label: "Logout",
icon: "\uF2F5",
cmd: menuWindow._isNiri ? ["niri", "msg", "action", "quit"] : ["loginctl", "terminate-user", ""],
color: M.Theme.base0A
color: S.Theme.base0A
},
{
label: "Reboot",
icon: "\uF021",
cmd: ["systemctl", "reboot"],
color: M.Theme.base09
color: S.Theme.base09
},
{
label: "Shutdown",
icon: "\uF011",
cmd: ["systemctl", "poweroff"],
color: M.Theme.base08
color: S.Theme.base08
}
]
@ -64,8 +65,8 @@ M.HoverPanel {
anchors.fill: parent
anchors.leftMargin: 4
anchors.rightMargin: 4
color: entryArea.containsMouse ? M.Theme.base02 : "transparent"
radius: M.Theme.radius
color: entryArea.containsMouse ? S.Theme.base02 : "transparent"
radius: S.Theme.radius
}
Text {
@ -75,8 +76,8 @@ M.HoverPanel {
anchors.leftMargin: 12
text: entry.modelData.icon
color: entry.modelData.color
font.pixelSize: M.Theme.fontSize + 1
font.family: M.Theme.iconFontFamily
font.pixelSize: S.Theme.fontSize + 1
font.family: S.Theme.iconFontFamily
}
Text {
@ -84,9 +85,9 @@ M.HoverPanel {
anchors.left: entryIcon.right
anchors.leftMargin: 10
text: entry.modelData.label
color: M.Theme.base05
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: S.Theme.base05
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
}
MouseArea {

View file

@ -1,11 +1,12 @@
import QtQuick
import "." as M
import "../services" as S
M.BarIcon {
id: root
tooltip: "Power profile: " + (M.PowerProfileService.profile || "unknown")
color: M.PowerProfileService.profile === "performance" ? M.Theme.base09 : M.PowerProfileService.profile === "power-saver" ? M.Theme.base0B : root.accentColor
color: M.PowerProfileService.profile === "performance" ? S.Theme.base09 : M.PowerProfileService.profile === "power-saver" ? S.Theme.base0B : root.accentColor
icon: {
if (M.PowerProfileService.profile === "performance")

View file

@ -3,6 +3,7 @@ pragma Singleton
import QtQuick
import Quickshell.Io
import "." as M
import "../services" as S
QtObject {
id: root
@ -11,7 +12,7 @@ QtObject {
readonly property bool powerSaver: profile === "power-saver"
property var _proc: Process {
running: M.Modules.powerProfile.enable
running: S.Modules.powerProfile.enable
command: ["powerprofilesctl", "get"]
stdout: StdioCollector {
onStreamFinished: root.profile = text.trim()
@ -19,7 +20,7 @@ QtObject {
}
property var _monitor: Process {
running: M.Modules.powerProfile.enable
running: S.Modules.powerProfile.enable
command: ["sh", "-c", "dbus-monitor --system \"interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='/net/hadess/PowerProfiles'\" 2>/dev/null"]
stdout: SplitParser {
splitMarker: "\n"
@ -34,7 +35,7 @@ QtObject {
property var _poll: Timer {
interval: 60000
running: M.Modules.powerProfile.enable
running: S.Modules.powerProfile.enable
repeat: true
onTriggered: root._proc.running = true
}

View file

@ -2,10 +2,11 @@ import QtQuick
import QtQuick.Effects
import Quickshell.Services.Pipewire
import "." as M
import "../services" as S
Row {
id: root
spacing: M.Theme.moduleSpacing
spacing: S.Theme.moduleSpacing
// Only detect active client streams, not hardware sources/devices
readonly property bool _videoCapture: {
@ -34,21 +35,21 @@ Row {
return false;
}
visible: M.Modules.privacy.enable && (root._videoCapture || root._audioIn)
visible: S.Modules.privacy.enable && (root._videoCapture || root._audioIn)
// Screenshare indicator
Text {
visible: root._videoCapture
text: "\uF03D"
color: M.Theme.base08
font.pixelSize: M.Theme.fontSize + 2
font.family: M.Theme.iconFontFamily
color: S.Theme.base08
font.pixelSize: S.Theme.fontSize + 2
font.family: S.Theme.iconFontFamily
anchors.verticalCenter: parent.verticalCenter
layer.enabled: true
layer.effect: MultiEffect {
shadowEnabled: true
shadowColor: M.Theme.base08
shadowColor: S.Theme.base08
shadowBlur: 0.8
shadowVerticalOffset: 0
shadowHorizontalOffset: 0
@ -74,15 +75,15 @@ Row {
Text {
visible: root._audioIn
text: "\uF130"
color: M.Theme.base0B
font.pixelSize: M.Theme.fontSize + 2
font.family: M.Theme.iconFontFamily
color: S.Theme.base0B
font.pixelSize: S.Theme.fontSize + 2
font.family: S.Theme.iconFontFamily
anchors.verticalCenter: parent.verticalCenter
layer.enabled: true
layer.effect: MultiEffect {
shadowEnabled: true
shadowColor: M.Theme.base0B
shadowColor: S.Theme.base0B
shadowBlur: 0.8
shadowVerticalOffset: 0
shadowHorizontalOffset: 0

View file

@ -2,6 +2,7 @@ import QtQuick
import Quickshell
import Quickshell.Wayland
import "." as M
import "../services" as S
// Draws rounded black corners at the edges of each screen.
// Disabled when screenRadius is 0.
@ -10,7 +11,7 @@ Item {
required property var screen
readonly property int _r: M.Theme.screenRadius
readonly property int _r: S.Theme.screenRadius
component Corner: PanelWindow {
id: win

View file

@ -1,28 +1,29 @@
import QtQuick
import Quickshell
import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
id: root
spacing: Math.max(1, M.Theme.moduleSpacing - 2)
spacing: Math.max(1, S.Theme.moduleSpacing - 2)
tooltip: ""
readonly property int _warm: M.Modules.temperature.warm || 80
readonly property int _hot: M.Modules.temperature.hot || 90
readonly property string _deviceFilter: M.Modules.temperature.device || ""
readonly property int _warm: S.Modules.temperature.warm || 80
readonly property int _hot: S.Modules.temperature.hot || 90
readonly property string _deviceFilter: S.Modules.temperature.device || ""
// If a device filter is set, use that device's temp; otherwise fall back to system max
readonly property int _temp: {
if (_deviceFilter !== "") {
const dev = M.SystemStats.tempDevices.find(d => d.name === _deviceFilter);
const dev = S.SystemStats.tempDevices.find(d => d.name === _deviceFilter);
if (dev)
return dev.celsius;
}
return M.SystemStats.tempCelsius;
return S.SystemStats.tempCelsius;
}
property color _stateColor: _temp > _hot ? M.Theme.base08 : _temp > _warm ? M.Theme.base0A : root.accentColor
property color _stateColor: _temp > _hot ? S.Theme.base08 : _temp > _warm ? S.Theme.base0A : root.accentColor
Behavior on _stateColor {
ColorAnimation {
duration: 300
@ -81,8 +82,8 @@ M.BarSection {
temp: root._temp
warm: root._warm
hot: root._hot
history: M.SystemStats.tempHistory
devices: M.SystemStats.tempDevices
history: S.SystemStats.tempHistory
devices: S.SystemStats.tempDevices
accentColor: root.accentColor
deviceFilter: root._deviceFilter
active: root._showPanel

View file

@ -5,11 +5,12 @@ import Quickshell
import Quickshell.Services.SystemTray
import "." as M
import "../services" as S
RowLayout {
id: root
spacing: M.Theme.moduleSpacing + 2
visible: M.Modules.tray.enable && SystemTray.items.length > 0
spacing: S.Theme.moduleSpacing + 2
visible: S.Modules.tray.enable && SystemTray.items.length > 0
required property var bar
property var _activeMenu: null
@ -25,8 +26,8 @@ RowLayout {
property bool _hovered: false
property real _pulseOpacity: 1
implicitWidth: M.Theme.fontSize + 4
implicitHeight: M.Theme.fontSize + 4
implicitWidth: S.Theme.fontSize + 4
implicitHeight: S.Theme.fontSize + 4
SequentialAnimation {
running: iconItem._needsAttention
@ -56,16 +57,16 @@ RowLayout {
layer.enabled: iconItem._needsAttention || iconItem._hovered
layer.effect: MultiEffect {
shadowEnabled: true
shadowColor: iconItem._needsAttention ? M.Theme.base08 : M.Theme.base05
shadowColor: iconItem._needsAttention ? S.Theme.base08 : S.Theme.base05
shadowBlur: iconItem._needsAttention ? 0.8 : 0.5
shadowVerticalOffset: 0
shadowHorizontalOffset: 0
}
M.ThemedIcon {
S.ThemedIcon {
anchors.fill: parent
source: iconItem.modelData.icon
tint: iconItem._needsAttention ? M.Theme.base08 : (root.parent?.accentColor ?? M.Theme.base05)
tint: iconItem._needsAttention ? S.Theme.base08 : (root.parent?.accentColor ?? S.Theme.base05)
}
}
@ -77,7 +78,7 @@ RowLayout {
M.FlyoutState.text = tip;
M.FlyoutState.itemX = iconItem.mapToGlobal(iconItem.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0);
M.FlyoutState.screen = QsWindow.window?.screen ?? null;
M.FlyoutState.accentColor = root.parent?.accentColor ?? M.Theme.base05;
M.FlyoutState.accentColor = root.parent?.accentColor ?? S.Theme.base05;
M.FlyoutState.visible = true;
} else if (!hovered) {
M.FlyoutState.visible = false;
@ -110,7 +111,7 @@ RowLayout {
id: menuLoader
active: false
M.TrayMenu {
accentColor: root.parent?.accentColor ?? M.Theme.base05
accentColor: root.parent?.accentColor ?? S.Theme.base05
handle: iconItem.modelData.menu
screen: root.bar.screen
anchorX: iconItem.mapToGlobal(iconItem.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0)

View file

@ -1,6 +1,7 @@
import QtQuick
import Quickshell
import "." as M
import "../services" as S
M.HoverPanel {
id: menuWindow
@ -26,8 +27,8 @@ M.HoverPanel {
anchors.fill: parent
anchors.leftMargin: 4
anchors.rightMargin: 4
color: backArea.containsMouse ? M.Theme.base02 : "transparent"
radius: M.Theme.radius
color: backArea.containsMouse ? S.Theme.base02 : "transparent"
radius: S.Theme.radius
}
Text {
@ -35,9 +36,9 @@ M.HoverPanel {
anchors.left: parent.left
anchors.leftMargin: 12
text: "\u2039 Back"
color: M.Theme.base05
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: S.Theme.base05
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
}
MouseArea {
@ -71,7 +72,7 @@ M.HoverPanel {
anchors.leftMargin: 8
anchors.rightMargin: 8
height: 1
color: M.Theme.base03
color: S.Theme.base03
}
Rectangle {
@ -79,18 +80,18 @@ M.HoverPanel {
anchors.fill: parent
anchors.leftMargin: 4
anchors.rightMargin: 4
color: rowArea.containsMouse && entryItem.modelData.enabled ? M.Theme.base02 : "transparent"
radius: M.Theme.radius
color: rowArea.containsMouse && entryItem.modelData.enabled ? S.Theme.base02 : "transparent"
radius: S.Theme.radius
}
M.ThemedIcon {
S.ThemedIcon {
id: entryIcon
visible: !entryItem.modelData.isSeparator && entryItem.modelData.icon !== ""
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 12
width: M.Theme.fontSize
height: M.Theme.fontSize
width: S.Theme.fontSize
height: S.Theme.fontSize
source: entryItem.modelData.icon
tint: menuWindow.accentColor
fillMode: Image.PreserveAspectFit
@ -104,9 +105,9 @@ M.HoverPanel {
anchors.right: entryChevron.visible ? entryChevron.left : parent.right
anchors.rightMargin: entryChevron.visible ? 4 : 12
text: entryItem.modelData.text
color: entryItem.modelData.enabled ? M.Theme.base05 : M.Theme.base03
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: entryItem.modelData.enabled ? S.Theme.base05 : S.Theme.base03
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
elide: Text.ElideRight
}
@ -117,9 +118,9 @@ M.HoverPanel {
anchors.right: parent.right
anchors.rightMargin: 12
text: "\u203A"
color: entryItem.modelData.enabled ? M.Theme.base05 : M.Theme.base03
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
color: entryItem.modelData.enabled ? S.Theme.base05 : S.Theme.base03
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
}
MouseArea {

View file

@ -2,11 +2,12 @@ import QtQuick
import Quickshell
import Quickshell.Services.Pipewire
import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
id: root
spacing: M.Theme.moduleSpacing
spacing: S.Theme.moduleSpacing
tooltip: ""
PwObjectTracker {
@ -17,7 +18,7 @@ M.BarSection {
readonly property real volume: sink?.audio?.volume ?? 0
readonly property bool muted: sink?.audio?.muted ?? false
readonly property string _volumeIcon: muted ? "\uF026" : (volume > 0.5 ? "\uF028" : (volume > 0 ? "\uF027" : "\uF026"))
readonly property color _volumeColor: muted ? M.Theme.base04 : root.accentColor
readonly property color _volumeColor: muted ? S.Theme.base04 : root.accentColor
readonly property var _sinkList: {
const sinks = [];

View file

@ -1,10 +1,11 @@
import QtQuick
import Quickshell.Io
import "." as M
import "../services" as S
M.BarSection {
id: root
spacing: M.Theme.moduleSpacing
spacing: S.Theme.moduleSpacing
tooltip: root.weatherTooltip
property string weatherTooltip: ""
@ -12,7 +13,7 @@ M.BarSection {
Process {
id: proc
running: true
command: ["wttrbar"].concat(M.Modules.weather.args)
command: ["wttrbar"].concat(S.Modules.weather.args)
stdout: StdioCollector {
onStreamFinished: {
try {
@ -27,7 +28,7 @@ M.BarSection {
}
}
Timer {
interval: M.Modules.weather.interval || 3600000
interval: S.Modules.weather.interval || 3600000
running: true
repeat: true
onTriggered: proc.running = true

View file

@ -3,10 +3,11 @@ import QtQuick.Effects
import Quickshell
import Quickshell.Widgets
import "." as M
import "../services" as S
M.BarSection {
id: root
spacing: M.Theme.moduleSpacing
spacing: S.Theme.moduleSpacing
tooltip: M.NiriIpc.focusedAppId ? M.NiriIpc.focusedAppId + "\n" + M.NiriIpc.focusedTitle : M.NiriIpc.focusedTitle
readonly property string _iconSource: {
@ -25,7 +26,7 @@ M.BarSection {
id: _icon
visible: root._iconSource !== ""
source: root._iconSource
implicitSize: M.Theme.fontSize + 2
implicitSize: S.Theme.fontSize + 2
anchors.verticalCenter: parent.verticalCenter
layer.enabled: true
layer.effect: MultiEffect {

View file

@ -2,6 +2,7 @@ import QtQuick
import Quickshell
import Quickshell.Io
import "." as M
import "../services" as S
Row {
id: root
@ -70,7 +71,7 @@ Row {
M.FlyoutState.text = name;
M.FlyoutState.itemX = pill.mapToGlobal(pill.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0);
M.FlyoutState.screen = QsWindow.window?.screen ?? null;
M.FlyoutState.accentColor = root.parent?.accentColor ?? M.Theme.base05;
M.FlyoutState.accentColor = root.parent?.accentColor ?? S.Theme.base05;
M.FlyoutState.visible = true;
} else {
M.FlyoutState.visible = false;
@ -78,10 +79,10 @@ Row {
}
}
width: M.Theme.fontSize + 4
height: M.Theme.fontSize + 4
width: S.Theme.fontSize + 4
height: S.Theme.fontSize + 4
radius: width / 2
color: pill.active ? (root.parent?.accentColor ?? M.Theme.base0D) : (pill._hovered ? M.Theme.base03 : M.Theme.base02)
color: pill.active ? (root.parent?.accentColor ?? S.Theme.base0D) : (pill._hovered ? S.Theme.base03 : S.Theme.base02)
Behavior on color {
ColorAnimation {
duration: 150
@ -91,9 +92,9 @@ Row {
Text {
anchors.centerIn: parent
text: pill.modelData.idx
color: pill.active ? M.Theme.base00 : (root.parent?.accentColor ?? M.Theme.base05)
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
color: pill.active ? S.Theme.base00 : (root.parent?.accentColor ?? S.Theme.base05)
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
font.bold: pill.active
}

View file

@ -1,7 +1,5 @@
module modules
singleton Theme 1.0 Theme.qml
singleton FlyoutState 1.0 FlyoutState.qml
singleton Modules 1.0 Modules.qml
Bar 1.0 Bar.qml
BarGroup 1.0 BarGroup.qml
BarSection 1.0 BarSection.qml
@ -34,7 +32,6 @@ IdleInhibitor 1.0 IdleInhibitor.qml
Notifications 1.0 Notifications.qml
singleton NiriIpc 1.0 NiriIpc.qml
singleton PowerProfileService 1.0 PowerProfileService.qml
singleton SystemStats 1.0 SystemStats.qml
ProcessList 1.0 ProcessList.qml
singleton NotifService 1.0 NotifService.qml
NotifItem 1.0 NotifItem.qml

4
shell/services/qmldir Normal file
View file

@ -0,0 +1,4 @@
module services
singleton Theme 1.0 Theme.qml
singleton SystemStats 1.0 SystemStats.qml
singleton Modules 1.0 Modules.qml