added quickshell config

This commit is contained in:
2026-08-24 10:03:59 +01:00
parent 866ee0bb9b
commit c4b4a3bd26
14 changed files with 573 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
import QtQuick
import QtQuick.Layouts
import Quickshell.Hyprland
import "../../config"
Text {
Layout.maximumWidth: 320
elide: Text.ElideRight
font.family: Appearance.fontFamily
font.pixelSize: Appearance.fontSizeSmall
color: Colors.muted
text: Hyprland.activeToplevel ? Hyprland.activeToplevel.title : ""
}

View File

@@ -0,0 +1,55 @@
import Quickshell
import Quickshell.Wayland
import QtQuick
import QtQuick.Layouts
import "../../config"
PanelWindow {
id: bar
anchors {
top: true
left: true
right: true
}
implicitHeight: Appearance.barHeight
exclusiveZone: implicitHeight
color: "transparent"
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.namespace: "quickshell:bar"
Rectangle {
anchors.fill: parent
color: Colors.background
}
RowLayout {
anchors {
left: parent.left
verticalCenter: parent.verticalCenter
leftMargin: Appearance.spacing
}
spacing: Appearance.spacing
Workspaces { screen: bar.screen }
ActiveWindow {}
}
Clock {
anchors.centerIn: parent
}
RowLayout {
anchors {
right: parent.right
verticalCenter: parent.verticalCenter
rightMargin: Appearance.spacing
}
spacing: Appearance.spacing
Tray {}
NetworkIndicator {}
BluetoothIndicator {}
Volume {}
PowerButton {}
}
}

View File

