summaryrefslogtreecommitdiff
path: root/.config
diff options
context:
space:
mode:
authorSam Nystrom <sam@samnystrom.dev>2026-01-15 16:53:43 -0500
committerSam Nystrom <sam@samnystrom.dev>2026-01-15 16:53:43 -0500
commit53008538e5bef961e9ceb5abc5c5ee05a559e97d (patch)
tree3ad2f4fa7fbc88ff4bb67c75395cc4acdb9c09fb /.config
parent3ac17574dbcfe68b2fba11aeeb445f04d1170c2a (diff)
update qs config
Diffstat (limited to '.config')
-rw-r--r--.config/quickshell/Modules/Bar.qml (renamed from .config/quickshell/Bar.qml)101
-rw-r--r--.config/quickshell/Modules/Music.qml298
-rw-r--r--.config/quickshell/Modules/Wall.qml (renamed from .config/quickshell/Wall.qml)1
-rw-r--r--.config/quickshell/Services/Battery.qml (renamed from .config/quickshell/Battery.qml)0
-rw-r--r--.config/quickshell/Services/Brightness.qml (renamed from .config/quickshell/Brightness.qml)0
-rw-r--r--.config/quickshell/Services/Cava.qml (renamed from .config/quickshell/Cava.qml)5
-rw-r--r--.config/quickshell/Services/Flexoki.qml (renamed from .config/quickshell/Flexoki.qml)0
-rw-r--r--.config/quickshell/Services/HyprlandService.qml11
-rw-r--r--.config/quickshell/Services/Song.qml (renamed from .config/quickshell/Song.qml)14
-rw-r--r--.config/quickshell/Services/Tags.qml (renamed from .config/quickshell/Tags.qml)0
-rw-r--r--.config/quickshell/Services/Time.qml (renamed from .config/quickshell/Time.qml)0
-rw-r--r--.config/quickshell/Services/Uptime.qml (renamed from .config/quickshell/Uptime.qml)0
-rw-r--r--.config/quickshell/Services/Volume.qml (renamed from .config/quickshell/Volume.qml)0
-rw-r--r--.config/quickshell/Services/Wifi.qml (renamed from .config/quickshell/Wifi.qml)6
-rw-r--r--.config/quickshell/shell.qml11
15 files changed, 359 insertions, 88 deletions
diff --git a/.config/quickshell/Bar.qml b/.config/quickshell/Modules/Bar.qml
index 02b8781..3120574 100644
--- a/.config/quickshell/Bar.qml
+++ b/.config/quickshell/Modules/Bar.qml
@@ -1,6 +1,8 @@
import Quickshell
+import Quickshell.Hyprland
import QtQuick
import QtQuick.Layouts
+import qs.Services
Variants {
model: Quickshell.screens;
@@ -38,38 +40,34 @@ Variants {
Rectangle {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
- implicitWidth: tags.implicitWidth + 12*2
+ implicitWidth: workspaces.implicitWidth + 12*2
height: parent.height
color: Flexoki.bg
radius: 18
- RowLayout {
- id: tags
+ Row {
+ id: workspaces
anchors.centerIn: parent
- implicitHeight: parent.implicitHeight
+ height: 20
spacing: 6
Repeater {
- model: Tags.tags
+ model: ScriptModel {
+ values: Hyprland.workspaces.values.filter(ws => ws.id >= 0).sort((a, b) => a.id - b.id)
+ }
delegate: Rectangle {
- required property bool focused
- required property bool occupied
+ required property HyprlandWorkspace modelData
+ property bool focused: modelData.focused
+ property bool occupied: modelData.toplevels.values.length > 0
width: 20
height: 20
radius: 10
color: {
- if (focused) {
- if (occupied) {
- return Flexoki.re
- } else {
- return Flexoki.ui3
- }
- } else {
- return "transparent"
- }
+ if (!focused) return "transparent"
+ return occupied ? Flexoki.re : Flexoki.ui3
}
border.width: 2
@@ -79,74 +77,7 @@ Variants {
}
}
- RowLayout {
- anchors.centerIn: parent
- implicitHeight: parent.implicitHeight
- spacing: 4
-
- Rectangle {
- implicitWidth: song.implicitWidth + 16*2
- height: parent.height
- color: Flexoki.bg
-
- bottomLeftRadius: 18
- topLeftRadius: 18
- bottomRightRadius: 4
- topRightRadius: 4
-
- Text {
- id: song
- anchors.centerIn: parent
- text: {
- var text = Song.artist + " – " + Song.title
- if (text.length > 60) {
- text = text.substring(0, 60) + "…"
- }
- return text
- }
- color: Flexoki.tx
- font { family: root.fontFamily; pixelSize: root.fontSize }
- }
- }
-
- Rectangle {
- implicitWidth: cava.implicitWidth + 16*2
- height: parent.height
- color: Flexoki.bg
-
- bottomLeftRadius: 4
- topLeftRadius: 4
- bottomRightRadius: 18
- topRightRadius: 18
-
- Row {
- id: cava
- anchors.centerIn: parent
- height: 15 + 4
- spacing: 2
-
- Repeater {
- model: Cava.heights
-
- delegate: Rectangle {
- required property int modelData
- y: 15 - modelData
- width: 8
- height: modelData + 4
- radius: 4
- color: Flexoki.tx
-
- Behavior on height {
- NumberAnimation { duration: 1000 / 30; easing.type: Easing.Linear }
- }
- Behavior on y {
- NumberAnimation { duration: 1000 / 30; easing.type: Easing.Linear }
- }
- }
- }
- }
- }
- }
+ Music {}
Rectangle {
anchors.verticalCenter: parent.verticalCenter
@@ -194,7 +125,7 @@ Variants {
Text {
text: {
var icon
- var i = Math.round((Battery.capacity - 1) / 10)
+ var i = Math.floor((Battery.capacity - 1) / 10)
switch (Battery.status) {
case "Full":
icon = "󰂄"
diff --git a/.config/quickshell/Modules/Music.qml b/.config/quickshell/Modules/Music.qml
new file mode 100644
index 0000000..efb717e
--- /dev/null
+++ b/.config/quickshell/Modules/Music.qml
@@ -0,0 +1,298 @@
+import Quickshell
+import QtQuick
+import qs.Services
+
+MouseArea {
+ id: root
+ anchors.centerIn: parent
+ height: parent.implicitHeight
+ width: musicRow.implicitWidth
+ state: "POPUP_CLOSED"
+
+ hoverEnabled: true
+ onEntered: state = "POPUP_OPEN"
+
+ property string fontFamily: "FiraCode Nerd Font"
+ property int fontSize: 14
+
+ property int contractAnimDuration: 150
+
+ states: [
+ State {
+ name: "POPUP_CLOSED"
+ PropertyChanges { target: popup; visible: false }
+ PropertyChanges { target: musicRow; visible: true; spacing: 4 }
+ PropertyChanges { target: songContainer; bottomRightRadius: 4; topRightRadius: 4 }
+ PropertyChanges { target: cavaContainer; bottomLeftRadius: 4; topLeftRadius: 4 }
+ PropertyChanges { target: song; opacity: 1 }
+ PropertyChanges { target: cava; opacity: 1 }
+ PropertyChanges {
+ target: popupRect
+ width: musicRow.width
+ height: 36
+ border.color: Flexoki.bg
+ }
+ },
+ State {
+ name: "POPUP_OPEN"
+ PropertyChanges { target: popup; visible: true }
+ PropertyChanges { target: musicRow; visible: false; spacing: -1 }
+ PropertyChanges { target: songContainer; bottomRightRadius: 0; topRightRadius: 0 }
+ PropertyChanges { target: cavaContainer; bottomLeftRadius: 0; topLeftRadius: 0 }
+ PropertyChanges { target: song; opacity: 0 }
+ PropertyChanges { target: cava; opacity: 0 }
+ PropertyChanges {
+ target: popupRect
+ width: 700
+ height: 500
+ border.color: Flexoki.ui2
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "POPUP_CLOSED"
+ to: "POPUP_OPEN"
+
+ SequentialAnimation {
+ ParallelAnimation {
+ NumberAnimation {
+ target: songContainer
+ properties: "bottomRightRadius,topRightRadius"
+ duration: root.contractAnimDuration
+ easing.type: Easing.InQuad
+ }
+
+ NumberAnimation {
+ target: cavaContainer
+ properties: "bottomLeftRadius,topLeftRadius"
+ duration: root.contractAnimDuration
+ easing.type: Easing.InQuad
+ }
+
+ NumberAnimation {
+ target: musicRow
+ property: "spacing"
+ duration: root.contractAnimDuration
+ easing.type: Easing.OutQuad
+ }
+
+ NumberAnimation {
+ targets: [song, cava]
+ property: "opacity"
+ duration: root.contractAnimDuration
+ easing.type: Easing.OutQuad
+ }
+ }
+
+ PropertyAction { target: popup; property: "visible" }
+ PropertyAction { target: musicRow; property: "visible" }
+
+ ParallelAnimation {
+ NumberAnimation {
+ target: popupRect
+ property: "width"
+ duration: 250
+ easing.type: Easing.OutQuad
+ }
+
+ SpringAnimation {
+ target: popupRect
+ property: "height"
+ spring: 5
+ mass: 0.5
+ damping: 0.2
+ epsilon: 0.25
+ }
+
+ ColorAnimation {
+ target: popupRect
+ property: "border.color"
+ duration: 250
+ easing.type: Easing.OutQuad
+ }
+ }
+ }
+ },
+ Transition {
+ from: "POPUP_OPEN"
+ to: "POPUP_CLOSED"
+
+ SequentialAnimation {
+ ParallelAnimation {
+ NumberAnimation {
+ target: popupRect
+ property: "width"
+ duration: 250
+ easing.type: Easing.OutQuad
+ }
+
+ NumberAnimation {
+ target: popupRect
+ property: "height"
+ duration: 250
+ easing.type: Easing.OutQuad
+ }
+
+ ColorAnimation {
+ target: popupRect
+ property: "border.color"
+ duration: 250
+ easing.type: Easing.OutQuad
+ }
+ }
+
+ PropertyAction { target: musicRow; property: "visible" }
+ PropertyAction { target: popup; property: "visible" }
+
+ ParallelAnimation {
+ NumberAnimation {
+ target: songContainer
+ properties: "bottomRightRadius,topRightRadius"
+ duration: root.contractAnimDuration
+ easing.type: Easing.InQuad
+ }
+
+ NumberAnimation {
+ target: cavaContainer
+ properties: "bottomLeftRadius,topLeftRadius"
+ duration: root.contractAnimDuration
+ easing.type: Easing.InQuad
+ }
+
+ NumberAnimation {
+ target: musicRow
+ property: "spacing"
+ duration: root.contractAnimDuration
+ easing.type: Easing.OutQuad
+ }
+
+ NumberAnimation {
+ targets: [song, cava]
+ property: "opacity"
+ duration: root.contractAnimDuration
+ easing.type: Easing.OutQuad
+ }
+ }
+ }
+ },
+ ]
+
+ PopupWindow {
+ id: popup
+ anchor.item: root
+ anchor.rect.x: root.width / 2 - width / 2
+ anchor.rect.y: 0
+ implicitWidth: 1920
+ implicitHeight: 600
+ color: "transparent"
+ visible: false
+
+
+ Rectangle {
+ id: popupRect
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ width: 700
+ height: 36
+ color: Flexoki.bg
+ border.color: Flexoki.ui
+ border.width: 2
+ radius: 18
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ onExited: root.state = "POPUP_CLOSED"
+ }
+
+ Text {
+ visible: false
+ anchors.centerIn: parent
+ color: Flexoki.tx
+ text: "Hello world!"
+ }
+ }
+ }
+
+ Row {
+ id: musicRow
+ anchors.centerIn: parent
+ height: parent.height
+ spacing: 4
+
+ Rectangle {
+ id: songContainer
+ implicitWidth: song.implicitWidth + 16*2
+ height: parent.height
+ color: Flexoki.bg
+
+ bottomLeftRadius: 18
+ topLeftRadius: 18
+ bottomRightRadius: 4
+ topRightRadius: 4
+
+ Text {
+ id: song
+ anchors.centerIn: parent
+ text: {
+ if (!Song.file) return "Not playing"
+ var text = Song.file
+ if (Song.title) {
+ if (Song.artist) {
+ text = Song.artist + " – " + Song.title
+ } else {
+ text = Song.title
+ }
+ }
+ if (text.length > 60) {
+ text = text.substring(0, 60) + "…"
+ }
+ return text
+ }
+ color: Flexoki.tx
+ font { family: root.fontFamily; pixelSize: root.fontSize }
+ }
+ }
+
+ Rectangle {
+ id: cavaContainer
+ implicitWidth: cava.implicitWidth + 16*2
+ height: parent.height
+ color: Flexoki.bg
+
+ bottomLeftRadius: 4
+ topLeftRadius: 4
+ bottomRightRadius: 18
+ topRightRadius: 18
+
+ Row {
+ id: cava
+ anchors.centerIn: parent
+ height: 15 + 4
+ spacing: 2
+
+ Repeater {
+ model: Cava.heights
+
+ delegate: Rectangle {
+ required property int modelData
+ y: 15 - modelData
+ width: 8
+ height: modelData + 4
+ radius: 4
+ color: Flexoki.tx
+
+ Behavior on height {
+ NumberAnimation { duration: 1000 / 30; easing.type: Easing.Linear }
+ }
+ Behavior on y {
+ NumberAnimation { duration: 1000 / 30; easing.type: Easing.Linear }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/.config/quickshell/Wall.qml b/.config/quickshell/Modules/Wall.qml
index fc47161..b585c2e 100644
--- a/.config/quickshell/Wall.qml
+++ b/.config/quickshell/Modules/Wall.qml
@@ -1,6 +1,7 @@
import Quickshell
import QtQuick
import QtQuick.Layouts
+import qs.Services
Variants {
model: Quickshell.screens;
diff --git a/.config/quickshell/Battery.qml b/.config/quickshell/Services/Battery.qml
index 0d6213c..0d6213c 100644
--- a/.config/quickshell/Battery.qml
+++ b/.config/quickshell/Services/Battery.qml
diff --git a/.config/quickshell/Brightness.qml b/.config/quickshell/Services/Brightness.qml
index 80a8d1f..80a8d1f 100644
--- a/.config/quickshell/Brightness.qml
+++ b/.config/quickshell/Services/Brightness.qml
diff --git a/.config/quickshell/Cava.qml b/.config/quickshell/Services/Cava.qml
index 2067a11..96cb918 100644
--- a/.config/quickshell/Cava.qml
+++ b/.config/quickshell/Services/Cava.qml
@@ -6,14 +6,15 @@ import QtQuick
Singleton {
id: root
- property var heights
+ property list<int> heights
Process {
command: ["cava", "-p", "/home/samn/.config/quickshell/cava.ini"]
running: true
stdout: SplitParser {
onRead: line => {
- root.heights = line.substring(0, line.length - 1).split(';').map(x => parseInt(x))
+ var heights = line.substring(0, line.length - 1).split(';').map(x => parseInt(x))
+ if (heights !== root.heights) root.heights = heights
}
}
}
diff --git a/.config/quickshell/Flexoki.qml b/.config/quickshell/Services/Flexoki.qml
index 1c467b5..1c467b5 100644
--- a/.config/quickshell/Flexoki.qml
+++ b/.config/quickshell/Services/Flexoki.qml
diff --git a/.config/quickshell/Services/HyprlandService.qml b/.config/quickshell/Services/HyprlandService.qml
new file mode 100644
index 0000000..9d35866
--- /dev/null
+++ b/.config/quickshell/Services/HyprlandService.qml
@@ -0,0 +1,11 @@
+pragma Singleton
+
+import Quickshell
+import Quickshell.Hyprland
+import QtQuick
+
+Singleton {
+ id: root
+ property int activeWorkspace
+
+}
diff --git a/.config/quickshell/Song.qml b/.config/quickshell/Services/Song.qml
index 14d7704..a4dc969 100644
--- a/.config/quickshell/Song.qml
+++ b/.config/quickshell/Services/Song.qml
@@ -6,8 +6,10 @@ import QtQuick
Singleton {
id: root
+ property string file
property string artist
property string title
+ property string coverPath: "/home/samn/Music/cover.jpg"
Process {
id: songProc
@@ -15,13 +17,25 @@ Singleton {
running: true
stdout: StdioCollector {
onStreamFinished: {
+ var oldFile = root.file
var obj = JSON.parse(this.text);
+
+ root.file = obj.file
root.artist = obj.metadata.artist
root.title = obj.metadata.title
+
+ if (obj.file !== oldFile) {
+ coverProc.exec(["ffmpeg", "-y", "-i", "/home/samn/Music/" + obj.file, "-an", "-c:v", "copy", "/home/samn/Music/cover.jpg"])
+ }
}
}
}
+ Process {
+ id: coverProc
+ running: false
+ }
+
Timer {
interval: 5000
running: true
diff --git a/.config/quickshell/Tags.qml b/.config/quickshell/Services/Tags.qml
index 66aadaa..66aadaa 100644
--- a/.config/quickshell/Tags.qml
+++ b/.config/quickshell/Services/Tags.qml
diff --git a/.config/quickshell/Time.qml b/.config/quickshell/Services/Time.qml
index 7af1b1f..7af1b1f 100644
--- a/.config/quickshell/Time.qml
+++ b/.config/quickshell/Services/Time.qml
diff --git a/.config/quickshell/Uptime.qml b/.config/quickshell/Services/Uptime.qml
index 155be44..155be44 100644
--- a/.config/quickshell/Uptime.qml
+++ b/.config/quickshell/Services/Uptime.qml
diff --git a/.config/quickshell/Volume.qml b/.config/quickshell/Services/Volume.qml
index 875f1c9..875f1c9 100644
--- a/.config/quickshell/Volume.qml
+++ b/.config/quickshell/Services/Volume.qml
diff --git a/.config/quickshell/Wifi.qml b/.config/quickshell/Services/Wifi.qml
index 76ff2b5..a438471 100644
--- a/.config/quickshell/Wifi.qml
+++ b/.config/quickshell/Services/Wifi.qml
@@ -1,6 +1,7 @@
pragma Singleton
import Quickshell
+import Quickshell.Hyprland
import Quickshell.Io
import QtQuick
@@ -13,7 +14,10 @@ Singleton {
command: ["sh", "-c", "iwctl station wlan0 get-networks | awk -F' ' '/>/ {print $3}'"]
running: true
stdout: StdioCollector {
- onStreamFinished: root.ssid = this.text.trim()
+ onStreamFinished: {
+ root.ssid = this.text.trim()
+ // Hyprland.refreshWorkspaces()
+ }
}
}
diff --git a/.config/quickshell/shell.qml b/.config/quickshell/shell.qml
index 7a27cf2..4285ded 100644
--- a/.config/quickshell/shell.qml
+++ b/.config/quickshell/shell.qml
@@ -1,6 +1,17 @@
import Quickshell
+import Quickshell.Hyprland
+import QtQuick
+import qs.Modules
Scope {
Bar {}
Wall {}
+
+ Connections {
+ target: Hyprland
+ function onRawEvent(event) {
+ throw new Exception('hyprland event')
+ Hyprland.refreshWorkspaces()
+ }
+ }
}