Compare commits

...

2 Commits

Author SHA1 Message Date
6ea4782a80 usable 2026-03-15 20:08:48 -05:00
9871af127a start dashboard 2026-03-09 13:45:08 -05:00
17 changed files with 680 additions and 519 deletions

View File

@@ -12,6 +12,8 @@ PanelWindow {
property real radius: 10 property real radius: 10
onRadiusChanged: Hyprland.dispatch("exec hyprctl keyword decoration:rounding " + radius)
anchors { anchors {
top: true top: true
left: true left: true
@@ -20,18 +22,19 @@ PanelWindow {
} }
Component.onCompleted: { Component.onCompleted: {
//Hyprland.dispatch("exec hyprctl keyword monitor eDP-1,addreserved," + topRect.height + "," + botRect.height + "," + leftRect.width + "," + rightRect.width) Hyprland.dispatch("exec hyprctl keyword monitor " + Hyprland.monitorFor(root.screen).name + ",addreserved," + topEx + "," + botEx + "," + leftEx + "," + rightEx)
Hyprland.dispatch("exec hyprctl keyword monitor eDP-1,addreserved," + (midFO.visible ? midFO.y + midFO.height : topEx) + "," + botEx + "," + leftEx + "," + rightEx) Hyprland.dispatch("exec hyprctl keyword decoration:rounding " + radius)
} }
property int topEx: topRect.height property int topEx: topRect.reserve
property int botEx: botRect.height property int botEx: botRect.reserve
property int leftEx: leftRect.width property int leftEx: leftRect.reserve
property int rightEx: rightRect.width property int rightEx: rightRect.reserve
id: root id: root
@@ -45,7 +48,7 @@ PanelWindow {
mask: Region { mask: Region {
Region { Region {
item: topRect item: topRect.topRectArea
} }
Region { Region {
@@ -53,56 +56,32 @@ PanelWindow {
} }
Region { Region {
item: midFO.visible ? midFO : topRect item: topRect.midFO.visible ? topRect.midFO : leftRect
//item: midFO }
Region {
item: dash.visible ? dash : leftRect
} }
} }
WrapperMouseArea {
id: topRectArea
Rectangle {
id: topRect
color: Pywal.special.background
anchors.fill: parent
}
implicitHeight: 10
implicitWidth: parent.width
hoverEnabled: true BarBottom {
onEntered: {
midFO.set = !midFO.set
midFO.visible = Qt.binding(() => midFO.set)
Hyprland.dispatch("exec hyprctl keyword monitor eDP-1,addreserved," + (midFO.visible ? midFO.y + midFO.height : topEx) + "," + botEx + "," + leftEx + "," + rightEx)
}
//onEntered: midFO.visible = true
}
Rectangle {
id: botRect id: botRect
y: parent.height - height
color: Pywal.special.background
implicitHeight: 10
implicitWidth: parent.width
} }
BarLeft { BarLeft {
id: leftRect id: leftRect
window: root
} }
BarRight {
Rectangle {
id: rightRect id: rightRect
x: parent.width - width
color: Pywal.special.background
implicitWidth: 10
implicitHeight: parent.height
} }
Shape { Shape {
x: leftRect.x + leftRect.width - 1 x: leftRect.x + leftRect.width - 1
y: topRect.y + topRect.height - 1 y: topRect.cornerY
ShapePath { ShapePath {
strokeWidth: 4 strokeWidth: 4
@@ -110,12 +89,6 @@ PanelWindow {
fillColor: Pywal.special.background fillColor: Pywal.special.background
startX: 0; startY: 0 startX: 0; startY: 0
onFillColorChanged: {
console.log(Pywal.special.background)
fillColor = Qt.binding(() => Pywal.special.background)
strokeColor = Qt.binding(() => Pywal.special.background)
}
PathLine { relativeX: 0; relativeY: radius } PathLine { relativeX: 0; relativeY: radius }
PathArc { PathArc {
radiusX: radius radiusX: radius
@@ -129,7 +102,7 @@ PanelWindow {
Shape { Shape {
x: rightRect.x + 1 x: rightRect.x + 1
y: topRect.y + topRect.height - 1 y: topRect.cornerY
ShapePath { ShapePath {
strokeWidth: 4 strokeWidth: 4
@@ -193,11 +166,31 @@ PanelWindow {
} }
BarTop { BarTop {
id: midFO id: topRect
x: root.screen.width / 2 - width / 2 x: leftRect.x + leftRect.width
y: topRect.y + topRect.height - 1 width: rightRect.x - x
//y: topRect.y + topRect.height - 1
window: root window: root
radius: root.radius radius: root.radius
onShowDashChanged: dash.visible = showDash
} }
onTopExChanged: Hyprland.dispatch("exec hyprctl keyword monitor " + Hyprland.monitorFor(root.screen).name + ",addreserved," + topEx + "," + botEx + "," + leftEx + "," + rightEx)
onBotExChanged: Hyprland.dispatch("exec hyprctl keyword monitor " + Hyprland.monitorFor(root.screen).name + ",addreserved," + topEx + "," + botEx + "," + leftEx + "," + rightEx)
onRightExChanged: Hyprland.dispatch("exec hyprctl keyword monitor " + Hyprland.monitorFor(root.screen).name + ",addreserved," + topEx + "," + botEx + "," + leftEx + "," + rightEx)
onLeftExChanged: Hyprland.dispatch("exec hyprctl keyword monitor " + Hyprland.monitorFor(root.screen).name + ",addreserved," + topEx + "," + botEx + "," + leftEx + "," + rightEx)
Dashboard {
id: dash
x: root.screen.width / 2 - width / 2
y: topRect.reserve - 1
onVisibleChanged: topRect.showDash = visible
//onEntered: topRect.midFO.visible = true
onHoveredChanged: topRect.midFO.visible = !hovered
radius: root.radius
}
} }

View File

@@ -0,0 +1,19 @@
import Quickshell // for PanelWindow
import QtQuick // for Text
import QtQuick.Shapes
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Widgets
import Quickshell.Wayland
import Quickshell.Hyprland
Rectangle {
property real reserve: height
id: botRect
y: parent.height - height
color: Pywal.special.background
implicitHeight: 10
implicitWidth: parent.width
}

View File

@@ -13,6 +13,10 @@ Rectangle {
id: leftRect id: leftRect
property real reserve: width
required property QsWindow window
implicitHeight: parent.height implicitHeight: parent.height
implicitWidth: 40 implicitWidth: 40
@@ -34,5 +38,25 @@ Rectangle {
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
} }
IdleInhibitor {
x: parent.width / 2 - width / 2
y: battery.y - height - 20
id: idleInhibitor
}
Battery {
id: battery
x: parent.width / 2 - width / 2
y: tray.y - height - 20
}
Tray {
id: tray
x: parent.width / 2 - width / 2
y: leftRect.y + leftRect.height - height - 100
window: leftRect.window
popupOffset: x + leftRect.width
}
} }

View File

@@ -0,0 +1,19 @@
import Quickshell // for PanelWindow
import QtQuick // for Text
import QtQuick.Shapes
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Widgets
import Quickshell.Wayland
import Quickshell.Hyprland
Rectangle {
property real reserve: width
id: rightRect
x: parent.width - width
color: Pywal.special.background
implicitWidth: 10
implicitHeight: parent.height
}

View File

@@ -8,63 +8,66 @@ import Quickshell.Widgets
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Hyprland import Quickshell.Hyprland
VFlyout { ColumnLayout {
spacing: -1
id: root
WrapperMouseArea {
id: topRectArea
Rectangle {
id: topRect
color: Pywal.special.background
anchors.fill: parent
}
implicitHeight: 10
implicitWidth: parent.width
hoverEnabled: true
onEntered: {
root.showDash = true
}
}
property bool showDash: false
required property real radius
property real cornerY: topRectArea.height - 1
//property real reserve: midFO.visible ? root.height : topRectArea.height
property real reserve: topRectArea.height
property QsWindow window
property Item topRectArea: topRectArea
property Item midFO: midFO
VFlyout {
id: midFO id: midFO
radius: root.radius
Layout.alignment: Qt.AlignHCenter
color: Pywal.special.background color: Pywal.special.background
visible: set visible: true
property bool set: true
property QsWindow window
property real radius
item: mid item: mid
onEntered: visible = false
RowLayout { RowLayout {
id: mid id: mid
Notifications {
id: notifications
window: midFO.window
}
Battery {
window: midFO.window
popupOffset: x + midFO.x
}
Tray {
window: midFO.window
popupOffset: x + midFO.x
}
Clock { Clock {
id: clock id: clock
} }
IdleInhibitor {
id: idleInhibitor
}
Bluetooth {
window: midFO.window
popupOffset: x + midFO.x
}
Volume {
window: midFO.window
popupOffset: x + midFO.x
}
Power {
id: power
window: midFO.window
popupOffset: x + midFO.x
}
} }
radius: radius
} }
}

View File

@@ -8,88 +8,27 @@ import Quickshell.Hyprland
import Quickshell.Services.UPower import Quickshell.Services.UPower
ClippingWrapperRectangle { ClippingWrapperRectangle {
radius: 5
width: 100; height: 30
color: "red"
Button {
id: button
text: if(UPower.onBattery) {
"󰁹 " + Math.floor(UPower.displayDevice.percentage * 100) + "%"
} else {
"󰂄 " + Math.floor(UPower.displayDevice.percentage * 100) + "%"
}
font.pointSize: 12
implicitHeight: parent.height
//icon.color: "red"
//icon.source: "/nix/store/c4dcn4vl0v5njv4d587sazrad1xgyd9h-rose-pine-icon-theme-unstable-2022-09-01/share/icons/rose-pine/symbolic/devices/battery-symbolic.svg"
onClicked: {
menu.visible = true
grab.active = true
}
}
required property var window radius: 3
required property real popupOffset
id: root
PopupWindow { color: Pywal.colors.color2
id: menu
anchor.window: window implicitWidth: 30
anchor.rect.x: popupOffset
anchor.rect.y: 50
implicitWidth: 250
implicitHeight: 150
visible: false
color: "transparent" implicitHeight: text.contentWidth + text.padding
ClippingWrapperRectangle {
radius: 5
implicitHeight: parent.height - 20 Text {
implicitWidth: parent.width id: text
text: UPower.displayDevice.percentage * 100 + "%"
ColumnLayout {
spacing: 0 padding: 10
Button { horizontalAlignment: Text.AlignHCenter
Layout.topMargin: 5 verticalAlignment: Text.AlignVCenter
x: (parent.width - width) / 2
implicitWidth: parent.width - 10
implicitHeight: parent.height / 5 - parent.spacing
text: 'performance' font.pointSize: 14
onClicked: PowerProfiles.profile = PowerProfile.Performance
visible: PowerProfiles.hasPerformanceProfile
}
Button {
Layout.topMargin: 5
x: (parent.width - width) / 2
implicitWidth: parent.width - 10
implicitHeight: parent.height / 5 - parent.spacing
text: 'balanced' color: Pywal.special.foreground
onClicked: PowerProfiles.profile = PowerProfile.Balanced rotation: -90
}
Button {
Layout.topMargin: 5
x: (parent.width - width) / 2
implicitWidth: parent.width - 10
implicitHeight: parent.height / 5 - parent.spacing
text: 'power saver'
onClicked: PowerProfiles.profile = PowerProfile.PowerSaver
}
}
}
HyprlandFocusGrab {
id: grab
windows: [ menu ]
onCleared: menu.visible = false
}
} }
} }

View File

@@ -7,135 +7,94 @@ import Quickshell.Widgets
import Quickshell.Hyprland import Quickshell.Hyprland
import Quickshell.Bluetooth import Quickshell.Bluetooth
ClippingWrapperRectangle { ColumnLayout {
radius: 5
implicitWidth: 30; implicitHeight: 30
Button {
id: button
text: ""
font.pointSize: 16
onClicked: {
menu.visible = true
grab.active = true
}
implicitHeight: parent.height
}
required property PanelWindow window anchors.fill: parent
required property real popupOffset
id: root id: root
PopupWindow { spacing: 0
id: menu
anchor.window: window ClippingWrapperRectangle {
anchor.rect.x: popupOffset - width radius: 5
anchor.rect.y: 50 implicitWidth: parent.width - 2 * Layout.margins
implicitWidth: 250 implicitHeight: 30
implicitHeight: 150 Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
visible: false Layout.margins: 5
color: Pywal.colors.color11
color: "transparent" RowLayout {
Text {
ClippingWrapperRectangle { text: 'Bluetooth'
radius: 5 Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.margins: 5
color: Pywal.colors.color0
}
implicitHeight: parent.height - 20 Switch {
implicitWidth: parent.width Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
//Layout.margins: 5
ColumnLayout { checked: Bluetooth.defaultAdapter.enabled
onClicked: {
Bluetooth.defaultAdapter.enabled = checked
scroll.visible = checked
}
}
}
spacing: 0 }
ScrollView {
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Layout.margins: 5
implicitWidth: parent.width - 4 * Layout.margins
implicitHeight: parent.height / 2
id: scroll
ColumnLayout {
spacing: 0
Repeater {
id: rep
model: Bluetooth.devices.values
ClippingWrapperRectangle { ClippingWrapperRectangle {
radius: 5 radius: 5
implicitWidth: parent.width - 2 * Layout.margins color: Pywal.colors.color4
implicitHeight: 30
implicitWidth: root.width - 3 * scroll.x
implicitHeight: 40
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Layout.margins: 5 Layout.margins: 5
color: "#ff3333aa"
RowLayout { RowLayout {
Text { Text {
text: 'Bluetooth'
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.margins: 5 Layout.margins: 5
text: rep.model[index].name
color: Pywal.colors.color0
} }
Switch { Button {
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
//Layout.margins: 5 Layout.rightMargin: 5
checked: Bluetooth.defaultAdapter.enabled text: 'Connect'
onClicked: Bluetooth.defaultAdapter.enabled = checked
onClicked: rep.model[index].connected = !rep.model[index].connected
} }
} }
}
ScrollView {
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Layout.margins: 5
implicitWidth: parent.width - 4 * Layout.margins
implicitHeight: menu.height / 2
id: scroll
ColumnLayout {
spacing: 0
Repeater {
id: rep
model: Bluetooth.devices.values
ClippingWrapperRectangle {
radius: 5
color: "#ff3333aa"
implicitWidth: menu.width - 3 * scroll.x
implicitHeight: 40
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Layout.margins: 5
RowLayout {
Text {
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.margins: 5
text: rep.model[index].name
}
Button {
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.rightMargin: 5
text: 'Connect'
onClicked: rep.model[index].connected = !rep.model[index].connected
}
}
}
}
}
} }
} }
} }
HyprlandFocusGrab {
id: grab
windows: [ menu ]
onCleared: menu.visible = false
}
} }
} }

View File

@@ -11,7 +11,7 @@ WrapperMouseArea {
ClippingWrapperRectangle { ClippingWrapperRectangle {
id: rect id: rect
color: Pywal.colors.color12 color: Pywal.colors.color12
radius: 5 radius: 3
anchors.fill: parent anchors.fill: parent
Text { Text {
id: t id: t

View File

@@ -0,0 +1,245 @@
import Quickshell // for PanelWindow
import QtQuick // for Text
import QtQuick.Shapes
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Widgets
import Quickshell.Wayland
import Quickshell.Hyprland
import Quickshell.Services.Notifications
Item {
implicitWidth: 700
implicitHeight: 450
required property real radius
property bool hovered: false
id: root
visible: false
property int selected: 0
VFlyout {
visible: root.visible
color: Pywal.special.background
radius: root.radius
item: main
WrapperMouseArea {
ClippingRectangle {
//anchors.fill: parent
color: Pywal.special.background
id: main
radius: root.radius
implicitWidth: root.width
implicitHeight: root.height
Item {
implicitWidth: root.width - 4 * lay.spacing
implicitHeight: root.height - 4 * lay.spacing
x: 2 * lay.spacing
y: 2 * lay.spacing
RowLayout {
id: lay
spacing: 2
anchors.fill: parent
ColumnLayout {
id: tabs
Layout.alignment: Qt.AlignTop
Repeater {
id: rep
model: 9
WrapperMouseArea {
ClippingRectangle {
//Layout.alignment: Qt.AlignTop
implicitWidth: 40
implicitHeight: 40
radius: root.radius
color: index == selected ? Pywal.colors.color13 : Pywal.colors.color4
//Launcher { anchors.centerIn: parent }
Text {
font.pointSize: 14
text: switch(index) {
case 0:
return " ";
case 1:
return "󰍹 ";
case 2:
return "󰤨 ";
case 3:
return "󰂯";
case 4:
return " ";
case 5:
return " ";
case 6:
return "󰌳 ";
case 7:
return " ";
case 8:
return "󰁹";
default:
return "";
}
anchors.centerIn: parent
color: Pywal.colors.color0
}
}
onEntered: child.color = Qt.binding(() => index == selected ? Pywal.colors.color13 : Pywal.colors.color12)
onExited: child.color = Qt.binding(() => index == selected ? Pywal.colors.color13 : Pywal.colors.color4)
onClicked: {
selected = index
child.color = Qt.binding(() => index == selected ? Pywal.colors.color13 : Pywal.colors.color4)
}
hoverEnabled: true
}
}
}
ClippingRectangle {
id: content
Layout.alignment: Qt.AlignHCenter
implicitWidth: parent.width - tabs.width - 2 * parent.spacing - rTabs.width - 2 * parent.spacing
implicitHeight: parent.height
radius: root.radius
color: Pywal.colors.color1
NotificationServer {
id: nserver
persistenceSupported: true
imageSupported: true
actionsSupported: true
bodyImagesSupported: true
bodySupported: true
bodyHyperlinksSupported: true
inlineReplySupported: true
actionIconsSupported: true
onNotification: (n) => {
n.tracked = !n.transient
}
}
Loader {
anchors.fill: parent
readonly property Component launcher: Launcher {}
readonly property Component notifs: Notifications { server: nserver }
readonly property Component bt: Bluetooth {}
readonly property Component vol: Volume {}
readonly property Component bat: PowerMode {}
readonly property Component mon: Launcher {}
readonly property Component net: Launcher {}
readonly property Component mus: Launcher {}
readonly property Component clk: Clock {}
readonly property Component wal: Launcher {}
sourceComponent: switch(selected) {
case 0:
return wal;
case 1:
return mon;
case 2:
return net;
case 3:
return bt;
case 4:
return vol;
case 5:
return notifs;
case 6:
return mus;
case 7:
return wal;
case 8:
return bat;
default:
return launcher;
}
}
}
ColumnLayout {
id: rTabs
Layout.alignment: Qt.AlignBottom
Repeater {
id: rRep
model: 9
WrapperMouseArea {
ClippingRectangle {
//Layout.alignment: Qt.AlignTop
implicitWidth: 40
implicitHeight: 40
radius: root.radius
color: index + 9 == selected ? Pywal.colors.color13 : Pywal.colors.color4
//Launcher { anchors.centerIn: parent }
Text {
font.pointSize: 14
text: switch(index) {
case 0:
return " ";
case 1:
return " ";
case 2:
return " ";
case 3:
return "";
case 4:
return " ";
case 5:
return " ";
case 6:
return "󰊗 ";
case 7:
return " ";
case 8:
return " ";
default:
return "";
}
anchors.centerIn: parent
color: Pywal.colors.color0
}
}
onEntered: child.color = Qt.binding(() => index + 9 == selected ? Pywal.colors.color13 : Pywal.colors.color12)
onExited: child.color = Qt.binding(() => index + 9 == selected ? Pywal.colors.color13 : Pywal.colors.color4)
onClicked: {
selected = index + 9
child.color = Qt.binding(() => index + 9 == selected ? Pywal.colors.color13 : Pywal.colors.color12)
}
hoverEnabled: true
}
}
}
}
}
}
hoverEnabled: true
onEntered: hovered = true
onExited: {
root.visible = false
hovered = false
}
}
}
}

View File

@@ -9,12 +9,19 @@ ClippingWrapperRectangle {
property real interval: 100 property real interval: 100
id: root id: root
radius: 5 radius: 3
color: Pywal.colors.color1
implicitWidth: 30; height: 30 implicitWidth: 30; height: 30
Button { Button {
id: button id: button
text: "󰒳 " text: "󰒳 "
font.pointSize: 16 font.pointSize: 16
background: Rectangle {
color: Pywal.colors.color9
}
Process { Process {
id: idlent id: idlent
running: true running: true

View File

@@ -6,7 +6,7 @@ import Quickshell.Widgets
WrapperMouseArea { WrapperMouseArea {
ClippingWrapperRectangle { ClippingWrapperRectangle {
radius: 5 radius: 3
implicitWidth: 30; implicitHeight: 30 implicitWidth: 30; implicitHeight: 30
Text { Text {
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
@@ -29,7 +29,7 @@ WrapperMouseArea {
Process { Process {
id: launcher id: launcher
running: false running: false
command: ["rofi", "-show", "drun"] command: ["rofi", "-show", "drun", "-show-icons" ]
} }
onClicked: launcher.running = true onClicked: launcher.running = true

View File

@@ -15,7 +15,7 @@ ClippingWrapperRectangle {
implicitWidth: parent.width - 2 * Layout.margins implicitWidth: parent.width - 2 * Layout.margins
implicitHeight: 100 implicitHeight: 100
color: Pywal.colors.color2 color: Pywal.colors.color4
required property Notification src required property Notification src

View File

@@ -7,137 +7,69 @@ import Quickshell.Io
import Quickshell.Widgets import Quickshell.Widgets
import Quickshell.Hyprland import Quickshell.Hyprland
Item {
width: 50 ColumnLayout {
height: 30 anchors.fill: parent
id: lay
spacing: 10
required property NotificationServer server
ClippingWrapperRectangle { ClippingWrapperRectangle {
id: barbutton color: Pywal.colors.color11
radius: 5 radius: 5
anchors.fill: parent Layout.margins: 5
Button { Layout.alignment: Qt.AlignVCenter | Qt.AlignTop
id: button implicitWidth: lay.width - 2 * Layout.margins
text: "󰂚"
font.pointSize: 16
onClicked: {
menu.visible = true RowLayout {
grab.active = true width: parent.width
Text {
color: Pywal.colors.color0
Layout.margins: 5
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
text: 'Notifications'
} }
implicitHeight: parent.height Button {
} Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
} Layout.margins: 5
implicitWidth: 20
implicitHeight: 20
NotificationServer { text: 'x'
id: server
persistenceSupported: true
imageSupported: true
actionsSupported: true
bodyImagesSupported: true
bodySupported: true
bodyHyperlinksSupported: true
inlineReplySupported: true
actionIconsSupported: true
onNotification: (n) => { onClicked: {
n.tracked = !n.transient while(server.trackedNotifications.values.length > 0) {
} server.trackedNotifications.values[0].dismiss()
}
required property PanelWindow window
id: root
PopupWindow {
id: menu
anchor.window: window
anchor.rect.x: window.width - width
anchor.rect.y: 50
implicitWidth: 400
implicitHeight: 1080 - anchor.rect.y
visible: false
color: "transparent"
ClippingWrapperRectangle {
radius: 5
color: Pywal.special.background
implicitHeight: parent.height - 20
implicitWidth: parent.width
ColumnLayout {
id: lay
spacing: 10
ClippingWrapperRectangle {
color: Pywal.colors.color2
radius: 5
Layout.margins: 5
Layout.alignment: Qt.AlignVCenter | Qt.AlignTop
implicitWidth: menu.width - 2 * Layout.margins
RowLayout {
width: parent.width
Text {
color: Pywal.colors.color0
Layout.margins: 5
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
text: 'Notifications'
}
Button {
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.margins: 5
implicitWidth: 20
implicitHeight: 20
text: 'x'
onClicked: {
while(server.trackedNotifications.values.length > 0) {
server.trackedNotifications.values[0].dismiss()
}
}
}
} }
} }
ColumnLayout {
Layout.alignment: Qt.AlignVCenter | Qt.AlignTop
Repeater {
id: rep
model: server.trackedNotifications.values
Notif {
required property int index
src: rep.model[index]
}
onItemAdded: (idx, it) => {
button.text = '󱅫 ' + rep.count
}
onItemRemoved: (idx, it) => {
button.text = (rep.count - 1) <= 0 ? "󰂚" : '󱅫 ' + (rep.count - 1)
}
}
}
} }
} }
}
HyprlandFocusGrab { ColumnLayout {
id: grab width: parent.width
windows: [ menu ] Layout.alignment: Qt.AlignVCenter | Qt.AlignTop
onCleared: menu.visible = false Repeater {
id: rep
model: server.trackedNotifications.values
Notif {
required property int index
src: rep.model[index]
}
onItemAdded: (idx, it) => {
//button.text = '󱅫 ' + rep.count
}
onItemRemoved: (idx, it) => {
//button.text = (rep.count - 1) <= 0 ? "󰂚" : '󱅫 ' + (rep.count - 1)
}
} }
} }
} }

View File

@@ -27,31 +27,31 @@ Singleton {
property string alpha: "100" property string alpha: "100"
property JsonObject special: JsonObject { property JsonObject special: JsonObject {
property string background: "white" property string background: "transparent"
property string foreground: "white" property string foreground: "transparent"
property string cursor: "white" property string cursor: "transparent"
} }
property JsonObject colors: JsonObject { property JsonObject colors: JsonObject {
property string color0: "white" property string color0: "transparent"
property string color1: "white" property string color1: "transparent"
property string color2: "white" property string color2: "transparent"
property string color3: "white" property string color3: "transparent"
property string color4: "white" property string color4: "transparent"
property string color5: "white" property string color5: "transparent"
property string color6: "white" property string color6: "transparent"
property string color7: "white" property string color7: "transparent"
property string color8: "white" property string color8: "transparent"
property string color9: "white" property string color9: "transparent"
property string color10: "white" property string color10: "transparent"
property string color11: "white" property string color11: "transparent"
property string color12: "white" property string color12: "transparent"
property string color13: "white" property string color13: "transparent"
property string color14: "white" property string color14: "transparent"
property string color15: "white" property string color15: "transparent"
} }
} }
} }

View File

@@ -5,8 +5,8 @@ import Quickshell.Services.SystemTray
import Quickshell.Widgets import Quickshell.Widgets
Item { Item {
implicitWidth: 10 + rep.count * (2 * lay.spacing + 20) implicitHeight: 10 + rep.count * (2 * lay.spacing + 20)
height: 30 width: 30
visible: SystemTray.items.values.length != 0 visible: SystemTray.items.values.length != 0
id: root id: root
@@ -14,9 +14,10 @@ Item {
required property real popupOffset required property real popupOffset
ClippingWrapperRectangle { ClippingWrapperRectangle {
radius: 5 radius: 3
anchors.fill: parent anchors.fill: parent
RowLayout { color: Pywal.colors.color4
ColumnLayout {
id: lay id: lay
spacing: 4 spacing: 4
Repeater { Repeater {
@@ -25,9 +26,12 @@ Item {
model: SystemTray.items model: SystemTray.items
ClippingWrapperRectangle { ClippingWrapperRectangle {
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
radius: 10 radius: 3
implicitWidth: 20 implicitWidth: 20
implicitHeight: 20 implicitHeight: 20
color: Pywal.colors.color1
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
@@ -49,7 +53,7 @@ Item {
if(mouse.button == Qt.LeftButton) { if(mouse.button == Qt.LeftButton) {
SystemTray.items.values[index].activate() SystemTray.items.values[index].activate()
} else if(mouse.button == Qt.RightButton) { } else if(mouse.button == Qt.RightButton) {
SystemTray.items.values[index].display(root.window, popupOffset, 40) SystemTray.items.values[index].display(root.window, popupOffset, root.y - 100)
} }
} }
} }

View File

@@ -7,7 +7,7 @@ import Quickshell.Widgets
MouseArea { MouseArea {
id: root id: root
property real radius: 10 required property real radius
property real pad: 5 property real pad: 5
property color color property color color
@@ -34,51 +34,51 @@ MouseArea {
strokeColor: root.color strokeColor: root.color
fillColor: root.color fillColor: root.color
startX: -radius - pad; startY: 0 startX: -root.radius - pad; startY: 0
PathArc { PathArc {
radiusX: radius radiusX: root.radius
radiusY: radius radiusY: root.radius
relativeX: radius relativeX: root.radius
relativeY: radius relativeY: root.radius
} }
PathLine { relativeX: 0; relativeY: 2 * pad + item.height - 2 * radius } PathLine { relativeX: 0; relativeY: 2 * pad + item.height - 2 * root.radius }
PathArc { PathArc {
radiusX: radius radiusX: root.radius
radiusY: radius radiusY: root.radius
direction: PathArc.Counterclockwise direction: PathArc.Counterclockwise
relativeX: radius relativeX: root.radius
relativeY: radius relativeY: root.radius
} }
PathLine { x: item.width + pad - radius; relativeY: 0 } PathLine { x: item.width + pad - root.radius; relativeY: 0 }
PathArc { PathArc {
radiusX: radius radiusX: root.radius
radiusY: radius radiusY: root.radius
direction: PathArc.Counterclockwise direction: PathArc.Counterclockwise
relativeX: radius relativeX: root.radius
relativeY: -radius relativeY: -root.radius
} }
PathLine { relativeX: 0; relativeY: -item.height + 2 * radius - 2 * pad } PathLine { relativeX: 0; relativeY: -item.height + 2 * root.radius - 2 * pad }
PathArc { PathArc {
radiusX: radius radiusX: root.radius
radiusY: radius radiusY: root.radius
relativeX: radius relativeX: root.radius
relativeY: -radius relativeY: -root.radius
} }
PathLine { x: -radius - pad; y: 0 } PathLine { x: -root.radius - pad; y: 0 }
} }
} }
} }

View File

@@ -7,101 +7,118 @@ import Quickshell.Widgets
import Quickshell.Hyprland import Quickshell.Hyprland
import Quickshell.Services.Pipewire import Quickshell.Services.Pipewire
ClippingWrapperRectangle {
radius: 5
width: 100; height: 30
Button {
id: button
text: (Pipewire.defaultAudioSink?.audio?.muted ? " " : " ") + Math.floor(Pipewire.defaultAudioSink?.audio?.volume * 100) + "%"
font.pointSize: 12
implicitHeight: parent.height
PwObjectTracker {
objects: [ Pipewire.defaultAudioSink ]
}
onClicked: { ScrollView {
menu.visible = true anchors.fill: parent
grab.active = true ColumnLayout {
} anchors.fill: parent
} spacing: 0
required property var window
required property real popupOffset
id: root
PopupWindow {
id: menu
anchor.window: window
anchor.rect.x: popupOffset
anchor.rect.y: 50
implicitWidth: 250
implicitHeight: 150
visible: false
color: "transparent"
ClippingWrapperRectangle { ClippingWrapperRectangle {
color: Pywal.colors.color11
radius: 5 radius: 5
Layout.margins: 5
Layout.alignment: Qt.AlignVCenter | Qt.AlignTop
implicitWidth: parent.width - 2 * Layout.margins
implicitHeight: parent.height - 20 RowLayout {
implicitWidth: parent.width width: parent.width
Text {
color: Pywal.colors.color0
Layout.margins: 5
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
text: 'Output'
}
ScrollView { Slider {
ColumnLayout { from: 0
to: 2
spacing: 0 orientation: Qt.Horizontal
Text { implicitWidth: 500
text: 'Output Devices'
}
ColumnLayout { value: Pipewire.defaultAudioSink.audio.volume
Repeater {
id: outputs
model: {
Pipewire.nodes.values.filter(n => n.isSink && n.audio && n.nickname != "")
}
Button {
text: outputs.model[index].nickname
onClicked: Pipewire.preferredDefaultAudioSink = outputs.model[index]
}
}
}
Text {
text: 'Input Devices'
}
ColumnLayout {
Repeater {
id: inputs
model: {
Pipewire.nodes.values.filter(n => !n.isSink && n.audio && n.nickname != "")
}
Button {
text: inputs.model[index].nickname
onClicked: Pipewire.preferredDefaultAudioSource = inputs.model[index]
}
}
}
onValueChanged: Pipewire.defaultAudioSink.audio.volume = value
} }
} }
} }
HyprlandFocusGrab { ColumnLayout {
id: grab Repeater {
windows: [ menu ] id: outputs
onCleared: menu.visible = false
model: {
Pipewire.nodes.values.filter(n => n.isSink && n.audio && n.nickname != "")
}
Button {
text: outputs.model[index].nickname
onClicked: {
Pipewire.preferredDefaultAudioSink = outputs.model[index]
}
PwObjectTracker {
objects: [ outputs.model[index] ]
}
}
}
} }
ClippingWrapperRectangle {
color: Pywal.colors.color11
radius: 5
Layout.margins: 5
Layout.alignment: Qt.AlignVCenter | Qt.AlignTop
implicitWidth: parent.width - 2 * Layout.margins
RowLayout {
width: parent.width
Text {
color: Pywal.colors.color0
Layout.margins: 5
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
text: 'Input'
}
Slider {
from: 0
to: 2
visible: false
orientation: Qt.Horizontal
implicitWidth: 500
value: Pipewire.defaultAudioSource.audio.volume
onValueChanged: Pipewire.defaultAudioSource.audio.volume = value
}
}
}
ColumnLayout {
Repeater {
id: inputs
model: {
Pipewire.nodes.values.filter(n => !n.isSink && n.audio && n.nickname != "")
}
Button {
text: inputs.model[index].nickname
onClicked: {
Pipewire.preferredDefaultAudioSource = inputs.model[index]
}
}
}
}
} }
} }