refactor(bar): restructure panel window and corners

This commit is contained in:
tux
2026-08-23 02:02:38 +05:30
parent ab5587fd90
commit a1533e73c7
4 changed files with 444 additions and 309 deletions

245
Bar.qml
View File

@@ -4,33 +4,151 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Effects import QtQuick.Effects
import Quickshell.Wayland import QtQuick.Shapes
import Quickshell.Hyprland import Quickshell.Hyprland
import Quickshell.Services.UPower
import Quickshell.Services.SystemTray import Quickshell.Services.SystemTray
import Quickshell.Widgets
import Quickshell.Wayland
import qs.config import qs.config
Scope { PanelWindow {
Variants { id: window
model: Quickshell.screens
property color barColor: Appearance.colors.background
PanelWindow {
required property var modelData
screen: modelData
color: "transparent" color: "transparent"
exclusionMode: ExclusionMode.Ignore
anchors { mask: Region {
top: true item: cornersArea
intersection: Intersection.Subtract
} }
implicitHeight: 50 anchors {
implicitWidth: 1150 left: true
top: true
right: true
bottom: true
}
// Inline Components
component Corner: WrapperItem {
id: root
property int corner
property real radius: Appearance.radius
property color color
Component.onCompleted: {
switch (corner) {
case 0:
anchors.left = parent.left;
anchors.top = parent.top;
break;
case 1:
anchors.top = parent.top;
anchors.right = parent.right;
rotation = 90;
break;
case 2:
anchors.right = parent.right;
anchors.bottom = parent.bottom;
rotation = 180;
break;
case 3:
anchors.left = parent.left;
anchors.bottom = parent.bottom;
rotation = -90;
break;
}
}
Shape {
preferredRendererType: Shape.CurveRenderer
ShapePath {
strokeWidth: 0
fillColor: root.color
startX: root.radius
PathArc {
relativeX: -root.radius
relativeY: root.radius
radiusX: root.radius
radiusY: radiusX
direction: PathArc.Counterclockwise
}
PathLine {
relativeX: 0
relativeY: -root.radius
}
PathLine {
relativeX: root.radius
relativeY: 0
}
}
}
}
component Exclusion: PanelWindow {
property string name
implicitWidth: 0
implicitHeight: 0
WlrLayershell.namespace: `quickshell:${name}ExclusionZone`
}
// Exclusions
Scope {
Exclusion {
name: "left"
exclusiveZone: leftBar.implicitWidth
anchors.left: true
}
Exclusion {
name: "top"
exclusiveZone: topBar.implicitHeight
anchors.top: true
}
Exclusion {
name: "right"
exclusiveZone: rightBar.implicitWidth
anchors.right: true
}
Exclusion {
name: "bottom"
exclusiveZone: bottomBar.implicitHeight
anchors.bottom: true
}
}
// Bars
Rectangle { Rectangle {
anchors.fill: parent id: leftBar
anchors.topMargin: 10 implicitWidth: 10
radius: Appearance.radius implicitHeight: QsWindow.window?.height ?? 0
color: Appearance.colors.background color: window.barColor
anchors.left: parent.left
}
Rectangle {
id: rightBar
implicitWidth: 10
implicitHeight: QsWindow.window?.height ?? 0
color: window.barColor
anchors.right: parent.right
}
Rectangle {
id: bottomBar
implicitWidth: QsWindow.window?.width ?? 0
implicitHeight: 10
color: window.barColor
anchors.bottom: parent.bottom
}
Rectangle {
id: topBar
implicitWidth: QsWindow.window?.width ?? 0
implicitHeight: 50
color: window.barColor
anchors.top: parent.top
FlexboxLayout { FlexboxLayout {
id: flexLayout id: flexLayout
@@ -41,6 +159,7 @@ Scope {
direction: FlexboxLayout.Row direction: FlexboxLayout.Row
justifyContent: FlexboxLayout.JustifySpaceBetween justifyContent: FlexboxLayout.JustifySpaceBetween
Rectangle { Rectangle {
color: 'transparent' color: 'transparent'
implicitHeight: parent.height implicitHeight: parent.height
@@ -82,20 +201,15 @@ Scope {
} }
Button { Button {
property real percentage: Math.round(UPower.displayDevice.percentage * 100)
property real energyRate: UPower.displayDevice.changeRate
property string iconBase: Quickshell.shellPath("assets") + "/icons/"
property string iconName: parent.percentage < 30 ? "battery-low.svg" : parent.percentage < 70 ? "battery-medium.svg" : "battery-full.svg"
padding: Appearance.padding padding: Appearance.padding
text: `${percentage}% ${energyRate}W` text: `${Battery.percentage}% ${Battery.energyRate}W`
palette.buttonText: Appearance.colors.foreground palette.buttonText: Appearance.colors.foreground
font.family: Appearance.font.family font.family: Appearance.font.family
font.pointSize: Appearance.font.pointSize font.pointSize: Appearance.font.pointSize
icon.color: Appearance.colors.foreground icon.color: Appearance.colors.foreground
icon.source: iconBase + iconName icon.source: Battery.icon
background: Rectangle { background: Rectangle {
anchors.fill: parent anchors.fill: parent
@@ -176,69 +290,12 @@ Scope {
anchors.right: parent.right anchors.right: parent.right
spacing: Appearance.spacing spacing: Appearance.spacing
Button {
padding: Appearance.padding
display: AbstractButton.IconOnly
icon.color: Appearance.colors.foreground
icon.source: Quickshell.shellPath("assets") + "/icons/wifi.svg"
onClicked: {
Quickshell.execDetached(["vicinae", "vicinae://extensions/dagimg-dot/wifi-commander/scan-wifi"]);
}
hoverEnabled: true
HoverHandler {
cursorShape: Qt.PointingHandCursor
}
background: Rectangle {
anchors.fill: parent
radius: Appearance.radius
color: parent.hovered ? Appearance.colors.inActive : Appearance.colors.background
Behavior on color {
ColorAnimation {
duration: Appearance.duration
}
}
}
}
Button {
padding: Appearance.padding
display: AbstractButton.IconOnly
icon.color: Appearance.colors.foreground
icon.source: Quickshell.shellPath("assets") + "/icons/bluetooth.svg"
onClicked: {
Quickshell.execDetached(["vicinae", "vicinae://extensions/Gelei/bluetooth/devices"]);
}
hoverEnabled: true
HoverHandler {
cursorShape: Qt.PointingHandCursor
}
background: Rectangle {
anchors.fill: parent
radius: Appearance.radius
color: parent.hovered ? Appearance.colors.inActive : Appearance.colors.background
Behavior on color {
ColorAnimation {
duration: Appearance.duration
}
}
}
}
Rectangle { Rectangle {
implicitWidth: sysTrayRow.implicitWidth + 10 implicitWidth: sysTrayRow.implicitWidth + 10
implicitHeight: parent.height implicitHeight: parent.height
radius: Appearance.radius radius: Appearance.radius
color: Appearance.colors.inActive color: Appearance.colors.inActive
visible: SystemTray.items.values.length > 0
Row { Row {
id: sysTrayRow id: sysTrayRow
@@ -250,8 +307,8 @@ Scope {
model: SystemTray.items.values.length model: SystemTray.items.values.length
Image { Image {
source: SystemTray.items.values[index].icon source: SystemTray.items.values[index].icon
height: parent.parent.height - 15 height: parent.parent.height - 18
width: parent.parent.height - 15 width: parent.parent.height - 18
} }
} }
} }
@@ -300,7 +357,27 @@ Scope {
} }
} }
} }
}
Rectangle {
id: cornersArea
implicitWidth: QsWindow.window?.width - (leftBar.implicitWidth + rightBar.implicitWidth)
implicitHeight: QsWindow.window?.height - (topBar.implicitHeight + bottomBar.implicitHeight)
color: "transparent"
x: leftBar.implicitWidth
y: topBar.implicitHeight
Repeater {
model: [0, 1, 2, 3]
Corner {
required property int modelData
corner: modelData
color: window.barColor
} }
} }
} }
} }

13
Battery.qml Normal file
View File

@@ -0,0 +1,13 @@
pragma Singleton
import Quickshell
import QtQuick
import Quickshell.Services.UPower
Singleton {
id: root
readonly property int percentage: Math.round(UPower.displayDevice.percentage * 100)
readonly property real energyRate: UPower.displayDevice.changeRate
readonly property string iconName: root.percentage < 30 ? "battery-low.svg" : root.percentage < 70 ? "battery-medium.svg" : "battery-full.svg"
readonly property url icon: `${Quickshell.shellPath("assets")}/icons/${root.iconName}`
}

41
flake.lock generated
View File

@@ -2,15 +2,15 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1771848320, "lastModified": 1787360063,
"narHash": "sha256-0MAd+0mun3K/Ns8JATeHT1sX28faLII5hVLq0L3BdZU=", "narHash": "sha256-dt4WdcvsA8/RCe+VZZwqU0X+XMM3wBbGCWA0/sFWzGo=",
"owner": "nixos", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "2fc6539b481e1d2569f25f8799236694180c0993", "rev": "2c423e03bbafcff28bfadc6781a4a8257f205cb5",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "NixOS",
"ref": "nixos-unstable", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
@@ -23,11 +23,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1771926182, "lastModified": 1787279335,
"narHash": "sha256-QbXuSLhiSxOq6ydBL3+KGe1aiYWBW+e3J6qjJZaRMq0=", "narHash": "sha256-CLX2Zp5i5BuLbOxNOkwRd9YY84IOrACNxBV79o9/F9Y=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "cddb4f061bab495f4473ca5f2c571b6c710efef7", "rev": "1a4716cde794a59928d9d9fc15f2afc7a95de360",
"revCount": 744, "revCount": 846,
"type": "git", "type": "git",
"url": "https://git.outfoxxed.me/outfoxxed/quickshell" "url": "https://git.outfoxxed.me/outfoxxed/quickshell"
}, },
@@ -39,7 +39,28 @@
"root": { "root": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"quickshell": "quickshell" "quickshell": "quickshell",
"treefmt-nix": "treefmt-nix"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1786901030,
"narHash": "sha256-WSFCsDSE5ffgD2MqzkM2CYjeFiKhRF/dJUN8uedb6YE=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "27b3b12a8e6375f28ebe122f07d230ca5459bbfa",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
} }
} }
}, },

