mpris widget in bar yippie ^_^

This commit is contained in:
lucy 2025-12-26 00:37:39 +01:00
parent 38173b9959
commit d72adec2ef
10 changed files with 194 additions and 42 deletions

View File

@ -5,7 +5,7 @@ import Quickshell
Singleton {
id: customColors
// Core Backgrounds
readonly property color background: "#1A1B26"
readonly property color background: "#24283B"
readonly property color foreground: "#C0CAF5"
readonly property color cursor: "#C0CAF5"
@ -17,7 +17,7 @@ Singleton {
readonly property color color4: "#7AA2F7"
readonly property color color5: "#BB9AF7"
readonly property color color6: "#7DCFFF"
readonly property color color7: "#A9B1D6"
readonly property color color7: "#C0CAF5"
readonly property color color8: "#414868"
readonly property color color9: "#F7768E"
readonly property color color10: "#9ECE6A"

View File

@ -8,7 +8,7 @@ PanelWindow {
required property var modelData
implicitHeight: 30
//color: Colors.background
color: "black"
color: Colors.background
anchors {
top: true
left: true
@ -17,11 +17,13 @@ PanelWindow {
RowLayout {
id: leftLayout
spacing: 30
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
Clock {
Layout.leftMargin: 30
}
Mpris {}
}
RowLayout {
@ -37,6 +39,7 @@ PanelWindow {
anchors.verticalCenter: parent.verticalCenter
Volume {}
Battery {}
PowerProfiles {}
SystemTray {
Layout.rightMargin: 30
}

View File

@ -27,26 +27,5 @@ Item {
color: Colors.foreground
text: Math.round(UPower.displayDevice.percentage * 100) + "%"
}
Text {
id: powerProfile
text: PowerProfile.toString(PowerProfiles.profile)
font.weight: 900
color: Colors.foreground
font.family: Appearance.font
font.pixelSize: Appearance.fontSize
}
}
MouseArea {
acceptedButtons: Qt.LeftButton
cursorShape: Qt.OpenHandCursor
anchors.fill: parent
onClicked: {
const modes = [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance];
let current = PowerProfiles.profile;
let currentIndex = modes.indexOf(current);
let nextIndex = (currentIndex + 1) % modes.length;
PowerProfiles.profile = modes[nextIndex];
PowerProfiles.profile = profiles[nextIndex];
}
}
}

134
modules/bar/Mpris.qml Normal file
View File

@ -0,0 +1,134 @@
// Ensure Colors is imported
// import "../../"
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Services.Mpris
import qs
RowLayout {
id: root
// 1. Let Repeater loop through the ObjectModel for us
Repeater {
id: mprisRepeater
model: Mpris.players
delegate: RowLayout {
required property var modelData
// 2. 🕵 FILTER LOGIC
// Check if this specific player is Spotify.
// We verify 'modelData' exists and check the name.
property bool isSpotify: modelData && modelData.identity.toLowerCase().includes("spotify")
// 3. 👻 HIDE NON-SPOTIFY PLAYERS
visible: isSpotify
// If hidden, take up ZERO space
Layout.preferredWidth: isSpotify ? Math.min(implicitWidth, 400) : 0
Layout.fillHeight: true
// 4. 🎵 USE 'modelData' DIRECTLY
// property string title: modelData.metadata["xesam:title"] || "No Title"
// property string artist: modelData.metadata["xesam:artist"] || "Unknown"
// property string artUrl: modelData.metadata["mpris:artUrl"] || ""
// property bool isPlaying: modelData.playbackStatus === MprisPlaybackStatus.Playing
property string title: modelData.trackTitle
property string artist: modelData.trackArtist
property string artUrl: modelData.trackArtUrl
property bool isPlaying: modelData.isPlaying
spacing: 8
// 🖼 ALBUM ART
Rectangle {
Layout.preferredHeight: parent.height * 0.8
Layout.preferredWidth: Layout.preferredHeight
Layout.alignment: Qt.AlignVCenter
radius: 4
color: Colors.background
clip: true
visible: parent.visible // Optimization
Image {
anchors.fill: parent
source: parent.parent.artUrl // Access property from delegate
fillMode: Image.PreserveAspectCrop
asynchronous: true
sourceSize.width: 128
sourceSize.height: 128
}
}
// 📝 TEXT INFO
ColumnLayout {
Layout.alignment: Qt.AlignVCenter
spacing: 0
visible: parent.visible
Text {
text: parent.parent.title
color: Colors.foreground
font.bold: true
font.pixelSize: 12
elide: Text.ElideRight
Layout.preferredWidth: implicitWidth
}
Text {
text: parent.parent.artist
color: Colors.foreground
opacity: 0.7
font.pixelSize: 10
Layout.preferredWidth: implicitWidth
}
}
// CONTROLS
RowLayout {
Layout.alignment: Qt.AlignVCenter
spacing: 8
visible: parent.visible
// PREV
Text {
text: "󰒮"
color: Colors.foreground
font.pixelSize: 24
MouseArea {
anchors.fill: parent
// Use modelData to control THIS player
onClicked: modelData.previous()
cursorShape: Qt.PointingHandCursor
}
}
// PLAY / PAUSE
Text {
text: parent.parent.isPlaying ? "󰏤" : "󰐊"
color: Colors.foreground
font.pixelSize: 24
MouseArea {
anchors.fill: parent
onClicked: modelData.playPause()
cursorShape: Qt.PointingHandCursor
}
}
// NEXT
Text {
text: "󰒭"
color: Colors.foreground
font.pixelSize: 24
MouseArea {
anchors.fill: parent
onClicked: modelData.next()
cursorShape: Qt.PointingHandCursor
}
}
}
}
}
}

View File

@ -0,0 +1,33 @@
import QtQuick
import Quickshell.Services.UPower
import qs
Item {
id: root
implicitWidth: 80
Text {
id: powerProfile
text: PowerProfile.toString(PowerProfiles.profile)
font.weight: 900
color: Colors.foreground
font.family: Appearance.font
font.pixelSize: Appearance.fontSize
anchors.centerIn: parent
MouseArea {
acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: Qt.OpenHandCursor
anchors.fill: parent
onClicked: mouse => {
const modes = [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance];
let current = PowerProfiles.profile;
let currentIndex = modes.indexOf(current);
let nextIndex = (currentIndex + 1) % modes.length;
let prevIndex = (currentIndex - 1) % modes.length;
if (mouse.button == Qt.LeftButton)
PowerProfiles.profile = modes[nextIndex];
if (mouse.button == Qt.RightButton)
PowerProfiles.profile = modes[prevIndex];
}
}
}
}

View File

@ -73,6 +73,8 @@ Item {
objects: Pipewire.defaultAudioSink
}
anchors.verticalCenter: parent.verticalCenter
width: 20
font.weight: 900
color: Colors.foreground
font.family: Appearance.font

View File

@ -59,7 +59,7 @@ WlrLayershell {
required property var modelData
Timer {
id: timout
interval: 5000
interval: 30000
running: true
onRunningChanged: notifyItem.modelData.dismiss()
}
@ -67,27 +67,30 @@ WlrLayershell {
Rectangle {
anchors.fill: parent
color: Colors.background
radius: 20
radius: 10
border.color: Colors.color5
// 2. Use RowLayout to put Image | Text side-by-side
RowLayout {
anchors.fill: parent
Row {
anchors.margins: 10
anchors.fill: parent
anchors.centerIn: parent
spacing: 15
// 🖼 THE IMAGE ON THE LEFT
Image {
// Use the image if available, otherwise hide this space?
// Or you could use an icon fallback.
source: notifyItem.modelData.image
anchors.verticalCenter: parent.verticalCenter
// Hide if no image exists so text takes full width
visible: notifyItem.modelData.image !== ""
// Fixed size for consistency
Layout.preferredWidth: 48
Layout.preferredHeight: 48
width: 48
height: 48
// Crop it nicely so it doesn't stretch
fillMode: Image.PreserveAspectCrop
@ -100,7 +103,7 @@ WlrLayershell {
ColumnLayout {
// Take up all remaining width
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter // Center vertically
Layout.alignment: Qt.AlignVCenter | Qt.AlignTop // Center vertically
spacing: 2
Text {
@ -128,6 +131,8 @@ WlrLayershell {
// (Your MouseArea for closing can still go here covering the whole thing)
MouseArea {
anchors.fill: parent
Layout.fillWidth: true
Layout.fillHeight: true
acceptedButtons: Qt.LeftButton
onClicked: notifyItem.modelData.dismiss()
}

View File

@ -1,7 +1,8 @@
import QtQuick
import Quickshell
import Quickshell.Wayland
import "." // <--- Ensures we can find ScreenCorners.qml
import "../../"
import "."
WlrLayershell {
id: overlayRoot
@ -29,7 +30,7 @@ WlrLayershell {
ScreenCorners {
// Adjust these to match your screen's aesthetic
cornerRadius: 25
cornerColor: "black"
cornerColor: Colors.background
shouldShow: true
// Ensure it stays on top of any other items in this window

View File

@ -1,8 +1,5 @@
import QtQuick
import QtQuick.Shapes
import qs
// removed "import qs.Commons" because you don't have it!
Item {
id: root
@ -17,7 +14,7 @@ Item {
// What color should the corners be? (Usually black to match the bezel)
// You can change this to "transparent" or a theme color if you want.
property color cornerColor: Colors.background
property color cornerColor
// Enable/Disable toggle
property bool shouldShow: true
@ -52,8 +49,7 @@ Item {
readonly property real screenHeight: cornersShape.height
strokeWidth: -1 // No outline
//fillColor: Colors.background
fillColor: "black"
fillColor: cornerColor
// Smooth fade if you toggle it

View File

@ -21,9 +21,8 @@ WlrLayershell {
// 1. The StackView manages the images
StackView {
id: wallStack
anchors.fill: parent
implicitWidth: Screen.width
implicitHeight: Screen.height
width: parent.width
height: parent.height
// 2. Define what a "Wallpaper" looks like
Component {