workspace view rework

This commit is contained in:
2025-07-30 23:21:13 +01:00
parent 9d65cb0d58
commit 92636a2dde
13 changed files with 285 additions and 15 deletions

View File

@@ -4,11 +4,13 @@ import Quickshell.Io
import QtQuick
import QtQuick.Layouts
import Quickshell.Widgets
import Quickshell.Hyprland
import "widgets" as Widgets
import "widgets/player" as Player
import "widgets/common" as Common
import "widgets/clock" as Clock
import "widgets/workspace" as Workspace
// Tako kindly threatened you to sort the naming schema and to put all the svg's in an asset folder, so please do that
@@ -37,26 +39,26 @@ import "widgets/clock" as Clock
RowLayout { // Left
Layout.alignment: Qt.AlignLeft
Clock.Date {}
Clock.Clock {}
Workspace.WorkspaceWidget {}
}
RowLayout { // Center
// TODO: add icons of the active window per workspace in the workspace tab
anchors.centerIn: parent
Widgets.Workspaces {}
}
RowLayout { // Right
Layout.alignment: Qt.AlignRight
Common.VerticalSeprator {}
Loader {
sourceComponent: Widgets.Audio {}
}
RowLayout {
Text {
text: HyprlandWindowTracker.HyprlandWindowTracker.aaaa
}
visible: Player.activePlayer.isPlaying()
Common.VerticalSeprator {}
Player.PlayerWidgetV2 {
}
}
Common.VerticalSeprator {}
Clock.Clock {}
Widgets.SystemTray {
id: systemTray
}

View File

@@ -4,6 +4,8 @@ import QtQuick
import QtQuick.Layouts
import Quickshell.Widgets
import Quickshell.Services.Pipewire
import "common" as Common
Item {
id: root
@@ -27,17 +29,32 @@ Item {
radius: 7
color: "black"
}
IconImage {
Text {
anchors.centerIn: parent
implicitSize: 25
source: root.speakerNode.audio.muted ? "root:/assets/bar/MutedSpeaker.svg" : "root:/assets/bar/Speaker.svg"
// source: "root:/assets/bar/Speaker.svg"
// implicitSize: 25
font.pixelSize: 28
color: root.speakerNode.audio.muted ? "#FF474C" : "white"
font.family: "JetBrainsMono Nerd Font Mono"
text: root.speakerNode.audio.muted ? Common.Icons.audioIcons.speakerMuted : Common.Icons.audioIcons.speaker
}
}
IconImage {
implicitSize: 25
source: root.microphoneNode.audio.muted ? "root:/assets/bar/MutedMic.svg" : "root:/assets/bar/Mic.svg"
// source: "root:/assets/bar/Mic.svg"
Item {
implicitWidth: 28
implicitHeight: 28
Rectangle {
width: parent.width
height: parent.height
radius: 7
color: "black"
}
Text {
anchors.centerIn: parent
// implicitSize: 25
font.pixelSize: 34
color: root.microphoneNode.audio.muted ? "#FF474C" : "white"
font.family: "JetBrainsMono Nerd Font Mono"
text: root.microphoneNode.audio.muted ? Common.Icons.audioIcons.microphoneMuted : Common.Icons.audioIcons.microphone
}
}
}
}

View File

@@ -35,6 +35,9 @@ RowLayout {
if (event.button === Qt.LeftButton) {
Hyprland.dispatch('workspace ' + index_workspace.id);
}
for (x in index_workspace.toplevels.values) {
console.log(index_workspace.toplevels.values[x].title)
}
}
}
}

View File

