mpris widget in bar yippie ^_^
This commit is contained in:
parent
38173b9959
commit
d72adec2ef
@ -5,7 +5,7 @@ import Quickshell
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: customColors
|
id: customColors
|
||||||
// Core Backgrounds
|
// Core Backgrounds
|
||||||
readonly property color background: "#1A1B26"
|
readonly property color background: "#24283B"
|
||||||
readonly property color foreground: "#C0CAF5"
|
readonly property color foreground: "#C0CAF5"
|
||||||
readonly property color cursor: "#C0CAF5"
|
readonly property color cursor: "#C0CAF5"
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ Singleton {
|
|||||||
readonly property color color4: "#7AA2F7"
|
readonly property color color4: "#7AA2F7"
|
||||||
readonly property color color5: "#BB9AF7"
|
readonly property color color5: "#BB9AF7"
|
||||||
readonly property color color6: "#7DCFFF"
|
readonly property color color6: "#7DCFFF"
|
||||||
readonly property color color7: "#A9B1D6"
|
readonly property color color7: "#C0CAF5"
|
||||||
readonly property color color8: "#414868"
|
readonly property color color8: "#414868"
|
||||||
readonly property color color9: "#F7768E"
|
readonly property color color9: "#F7768E"
|
||||||
readonly property color color10: "#9ECE6A"
|
readonly property color color10: "#9ECE6A"
|
||||||
|
|||||||
@ -8,7 +8,7 @@ PanelWindow {
|
|||||||
required property var modelData
|
required property var modelData
|
||||||
implicitHeight: 30
|
implicitHeight: 30
|
||||||
//color: Colors.background
|
//color: Colors.background
|
||||||
color: "black"
|
color: Colors.background
|
||||||
anchors {
|
anchors {
|
||||||
top: true
|
top: true
|
||||||
left: true
|
left: true
|
||||||
@ -17,11 +17,13 @@ PanelWindow {
|
|||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: leftLayout
|
id: leftLayout
|
||||||
|
spacing: 30
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
Clock {
|
Clock {
|
||||||
Layout.leftMargin: 30
|
Layout.leftMargin: 30
|
||||||
}
|
}
|
||||||
|
Mpris {}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
@ -37,6 +39,7 @@ PanelWindow {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
Volume {}
|
Volume {}
|
||||||
Battery {}
|
Battery {}
|
||||||
|
PowerProfiles {}
|
||||||
SystemTray {
|
SystemTray {
|
||||||
Layout.rightMargin: 30
|
Layout.rightMargin: 30
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,26 +27,5 @@ Item {
|
|||||||
color: Colors.foreground
|
color: Colors.foreground
|
||||||
text: Math.round(UPower.displayDevice.percentage * 100) + "%"
|
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
134
modules/bar/Mpris.qml
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
modules/bar/PowerProfiles.qml
Normal file
33
modules/bar/PowerProfiles.qml
Normal 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -73,6 +73,8 @@ Item {
|
|||||||
|
|
||||||
objects: Pipewire.defaultAudioSink
|
objects: Pipewire.defaultAudioSink
|
||||||
}
|
}
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 20
|
||||||
font.weight: 900
|
font.weight: 900
|
||||||
color: Colors.foreground
|
color: Colors.foreground
|
||||||
font.family: Appearance.font
|
font.family: Appearance.font
|
||||||
|
|||||||
@ -59,7 +59,7 @@ WlrLayershell {
|
|||||||
required property var modelData
|
required property var modelData
|
||||||
Timer {
|
Timer {
|
||||||
id: timout
|
id: timout
|
||||||
interval: 5000
|
interval: 30000
|
||||||
running: true
|
running: true
|
||||||
onRunningChanged: notifyItem.modelData.dismiss()
|
onRunningChanged: notifyItem.modelData.dismiss()
|
||||||
}
|
}
|
||||||
@ -67,27 +67,30 @@ WlrLayershell {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: Colors.background
|
color: Colors.background
|
||||||
radius: 20
|
radius: 10
|
||||||
border.color: Colors.color5
|
border.color: Colors.color5
|
||||||
|
|
||||||
// 2. Use RowLayout to put Image | Text side-by-side
|
// 2. Use RowLayout to put Image | Text side-by-side
|
||||||
RowLayout {
|
Row {
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 10
|
anchors.margins: 10
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.centerIn: parent
|
||||||
spacing: 15
|
spacing: 15
|
||||||
|
|
||||||
// 🖼️ THE IMAGE ON THE LEFT
|
// 🖼️ THE IMAGE ON THE LEFT
|
||||||
Image {
|
Image {
|
||||||
|
|
||||||
// Use the image if available, otherwise hide this space?
|
// Use the image if available, otherwise hide this space?
|
||||||
// Or you could use an icon fallback.
|
// Or you could use an icon fallback.
|
||||||
source: notifyItem.modelData.image
|
source: notifyItem.modelData.image
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
// Hide if no image exists so text takes full width
|
// Hide if no image exists so text takes full width
|
||||||
visible: notifyItem.modelData.image !== ""
|
visible: notifyItem.modelData.image !== ""
|
||||||
|
|
||||||
// Fixed size for consistency
|
// Fixed size for consistency
|
||||||
Layout.preferredWidth: 48
|
width: 48
|
||||||
Layout.preferredHeight: 48
|
height: 48
|
||||||
|
|
||||||
// Crop it nicely so it doesn't stretch
|
// Crop it nicely so it doesn't stretch
|
||||||
fillMode: Image.PreserveAspectCrop
|
fillMode: Image.PreserveAspectCrop
|
||||||
@ -100,7 +103,7 @@ WlrLayershell {
|
|||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
// Take up all remaining width
|
// Take up all remaining width
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.alignment: Qt.AlignVCenter // Center vertically
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignTop // Center vertically
|
||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
@ -128,6 +131,8 @@ WlrLayershell {
|
|||||||
// (Your MouseArea for closing can still go here covering the whole thing)
|
// (Your MouseArea for closing can still go here covering the whole thing)
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onClicked: notifyItem.modelData.dismiss()
|
onClicked: notifyItem.modelData.dismiss()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import "." // <--- Ensures we can find ScreenCorners.qml
|
import "../../"
|
||||||
|
import "."
|
||||||
|
|
||||||
WlrLayershell {
|
WlrLayershell {
|
||||||
id: overlayRoot
|
id: overlayRoot
|
||||||
@ -29,7 +30,7 @@ WlrLayershell {
|
|||||||
ScreenCorners {
|
ScreenCorners {
|
||||||
// Adjust these to match your screen's aesthetic
|
// Adjust these to match your screen's aesthetic
|
||||||
cornerRadius: 25
|
cornerRadius: 25
|
||||||
cornerColor: "black"
|
cornerColor: Colors.background
|
||||||
shouldShow: true
|
shouldShow: true
|
||||||
|
|
||||||
// Ensure it stays on top of any other items in this window
|
// Ensure it stays on top of any other items in this window
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Shapes
|
import QtQuick.Shapes
|
||||||
import qs
|
|
||||||
|
|
||||||
// removed "import qs.Commons" because you don't have it!
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@ -17,7 +14,7 @@ Item {
|
|||||||
|
|
||||||
// What color should the corners be? (Usually black to match the bezel)
|
// 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.
|
// You can change this to "transparent" or a theme color if you want.
|
||||||
property color cornerColor: Colors.background
|
property color cornerColor
|
||||||
|
|
||||||
// Enable/Disable toggle
|
// Enable/Disable toggle
|
||||||
property bool shouldShow: true
|
property bool shouldShow: true
|
||||||
@ -52,8 +49,7 @@ Item {
|
|||||||
readonly property real screenHeight: cornersShape.height
|
readonly property real screenHeight: cornersShape.height
|
||||||
|
|
||||||
strokeWidth: -1 // No outline
|
strokeWidth: -1 // No outline
|
||||||
//fillColor: Colors.background
|
fillColor: cornerColor
|
||||||
fillColor: "black"
|
|
||||||
|
|
||||||
// Smooth fade if you toggle it
|
// Smooth fade if you toggle it
|
||||||
|
|
||||||
|
|||||||
@ -21,9 +21,8 @@ WlrLayershell {
|
|||||||
// 1. The StackView manages the images
|
// 1. The StackView manages the images
|
||||||
StackView {
|
StackView {
|
||||||
id: wallStack
|
id: wallStack
|
||||||
anchors.fill: parent
|
width: parent.width
|
||||||
implicitWidth: Screen.width
|
height: parent.height
|
||||||
implicitHeight: Screen.height
|
|
||||||
|
|
||||||
// 2. Define what a "Wallpaper" looks like
|
// 2. Define what a "Wallpaper" looks like
|
||||||
Component {
|
Component {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user