@@ -0,0 +1,38 @@
import QtQuick
import Quickshell.Bluetooth
import "../../config"
Item {
id: root
implicitWidth: label.implicitWidth + 4
implicitHeight: Appearance.barHeight
readonly property var adapter: Bluetooth.defaultAdapter
readonly property bool anyConnected: {
if (!adapter) return false
const devices = adapter.devices.values
for (let i = 0; i < devices.length; i++) {
if (devices[i].connected) return true
}
return false
}
Text {
id: label
anchors.centerIn: parent
font.family: Appearance.iconFontFamily
font.variableAxes: Appearance.iconFontAxes
font.pixelSize: 16
color: (root.adapter && root.adapter.enabled) ? Colors.foreground : Colors.muted
text: {
if (!root.adapter || !root.adapter.enabled) return "bluetooth_disabled"
return root.anyConnected ? "bluetooth_connected" : "bluetooth"
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: if (root.adapter) root.adapter.enabled = !root.adapter.enabled
}
}

View File

@@ -0,0 +1,18 @@
import QtQuick
import "../../config"
Text {
id: root
font.family: Appearance.fontFamily
font.pixelSize: Appearance.fontSize
font.bold: true
color: Colors.foreground
text: Qt.formatDateTime(new Date(), "ddd d MMM hh:mm")
Timer {
interval: 1000
running: true
repeat: true
onTriggered: root.text = Qt.formatDateTime(new Date(), "ddd d MMM hh:mm")
}
}

View File

@@ -0,0 +1,35 @@
import QtQuick
import Quickshell.Networking
import "../../config"
Item {
id: root
implicitWidth: label.implicitWidth + 4
implicitHeight: Appearance.barHeight
readonly property var connectedDevice: {
const devices = Networking.devices.values
for (let i = 0; i < devices.length; i++) {
if (devices[i].connected)
return devices[i]
}
return null
}
Text {
id: label
anchors.centerIn: parent
font.family: Appearance.iconFontFamily
font.variableAxes: Appearance.iconFontAxes
font.pixelSize: 16
color: root.connectedDevice ? Colors.foreground : Colors.muted
text: {
if (!root.connectedDevice)
return "wifi_off"
return root.connectedDevice.type === DeviceType.Wired ? "settings_ethernet" : "wifi"
}
}
// TODO(follow-up): wire this up to a network panel (SSID list, connect/forget)
// once the control center lands.
}

View File

@@ -0,0 +1,114 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import "../../config"
Item {
id: root
implicitWidth: label.implicitWidth + 4
implicitHeight: Appearance.barHeight
Text {
id: label
anchors.centerIn: parent
font.family: Appearance.iconFontFamily
font.variableAxes: Appearance.iconFontAxes
font.pixelSize: 16
color: Colors.foreground
text: "power_settings_new"
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: menu.visible = !menu.visible
}
Process { id: proc }
PopupWindow {
id: menu
visible: false
color: "transparent"
implicitWidth: 170
implicitHeight: list.model.length * 32 + (list.model.length - 1) * 2 + 16
anchor {
item: root
edges: Edges.Bottom | Edges.Right
gravity: Edges.Bottom | Edges.Left
margins.top: 4
}
Rectangle {
anchors.fill: parent
radius: Appearance.radius
color: Colors.surface
border.color: Colors.muted
border.width: 1
Column {
anchors.fill: parent
anchors.margins: 8
spacing: 2
Repeater {
id: list
model: [
// "iconSize" is optional — omit it to use the 15px default below.
// Material Symbols glyphs aren't all the same visual weight at a
// given size (a padlock silhouette reads bulkier than a thin arrow),
// so nudge individual icons here to balance them by eye.
{ label: "Lock", icon: "lock", iconSize: 13, cmd: ["hyprlock"] },
{ label: "Log out", icon: "logout", cmd: ["hyprctl", "dispatch", "exit"] },
{ label: "Reboot", icon: "restart_alt", cmd: ["systemctl", "reboot"] },
{ label: "Shut down", icon: "power_settings_new", cmd: ["systemctl", "poweroff"] }
]
delegate: Rectangle {
id: entry
required property var modelData
width: parent ? parent.width : 0
height: 32
radius: Appearance.radiusSmall
color: entryMouse.containsMouse ? Colors.primary : "transparent"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 8
spacing: 8
Text {
Layout.preferredWidth: 20
horizontalAlignment: Text.AlignHCenter
text: entry.modelData.icon
font.family: Appearance.iconFontFamily
font.variableAxes: Appearance.iconFontAxes
font.pixelSize: entry.modelData.iconSize || 15
color: entryMouse.containsMouse ? Colors.primaryText : Colors.foreground
}
Text {
text: entry.modelData.label
font.family: Appearance.fontFamily
font.pixelSize: Appearance.fontSize
color: entryMouse.containsMouse ? Colors.primaryText : Colors.foreground
}
}
MouseArea {
id: entryMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
proc.command = entry.modelData.cmd
proc.running = true
menu.visible = false
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,32 @@
import QtQuick
import QtQuick.Layouts
import Quickshell.Services.SystemTray
import Quickshell.Widgets
import "../../config"
RowLayout {
spacing: Appearance.spacing * 0.6
Repeater {
model: SystemTray.items
delegate: IconImage {
id: trayIcon
required property var modelData
implicitWidth: 16
implicitHeight: 16
source: modelData.icon
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: (mouse) => {
if (mouse.button === Qt.LeftButton)
trayIcon.modelData.activate()
else
trayIcon.modelData.secondaryActivate()
}
}
}
}
}

View File

@@ -0,0 +1,43 @@
import QtQuick
import Quickshell.Services.Pipewire
import "../../config"
Item {
id: root
implicitWidth: label.implicitWidth + 4
implicitHeight: Appearance.barHeight
readonly property var sink: Pipewire.defaultAudioSink
readonly property real vol: (sink && sink.audio) ? sink.audio.volume : 0
readonly property bool muted: (sink && sink.audio) ? sink.audio.muted : false
PwObjectTracker { objects: root.sink ? [root.sink] : [] }
Text {
id: label
anchors.centerIn: parent
font.family: Appearance.iconFontFamily
font.variableAxes: Appearance.iconFontAxes
font.pixelSize: 16
color: Colors.foreground
text: {
if (root.muted || root.vol <= 0) return "volume_off"
if (root.vol < 0.5) return "volume_down"
return "volume_up"
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton
onClicked: if (root.sink && root.sink.audio) root.sink.audio.muted = !root.sink.audio.muted
onWheel: (wheel) => {
if (!root.sink || !root.sink.audio) return
const step = 0.05
const delta = wheel.angleDelta.y > 0 ? step : -step
root.sink.audio.volume = Math.max(0, Math.min(1, root.sink.audio.volume + delta))
}
}
}

View File

@@ -0,0 +1,44 @@
import QtQuick
import QtQuick.Layouts
import Quickshell.Hyprland
import "../../config"
RowLayout {
id: root
property var screen
spacing: 4
Repeater {
model: Hyprland.workspaces
delegate: Rectangle {
id: pill
required property var modelData
visible: modelData.monitor && root.screen && modelData.monitor.name === root.screen.name
implicitWidth: 26
implicitHeight: 22
radius: Appearance.radiusSmall
color: modelData.urgent ? Colors.urgent
: modelData.active ? Colors.primary
: "transparent"
Behavior on color { ColorAnimation { duration: Appearance.animationDuration } }
Text {
anchors.centerIn: parent
text: modelData.name
font.family: Appearance.fontFamily
font.pixelSize: Appearance.fontSizeSmall
color: modelData.active ? Colors.primaryText : Colors.foreground
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: Hyprland.dispatch("workspace " + modelData.name)
}
}
}
}