View File

@@ -2,30 +2,54 @@
description = "tux's widgets for wayland"; description = "tux's widgets for wayland";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
quickshell = { quickshell = {
url = "git+https://git.outfoxxed.me/outfoxxed/quickshell"; url = "git+https://git.outfoxxed.me/outfoxxed/quickshell";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = { outputs =
{
self, self,
nixpkgs, nixpkgs,
quickshell, quickshell,
}: let treefmt-nix,
}:
let
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.${system} = { quickshellWithModules = quickshell.packages.${system}.default.withModules [
default = pkgs.mkShell { pkgs.qt6.qtbase
buildInputs = [ pkgs.qt6.qtdeclarative
quickshell.packages.${system}.default pkgs.qt6.qtmultimedia
pkgs.kdePackages.qtdeclarative pkgs.qt6.qttranslations
pkgs.kdePackages.qt5compat ];
treefmtEval = treefmt-nix.lib.evalModule pkgs {
projectRootFile = "flake.nix";
programs = {
nixfmt.enable = true;
};
};
in
{
formatter.${system} = treefmtEval.config.build.wrapper;
devShells.${system}.default = pkgs.mkShell {
packages = [
quickshellWithModules
pkgs.cava
pkgs.wallust
]; ];
}; };
}; };
};
} }