@@ -6,10 +6,11 @@ import "../common" as Common
Item {
id: root
width: text.width
width: text.width + 15
height: text.height
Common.Container {}
Text {
anchors.centerIn: parent
id: text
text: ClockData.time
font.pointSize: 10.25

View File

@@ -0,0 +1,12 @@
pragma Singleton
import Quickshell
import Quickshell.Io
Singleton {
id: root
readonly property var colors: ({
"primary": "",
})
}

View File

@@ -0,0 +1,27 @@
pragma Singleton
import Quickshell
import Quickshell.Io
Singleton {
id: root
readonly property var audioIcons: ({
microphone: "",
microphoneMuted: "",
speaker: "󰕾",
speakerMuted: "󰖁",
})
// {class}: {icon}
readonly property var appIcons: ({
"vesktop": "",
"steam": "",
"org.telegram.desktop": "",
"chromium": "",
"dev.zed.Zed": "",
"foot": "",
"gamescope": "󰺵",
"fallback": ""
})
}

View File

@@ -0,0 +1,17 @@
// import qs.services
// import qs.config
import "text" as Text
Text.StyledText {
property real fill
property int grade: Colours.light ? 0 : -25
font.family: Appearance.font.family.material
font.pointSize: Appearance.font.size.larger
font.variableAxes: ({
FILL: fill.toFixed(1),
GRAD: grade,
opsz: fontInfo.pixelSize,
wght: fontInfo.weight
})
}

View File

@@ -0,0 +1,54 @@
pragma ComponentBehavior: Bound
// https://github.com/caelestia-dots/shell/blob/a23bb48c243348096b27f5f4ac94f663271ece10/widgets/StyledText.qml
// import qs.services
// import qs.config
import QtQuick
Text {
id: root
property bool animate: false
property string animateProp: "scale"
property real animateFrom: 0
property real animateTo: 1
property int animateDuration: Appearance.anim.durations.normal
renderType: Text.NativeRendering
textFormat: Text.PlainText
color: Colours.palette.m3onSurface
font.family: Appearance.font.family.sans
font.pointSize: Appearance.font.size.smaller
Behavior on color {
ColorAnimation {
duration: Appearance.anim.durations.normal
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.standard
}
}
Behavior on text {
enabled: root.animate
SequentialAnimation {
Anim {
to: root.animateFrom
easing.bezierCurve: Appearance.anim.curves.standardAccel
}
PropertyAction {}
Anim {
to: root.animateTo
easing.bezierCurve: Appearance.anim.curves.standardDecel
}
}
}
component Anim: NumberAnimation {
target: root
property: root.animateProp
duration: root.animateDuration / 2
easing.type: Easing.BezierSpline
}
}

View File

@@ -31,9 +31,11 @@ Singleton {
property string lastActivePlayerIdentify: "";
onReloaded: {
root.setActivePlayerFromIdentity(lastActivePlayerIdentify)
root.updateActiveTrackPosition()
}
onLoaded: {
root.setActivePlayerFromIdentity(lastActivePlayerIdentify)
root.updateActiveTrackPosition()
}
}
@@ -166,6 +168,15 @@ Singleton {
this.activePlayer = player;
}
function setActivePlayerFromIdentity(identify: string) {
for (x in root.mpris.players) {
if (x.identify == identify) {
this.activePlayer = x
return
}
}
}
Timer {
// only emit the signal when the position is actually changing.
running: root.activePlayer.playbackState == MprisPlaybackState.Playing

View File

@@ -220,7 +220,6 @@ PopupWindow {
repeat: true
onTriggered: {
root.modelData.position = slider.value
audioPopup.player.update(); // force values to update // causing ui to update with it
slider.debounceValue = false;
}
}
@@ -245,6 +244,7 @@ PopupWindow {
updateTimer.tempOneshot = false;
slider.lastPosition = slider.value
slider.value = root.modelData.position
// root.audioPopup.player.update();
}
}
}

View File

@@ -0,0 +1,7 @@
import Quickshell
import QtQuick
Item {
property string initialClass: "";
property string initialTitle: "";
}

View File

@@ -0,0 +1,29 @@
pragma Singleton
import Quickshell
import QtQuick
import Quickshell.Io
import Quickshell.Hyprland
Singleton {
id: root
// property string aaaa: "";
property list<HyprlandClient> meow;
property Hyprland hyprland: Hyprland;
Process {
id: dateProc
command: ["hyprctl", "clients"]
running: true
stdout: StdioCollector {
onStreamFinished: parseClients(this.text)
}
}
function parseClients(text) {
hyprland.refreshToplevels();
var meow = hyprland.activeToplevel.lastIpcObject;
console.log(meow.class);
}
}

View File

@@ -0,0 +1,90 @@
import Quickshell
import Quickshell.Io
import QtQuick
import QtQuick.Layouts
import Quickshell.Widgets
import Quickshell.Hyprland
import "root:/bar/widgets/common" as Common
RowLayout {
id: root
spacing: 10
Layout.fillHeight: true
Repeater {
model: Hyprland.workspaces
delegate: Item {
id: root2
required property HyprlandWorkspace modelData
implicitWidth: 35 + appIconContainer.implicitWidth
Layout.fillHeight: true
Item {
visible: root2.modelData.toplevels.values[0] != undefined
id: appIconContainer
implicitWidth: row.implicitWidth
implicitHeight: 25
x: 30
anchors.verticalCenter: root2.verticalCenter
Rectangle {
x: -10
radius: 7
color: "black"
implicitWidth: row.width + 20
implicitHeight: 25
}
RowLayout {
x: 5
anchors.verticalCenter: parent.verticalCenter
id: row
spacing: 15
Repeater {
model: root2.modelData.toplevels
delegate: Item {
required property HyprlandToplevel modelData
width: icon.implicitWidth
height: icon.implicitHeight
Text {
id: icon
color: "white"
font.pointSize: 13
// long-ass oneliner for "if there is no class icon, go to fallback"
text: (Common.Icons.appIcons[(modelData.lastIpcObject.class)] != undefined ) ? Common.Icons.appIcons[(modelData.lastIpcObject.class)] : Common.Icons.appIcons["fallback"]
}
}
}
}
}
Item {
width: 30
height: 30
MouseArea {
width: 30
height: 30
onPressed: event => {
modelData.activate();
}
}
Rectangle {
width: 30
height: 30
radius: 10
color: modelData.focused ? "grey" : "black"
}
Text {
anchors.centerIn: parent
text: modelData.id
color: "white"
}
}
}
}
Timer {
id: updateTimer
running: true
interval: 1000 // 10secs
repeat: true
onTriggered: {
Hyprland.refreshToplevels()
}
}
}