brightess and volume control
This commit is contained in:
1
Lock.qml
1
Lock.qml
@@ -15,7 +15,6 @@ WlSessionLock {
|
|||||||
id: surface
|
id: surface
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
Component.onCompleted: console.log("done")
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: content
|
id: content
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|||||||
@@ -10,14 +10,13 @@ Column {
|
|||||||
width: Math.max(childrenRect.width, 300)
|
width: Math.max(childrenRect.width, 300)
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
anchors.topMargin: 6
|
anchors.topMargin: 6
|
||||||
TapHandler {onTapped: console.log(width)}
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
radius: 12
|
radius: 12
|
||||||
height: 40
|
height: 40
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.margins: 6
|
anchors.margins: 6
|
||||||
color: "#181818"
|
color: "#111"
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: "white"
|
color: "white"
|
||||||
width: (parent.width - anchors.margins * 2)/3
|
width: (parent.width - anchors.margins * 2)/3
|
||||||
@@ -116,7 +115,7 @@ Column {
|
|||||||
id: card
|
id: card
|
||||||
required property var data
|
required property var data
|
||||||
required property var label
|
required property var label
|
||||||
color: "#181818"
|
color: "#111"
|
||||||
height: 60
|
height: 60
|
||||||
width: 100
|
width: 100
|
||||||
radius: 12
|
radius: 12
|
||||||
|
|||||||
154
Panes/Brightness.qml
Normal file
154
Panes/Brightness.qml
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import QtQuick
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets as Widgets
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
margins: 6
|
||||||
|
}
|
||||||
|
width: 300
|
||||||
|
height: childrenRect.height + anchors.margins * 2
|
||||||
|
spacing: 6
|
||||||
|
Item {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
margins: 12
|
||||||
|
}
|
||||||
|
width: childrenRect.width
|
||||||
|
height: children[1].height
|
||||||
|
Image {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
verticalCenterOffset: 1
|
||||||
|
}
|
||||||
|
width: 24
|
||||||
|
height: width
|
||||||
|
sourceSize {width: width; height: height}
|
||||||
|
source: Quickshell.iconPath("brightnesssettings")
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
left: parent.children[0].right
|
||||||
|
leftMargin: 6
|
||||||
|
}
|
||||||
|
font.pixelSize: 16
|
||||||
|
color: "white"
|
||||||
|
text: "Laptop display"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Widgets.Slider {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
margins: 12
|
||||||
|
}
|
||||||
|
height: 24
|
||||||
|
value: Brightness.monitors[0].value / Brightness.monitors[0].max
|
||||||
|
onMoved: {
|
||||||
|
Brightness.monitors[0].set(Math.round(Brightness.monitors[0].max * position))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
component ToggleButton: Item {
|
||||||
|
id: toggleButton
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
margins: 12
|
||||||
|
}
|
||||||
|
height: children[0].height
|
||||||
|
property bool active: false
|
||||||
|
property var text
|
||||||
|
Text {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
height: 24
|
||||||
|
font.pixelSize: 14
|
||||||
|
color: "white"
|
||||||
|
text: toggleButton.text
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
anchors {
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
rightMargin: (24 - width)/2 + (36-24)/2
|
||||||
|
}
|
||||||
|
radius: height/2
|
||||||
|
color: parent.active ? "white" : "#00ffffff"
|
||||||
|
height: 10
|
||||||
|
width: parent.active ? 36 : 24
|
||||||
|
border.width: parent.active ? height/2 : 2
|
||||||
|
border.color: "white"
|
||||||
|
Behavior on width {NumberAnimation { duration: 150; easing.type: Easing.OutCubic }}
|
||||||
|
Behavior on border.width {NumberAnimation { duration: 150; easing.type: Easing.OutCubic }}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ToggleButton {
|
||||||
|
id: sunsetToggle
|
||||||
|
text: "Night Light"
|
||||||
|
Process {
|
||||||
|
running: true
|
||||||
|
command: [ "pgrep", "-x", "sunset" ]
|
||||||
|
onExited: (exitCode) => {if (!exitCode) sunsetToggle.active = true}
|
||||||
|
}
|
||||||
|
TapHandler {
|
||||||
|
property var idleProc: Process {command: ["hyprsunset"]}
|
||||||
|
property var idleKill: Process {command: ["pkill", "-x", "hyprsunset"]}
|
||||||
|
onTapped: {
|
||||||
|
parent.active = !parent.active
|
||||||
|
if (parent.active)
|
||||||
|
idleProc.startDetached()
|
||||||
|
else
|
||||||
|
idleKill.startDetached()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ToggleButton {
|
||||||
|
id: idleToggle
|
||||||
|
text: "Idle Timer"
|
||||||
|
Process {
|
||||||
|
running: true
|
||||||
|
command: [ "pgrep", "-x", "hypridle" ]
|
||||||
|
onExited: (exitCode) => {if (!exitCode) idleToggle.active = true}
|
||||||
|
}
|
||||||
|
TapHandler {
|
||||||
|
property var idleProc: Process {command: ["hypridle"]}
|
||||||
|
property var idleKill: Process {command: ["pkill", "-x", "hypridle"]}
|
||||||
|
onTapped: {
|
||||||
|
parent.active = !parent.active
|
||||||
|
if (parent.active)
|
||||||
|
idleProc.startDetached()
|
||||||
|
else
|
||||||
|
idleKill.startDetached()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ToggleButton {
|
||||||
|
id: dpmsToggle
|
||||||
|
text: "Screen on"
|
||||||
|
active: true
|
||||||
|
TapHandler {
|
||||||
|
property var resetTimer: Timer {
|
||||||
|
interval: 500
|
||||||
|
running: false
|
||||||
|
repeat: false
|
||||||
|
onTriggered: dpmsToggle.active = true
|
||||||
|
}
|
||||||
|
onTapped: {
|
||||||
|
dpmsToggle.active = false;
|
||||||
|
Hyprland.dispatch("dpms off");
|
||||||
|
resetTimer.start();
|
||||||
|
root.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,7 +38,7 @@ Item {
|
|||||||
margins: 6
|
margins: 6
|
||||||
}
|
}
|
||||||
height: 48
|
height: 48
|
||||||
color: "#181818"
|
color: "#111"
|
||||||
radius: 10
|
radius: 10
|
||||||
TextInput {
|
TextInput {
|
||||||
id: input
|
id: input
|
||||||
@@ -95,7 +95,6 @@ Item {
|
|||||||
property: "x"
|
property: "x"
|
||||||
duration: 300
|
duration: 300
|
||||||
easing.type: Easing.OutQuint
|
easing.type: Easing.OutQuint
|
||||||
onStarted: console.log("displaced")
|
|
||||||
}
|
}
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
property: "opacity"
|
property: "opacity"
|
||||||
@@ -146,7 +145,7 @@ Item {
|
|||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
width: 64
|
width: 64
|
||||||
height: width
|
height: width
|
||||||
source: Quickshell.iconPath(modelData.icon)
|
source: Quickshell.iconPath(modelData.icon, "application-default")
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Item {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
width: 400
|
width: 400
|
||||||
height: 300
|
height: 300
|
||||||
color: "#181818"
|
color: "#111"
|
||||||
radius: 10
|
radius: 10
|
||||||
Column {
|
Column {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -47,7 +47,6 @@ Item {
|
|||||||
anchors.rightMargin: anchors.leftMargin
|
anchors.rightMargin: anchors.leftMargin
|
||||||
clip: true
|
clip: true
|
||||||
spacing: 4
|
spacing: 4
|
||||||
interactive: background.index === 3
|
|
||||||
|
|
||||||
add: Transition {NumberAnimation {
|
add: Transition {NumberAnimation {
|
||||||
property: "opacity"
|
property: "opacity"
|
||||||
@@ -69,7 +68,7 @@ Item {
|
|||||||
header: Item {height: 4; width: 1}
|
header: Item {height: 4; width: 1}
|
||||||
model: Array.from(notifServer.trackedNotifications.values)
|
model: Array.from(notifServer.trackedNotifications.values)
|
||||||
delegate: Widgets.Notification {
|
delegate: Widgets.Notification {
|
||||||
color: "#222"
|
color: "#181818"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,25 +97,32 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Column {
|
Column {
|
||||||
anchors.centerIn: parent
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
margins: 6
|
||||||
|
}
|
||||||
opacity: Mpris.players.values.length
|
opacity: Mpris.players.values.length
|
||||||
Behavior on opacity {NumberAnimation {duration: 150}}
|
Behavior on opacity {NumberAnimation {duration: 150}}
|
||||||
Shape {
|
Shape {
|
||||||
|
id: progressShape
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
width: 180
|
width: 160
|
||||||
height: 180
|
height: width
|
||||||
|
property var strokeWidth: 6
|
||||||
preferredRendererType: Shape.CurveRenderer
|
preferredRendererType: Shape.CurveRenderer
|
||||||
ShapePath {
|
ShapePath {
|
||||||
capStyle: ShapePath.RoundCap
|
capStyle: ShapePath.RoundCap
|
||||||
strokeColor: "#444"
|
strokeColor: "#444"
|
||||||
fillColor: "transparent"
|
fillColor: "transparent"
|
||||||
strokeWidth: 4
|
strokeWidth: progressShape.strokeWidth
|
||||||
PathAngleArc {
|
PathAngleArc {
|
||||||
moveToStart: true
|
moveToStart: true
|
||||||
radiusX: 90 - 6
|
radiusX: (progressShape.width-progressShape.strokeWidth)/2
|
||||||
radiusY: 90 - 6
|
radiusY: (progressShape.height-progressShape.strokeWidth)/2
|
||||||
centerX: 90
|
centerX: progressShape.width/2
|
||||||
centerY: 90
|
centerY: progressShape.height/2
|
||||||
startAngle: 90 + 20
|
startAngle: 90 + 20
|
||||||
sweepAngle: 360 - 40
|
sweepAngle: 360 - 40
|
||||||
}
|
}
|
||||||
@@ -125,13 +131,13 @@ Item {
|
|||||||
capStyle: ShapePath.RoundCap
|
capStyle: ShapePath.RoundCap
|
||||||
strokeColor: "white"
|
strokeColor: "white"
|
||||||
fillColor: "transparent"
|
fillColor: "transparent"
|
||||||
strokeWidth: 4
|
strokeWidth: 6
|
||||||
PathAngleArc {
|
PathAngleArc {
|
||||||
moveToStart: true
|
moveToStart: true
|
||||||
radiusX: 90 - 6
|
radiusX: (progressShape.width-progressShape.strokeWidth)/2
|
||||||
radiusY: 90 - 6
|
radiusY: (progressShape.height-progressShape.strokeWidth)/2
|
||||||
centerX: 90
|
centerX: progressShape.width/2
|
||||||
centerY: 90
|
centerY: progressShape.height/2
|
||||||
startAngle: 90 + 20
|
startAngle: 90 + 20
|
||||||
sweepAngle: (player.modelData?.position/player.modelData.length) * (360 - 40)
|
sweepAngle: (player.modelData?.position/player.modelData.length) * (360 - 40)
|
||||||
}
|
}
|
||||||
@@ -140,9 +146,12 @@ Item {
|
|||||||
color: "transparent"
|
color: "transparent"
|
||||||
radius: height/2
|
radius: height/2
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 12
|
anchors.margins: progressShape.strokeWidth*2
|
||||||
Image {
|
Image {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
mipmap: true
|
||||||
|
smooth: true
|
||||||
source: player.modelData?.trackArtUrl ?? source
|
source: player.modelData?.trackArtUrl ?? source
|
||||||
}
|
}
|
||||||
NumberAnimation on rotation {
|
NumberAnimation on rotation {
|
||||||
@@ -159,15 +168,25 @@ Item {
|
|||||||
}
|
}
|
||||||
Item {width: 1; height: 10}
|
Item {width: 1; height: 10}
|
||||||
Text {
|
Text {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
color: "white"
|
color: "white"
|
||||||
text: player.modelData?.trackTitle ?? ""
|
text: player.modelData?.trackTitle ?? ""
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
font.pixelSize: 16
|
font.pixelSize: 16
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
color: "white"
|
color: "white"
|
||||||
text: player.modelData?.trackArtist ?? ""
|
text: player.modelData?.trackArtist ?? ""
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
}
|
}
|
||||||
Item {width: 1; height: 8}
|
Item {width: 1; height: 8}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Item {
|
|||||||
horizontalCenter: parent.horizontalCenter
|
horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
width: 350
|
width: 350
|
||||||
height: childrenRect.height
|
height: childrenRect.height + 12
|
||||||
Connections {
|
Connections {
|
||||||
target: notifServer
|
target: notifServer
|
||||||
function onNotification(notif) {
|
function onNotification(notif) {
|
||||||
@@ -22,6 +22,7 @@ Item {
|
|||||||
}
|
}
|
||||||
Widgets.Notification {
|
Widgets.Notification {
|
||||||
id: notifPopup
|
id: notifPopup
|
||||||
|
y: 6
|
||||||
anchors.margins: 6
|
anchors.margins: 6
|
||||||
modelData: notifServer.trackedNotifications.values[0] ?? undefined
|
modelData: notifServer.trackedNotifications.values[0] ?? undefined
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
@@ -32,4 +33,8 @@ Item {
|
|||||||
interval: 3000
|
interval: 3000
|
||||||
onTriggered: root.close()
|
onTriggered: root.close()
|
||||||
}
|
}
|
||||||
|
Connections {
|
||||||
|
target: background
|
||||||
|
function onIndexChanged() { timeout.stop() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ Item {
|
|||||||
bottom: parent.bottom
|
bottom: parent.bottom
|
||||||
}
|
}
|
||||||
Widgets.Battery {}
|
Widgets.Battery {}
|
||||||
|
Widgets.Volume {}
|
||||||
|
Widgets.Brightness {}
|
||||||
}
|
}
|
||||||
Widgets.Workspaces {
|
Widgets.Workspaces {
|
||||||
height: parent.height
|
height: parent.height
|
||||||
@@ -31,6 +33,7 @@ Item {
|
|||||||
right: parent.right
|
right: parent.right
|
||||||
bottom: parent.bottom
|
bottom: parent.bottom
|
||||||
}
|
}
|
||||||
|
Widgets.Uptime {}
|
||||||
Widgets.Time {}
|
Widgets.Time {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
104
Panes/Volume.qml
Normal file
104
Panes/Volume.qml
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import Quickshell.Services.Pipewire
|
||||||
|
import qs.Widgets as Widgets
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
padding: 6
|
||||||
|
height: 316
|
||||||
|
spacing: 6
|
||||||
|
|
||||||
|
PwObjectTracker {
|
||||||
|
objects: Pipewire.nodes.values.filter(node => [17, 21].includes(node.type))
|
||||||
|
}
|
||||||
|
|
||||||
|
component NodeList: ClippingRectangle {
|
||||||
|
id: nodeListRect
|
||||||
|
width: 350
|
||||||
|
color: "transparent"
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
bottom: parent.bottom
|
||||||
|
bottomMargin: 6
|
||||||
|
}
|
||||||
|
radius: 10
|
||||||
|
property var model
|
||||||
|
clip: true
|
||||||
|
ListView {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: 6
|
||||||
|
header: Item {width: 1; height: 6}
|
||||||
|
footer: header
|
||||||
|
model: nodeListRect.model
|
||||||
|
delegate: Rectangle {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
radius: 12
|
||||||
|
color: "#111"
|
||||||
|
height: children[1].height
|
||||||
|
Image {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
leftMargin: 6
|
||||||
|
}
|
||||||
|
sourceSize {width: width; height: height}
|
||||||
|
source: Quickshell.iconPath((() => {
|
||||||
|
const description = modelData.description.toLowerCase();
|
||||||
|
if (description.search("hdmi") !== -1)
|
||||||
|
return "display"
|
||||||
|
if (description.search("speaker") !== -1)
|
||||||
|
return "audio-speakers"
|
||||||
|
if (description.search("earphone") !== -1 || description.search("headphone") !== -1)
|
||||||
|
return "audio-headset"
|
||||||
|
if (modelData.properties["device.icon-name"])
|
||||||
|
return modelData.properties["device.icon-name"]
|
||||||
|
return modelData.properties["application.name"]
|
||||||
|
})()?.toLowerCase(), "audio-on")
|
||||||
|
width: 32
|
||||||
|
height: width
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
anchors {
|
||||||
|
left: parent.children[0].right
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
margins: 6
|
||||||
|
rightMargin: 12
|
||||||
|
}
|
||||||
|
topPadding: 6
|
||||||
|
bottomPadding: 6
|
||||||
|
spacing: 2
|
||||||
|
Text {
|
||||||
|
text: {
|
||||||
|
if (modelData.nickname !== "") return modelData.nickname
|
||||||
|
if (modelData.description !== "") return description
|
||||||
|
return modelData.name
|
||||||
|
}
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 16
|
||||||
|
}
|
||||||
|
Widgets.Slider {
|
||||||
|
value: modelData.audio.volume
|
||||||
|
onMoved: modelData.audio.volume = position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NodeList {
|
||||||
|
model: Pipewire.nodes.values.filter(node => node.type === 17)
|
||||||
|
}
|
||||||
|
NodeList {
|
||||||
|
model: Pipewire.nodes.values.filter(node => node.type === 21)
|
||||||
|
}
|
||||||
|
}
|
||||||
68
Services/Brightness.qml
Normal file
68
Services/Brightness.qml
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: brightness
|
||||||
|
property var monitors: []
|
||||||
|
Process {
|
||||||
|
id: lsbacklight
|
||||||
|
running: true
|
||||||
|
command: ["find", "/sys/class/backlight", "-maxdepth", "1", "-mindepth", "1"]
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: brightness.monitors = this.text.split('\n')
|
||||||
|
.filter(mon => mon)
|
||||||
|
.map(mon => brightnessMonitorGen.createObject(brightness, {path: mon}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component {
|
||||||
|
id: brightnessMonitorGen
|
||||||
|
BrightnessMonitor {}
|
||||||
|
}
|
||||||
|
component BrightnessMonitor: QtObject {
|
||||||
|
id: monitor
|
||||||
|
property var path
|
||||||
|
property var value
|
||||||
|
property var max
|
||||||
|
property var get: Process {
|
||||||
|
running: true
|
||||||
|
command: ["brightnessctl", "i", "-m"]
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: [,,value,,max] = this.text.split(",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
property var setInterp: Process {
|
||||||
|
running: false
|
||||||
|
command: ["brillo", "-r", "-u", "300000", "-S", value]
|
||||||
|
}
|
||||||
|
property var setInstant: Process {
|
||||||
|
running: false
|
||||||
|
command: ["brightnessctl", "s", value]
|
||||||
|
}
|
||||||
|
function increase() {
|
||||||
|
value += value * 0.1 + max * 0.01
|
||||||
|
value = Math.min(max, value)
|
||||||
|
setInterp.startDetached()
|
||||||
|
}
|
||||||
|
function decrease() {
|
||||||
|
value -= value * 0.1 + max * 0.01
|
||||||
|
value = Math.max(0, value)
|
||||||
|
setInterp.startDetached()
|
||||||
|
}
|
||||||
|
function set(value) {
|
||||||
|
this.value = Math.max(Math.min(value, max), 0)
|
||||||
|
setInstant.startDetached()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GlobalShortcut {
|
||||||
|
name: "increase_brightness"
|
||||||
|
onPressed: monitors[0]?.increase()
|
||||||
|
}
|
||||||
|
GlobalShortcut {
|
||||||
|
name: "decrease_brightness"
|
||||||
|
onPressed: monitors[0]?.decrease()
|
||||||
|
}
|
||||||
|
}
|
||||||
12
TopBar.qml
12
TopBar.qml
@@ -36,7 +36,7 @@ PanelWindow {
|
|||||||
|
|
||||||
GlobalShortcut {
|
GlobalShortcut {
|
||||||
id: shortcut
|
id: shortcut
|
||||||
name: "topbar"
|
name: "peek_bar"
|
||||||
description: "Hold to peek, tap to toggle topbar"
|
description: "Hold to peek, tap to toggle topbar"
|
||||||
onPressed: {
|
onPressed: {
|
||||||
background.index = 0
|
background.index = 0
|
||||||
@@ -70,7 +70,7 @@ PanelWindow {
|
|||||||
id: background
|
id: background
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
color: "#222222"
|
color: "#181818"
|
||||||
radius: 16
|
radius: 16
|
||||||
width: children[0].width + radius*2
|
width: children[0].width + radius*2
|
||||||
height: children[0].height
|
height: children[0].height
|
||||||
@@ -107,6 +107,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
width: children[0].width
|
width: children[0].width
|
||||||
height: children[0].height
|
height: children[0].height
|
||||||
|
visible: opacity
|
||||||
opacity: 0
|
opacity: 0
|
||||||
property var fadeIn: SequentialAnimation {
|
property var fadeIn: SequentialAnimation {
|
||||||
PauseAnimation {duration: 200}
|
PauseAnimation {duration: 200}
|
||||||
@@ -156,6 +157,8 @@ PanelWindow {
|
|||||||
Pane { Panes.Battery {} }
|
Pane { Panes.Battery {} }
|
||||||
Pane { Panes.NotificationCenter {} }
|
Pane { Panes.NotificationCenter {} }
|
||||||
Pane { Panes.Notifications {} }
|
Pane { Panes.Notifications {} }
|
||||||
|
Pane { Panes.Volume {} }
|
||||||
|
Pane { Panes.Brightness {} }
|
||||||
|
|
||||||
property var entry: SequentialAnimation {
|
property var entry: SequentialAnimation {
|
||||||
PauseAnimation {duration: 2}
|
PauseAnimation {duration: 2}
|
||||||
@@ -180,6 +183,9 @@ PanelWindow {
|
|||||||
launcher.clear()
|
launcher.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HoverHandler {id: hover}
|
HoverHandler {
|
||||||
|
id: hover
|
||||||
|
onHoveredChanged: { if (!hovered && background.index === 0) root.close() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
Wall.qml
7
Wall.qml
@@ -15,6 +15,11 @@ Variants {
|
|||||||
aboveWindows: false
|
aboveWindows: false
|
||||||
property var modelData
|
property var modelData
|
||||||
screen: modelData
|
screen: modelData
|
||||||
color: "#141414"
|
color: "#111"
|
||||||
|
Image {
|
||||||
|
source: Quickshell.shellPath("wallpaper")
|
||||||
|
anchors.fill: parent
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,13 @@ Item {
|
|||||||
top: parent.top
|
top: parent.top
|
||||||
bottom: parent.bottom
|
bottom: parent.bottom
|
||||||
}
|
}
|
||||||
width: children[1].width + 20
|
width: children[1].width + 16
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 4
|
anchors.margins: 4
|
||||||
|
anchors.rightMargin: 2
|
||||||
color: hover.hovered ? "#11ffffff" : "#00ffffff"
|
color: hover.hovered ? "#11ffffff" : "#00ffffff"
|
||||||
|
Behavior on color {ColorAnimation {duration: 150}}
|
||||||
radius: 8
|
radius: 8
|
||||||
bottomLeftRadius: 12
|
bottomLeftRadius: 12
|
||||||
}
|
}
|
||||||
|
|||||||
40
Widgets/Brightness.qml
Normal file
40
Widgets/Brightness.qml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import Quickshell
|
||||||
|
import QtQuick.Shapes
|
||||||
|
import qs.Services
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
width: children[1].width + 16
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 4
|
||||||
|
anchors.leftMargin: 2
|
||||||
|
anchors.rightMargin: 2
|
||||||
|
color: hover.hovered ? "#11ffffff" : "#00ffffff"
|
||||||
|
Behavior on color {ColorAnimation {duration: 150}}
|
||||||
|
radius: 8
|
||||||
|
}
|
||||||
|
PercentIndicator {
|
||||||
|
x: 8
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 26
|
||||||
|
height: width
|
||||||
|
percent: Brightness.monitors[0].value / Brightness.monitors[0].max
|
||||||
|
Image {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 20
|
||||||
|
height: width
|
||||||
|
sourceSize {width: width; height: height}
|
||||||
|
source: Quickshell.iconPath("brightnesssettings")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HoverHandler {id: hover}
|
||||||
|
TapHandler {onTapped: {
|
||||||
|
background.index = 6
|
||||||
|
}}
|
||||||
|
}
|
||||||
40
Widgets/PercentIndicator.qml
Normal file
40
Widgets/PercentIndicator.qml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import Quickshell
|
||||||
|
import QtQuick.Shapes
|
||||||
|
import Quickshell.Services.Pipewire
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Shape {
|
||||||
|
id: root
|
||||||
|
preferredRendererType: Shape.CurveRenderer
|
||||||
|
property var percent
|
||||||
|
ShapePath {
|
||||||
|
capStyle: ShapePath.RoundCap
|
||||||
|
fillColor: "transparent"
|
||||||
|
strokeColor: "#333"
|
||||||
|
strokeWidth: 2
|
||||||
|
PathAngleArc {
|
||||||
|
moveToStart: true
|
||||||
|
centerX: root.width/2
|
||||||
|
centerY: root.height/2
|
||||||
|
radiusX: root.width/2
|
||||||
|
radiusY: root.height/2
|
||||||
|
startAngle: 90 + 40
|
||||||
|
sweepAngle: 360 - 80
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShapePath {
|
||||||
|
capStyle: ShapePath.RoundCap
|
||||||
|
fillColor: "transparent"
|
||||||
|
strokeColor: "white"
|
||||||
|
strokeWidth: 2
|
||||||
|
PathAngleArc {
|
||||||
|
moveToStart: true
|
||||||
|
centerX: root.width/2
|
||||||
|
centerY: root.height/2
|
||||||
|
radiusX: root.width/2 - 1
|
||||||
|
radiusY: root.height/2 - 1
|
||||||
|
startAngle: 90 + 40
|
||||||
|
sweepAngle: root.percent * (360 - 80)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
Widgets/Slider.qml
Normal file
42
Widgets/Slider.qml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import QtQuick.Controls as QQC
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
QQC.Slider {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
height: 24
|
||||||
|
orientation: Qt.Horizontal
|
||||||
|
handle: Rectangle {
|
||||||
|
x: parent.visualPosition * (parent.availableWidth - width)
|
||||||
|
y: parent.availableHeight / 2 - height / 2
|
||||||
|
height: 16
|
||||||
|
width: 4
|
||||||
|
radius: width/2
|
||||||
|
}
|
||||||
|
background: Rectangle {
|
||||||
|
height: 6
|
||||||
|
anchors {
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
left: parent.handle.right
|
||||||
|
right: parent.right
|
||||||
|
leftMargin: 4
|
||||||
|
}
|
||||||
|
color: "#333"
|
||||||
|
topRightRadius: height/2
|
||||||
|
bottomRightRadius: topRightRadius
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
height: 6
|
||||||
|
anchors {
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
left: parent.left
|
||||||
|
right: parent.handle.left
|
||||||
|
rightMargin: 4
|
||||||
|
}
|
||||||
|
color: "white"
|
||||||
|
topLeftRadius: height/2
|
||||||
|
bottomLeftRadius: topLeftRadius
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ Item {
|
|||||||
radius: 8
|
radius: 8
|
||||||
bottomRightRadius: 12
|
bottomRightRadius: 12
|
||||||
color: hover.hovered ? "#11ffffff" : "#00ffffff"
|
color: hover.hovered ? "#11ffffff" : "#00ffffff"
|
||||||
Behavior on color {ColorAnimation {duration: 100}}
|
Behavior on color {ColorAnimation {duration: 150}}
|
||||||
}
|
}
|
||||||
Row {
|
Row {
|
||||||
spacing: 12
|
spacing: 12
|
||||||
|
|||||||
7
Widgets/Uptime.qml
Normal file
7
Widgets/Uptime.qml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors {
|
||||||
|
}
|
||||||
|
}
|
||||||
44
Widgets/Volume.qml
Normal file
44
Widgets/Volume.qml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import Quickshell
|
||||||
|
import QtQuick.Shapes
|
||||||
|
import Quickshell.Services.Pipewire
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
width: children[1].width + 16
|
||||||
|
|
||||||
|
PwObjectTracker {
|
||||||
|
objects: [Pipewire.defaultAudioSink]
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 4
|
||||||
|
anchors.leftMargin: 2
|
||||||
|
anchors.rightMargin: 2
|
||||||
|
color: hover.hovered ? "#11ffffff" : "#00ffffff"
|
||||||
|
Behavior on color {ColorAnimation {duration: 150}}
|
||||||
|
radius: 8
|
||||||
|
}
|
||||||
|
PercentIndicator {
|
||||||
|
x: 8
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 26
|
||||||
|
height: width
|
||||||
|
percent: Pipewire.defaultAudioSink.audio.volume
|
||||||
|
Image {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 20
|
||||||
|
height: width
|
||||||
|
sourceSize {width: width; height: height}
|
||||||
|
source: Quickshell.iconPath("volume-level-high")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HoverHandler {id: hover}
|
||||||
|
TapHandler {onTapped: {
|
||||||
|
background.index = 5
|
||||||
|
}}
|
||||||
|
}
|
||||||
@@ -18,9 +18,11 @@ Item {
|
|||||||
width: 24
|
width: 24
|
||||||
property var workspace: Hyprland.workspaces.values.find(ws => ws.id === modelData+1)
|
property var workspace: Hyprland.workspaces.values.find(ws => ws.id === modelData+1)
|
||||||
property var icon: {
|
property var icon: {
|
||||||
const appId = workspace ? Array.from(workspace.toplevels.values).sort(
|
let appId
|
||||||
(a, b) => b.lastIpcObject.focusHistoryId - a.lastIpcObject.focusHistoryId
|
if (workspace) {
|
||||||
)[0]?.wayland?.appId : undefined
|
let toplevel = Array.from(workspace.toplevels.values).reduce((prev, curr) => (prev.lastIpcObject.focusHistoryID < curr.lastIpcObject.focusHistoryID) ? prev : curr)
|
||||||
|
appId = toplevel.wayland?.appId
|
||||||
|
}
|
||||||
return DesktopEntries.applications.values.find(
|
return DesktopEntries.applications.values.find(
|
||||||
app => app.startupClass === appId || app.id === appId
|
app => app.startupClass === appId || app.id === appId
|
||||||
)?.icon;
|
)?.icon;
|
||||||
@@ -59,4 +61,8 @@ Item {
|
|||||||
height: 4
|
height: 4
|
||||||
radius: height/2
|
radius: height/2
|
||||||
}
|
}
|
||||||
|
Connections {
|
||||||
|
target: Hyprland
|
||||||
|
function onActiveToplevelChanged() {Hyprland.refreshToplevels()}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
shell.qml
11
shell.qml
@@ -1,3 +1,4 @@
|
|||||||
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
import Quickshell.Services.Notifications
|
import Quickshell.Services.Notifications
|
||||||
@@ -9,12 +10,20 @@ ShellRoot {
|
|||||||
onNotification: (notif) => notif.tracked = true
|
onNotification: (notif) => notif.tracked = true
|
||||||
}
|
}
|
||||||
Shell.Wall {}
|
Shell.Wall {}
|
||||||
Shell.TopBar {}
|
Shell.TopBar {id: bar}
|
||||||
Shell.Boateye {}
|
Shell.Boateye {}
|
||||||
Shell.Lock {
|
Shell.Lock {
|
||||||
id: lock
|
id: lock
|
||||||
animate: true
|
animate: true
|
||||||
}
|
}
|
||||||
|
PanelWindow {
|
||||||
|
anchors {
|
||||||
|
top: true
|
||||||
|
}
|
||||||
|
implicitHeight: 1
|
||||||
|
implicitWidth: 800
|
||||||
|
HoverHandler {onHoveredChanged: {if (hovered) bar.open() }}
|
||||||
|
}
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
target: "lock"
|
target: "lock"
|
||||||
function instalock() {lock.animate = false; lock.locked = true}
|
function instalock() {lock.animate = false; lock.locked = true}
|
||||||
|
|||||||
Reference in New Issue
Block a user