better widget style

This commit is contained in:
lucy 2025-12-28 17:36:11 +01:00
parent 484e1a8143
commit e6a8808858
6 changed files with 204 additions and 157 deletions

View File

@ -5,25 +5,25 @@ import Quickshell
Singleton {
id: customColors
// Core Backgrounds
readonly property color background: "#0A0E14"
readonly property color foreground: "#B3B1AD"
readonly property color cursor: "#E6B450"
readonly property color background: "#1A1B26"
readonly property color foreground: "#C0CAF5"
readonly property color cursor: "#C0CAF5"
// The 16 Colors of the Apocalypse
readonly property color color0: "#0A0E14"
readonly property color color1: "#FF3333"
readonly property color color2: "#C2D94C"
readonly property color color3: "#FF8F40"
readonly property color color4: "#59C2FF"
readonly property color color5: "#FFEE99"
readonly property color color6: "#95E6CB"
readonly property color color7: "#B3B1AD"
readonly property color color8: "#4D5566"
readonly property color color9: "#FF3333"
readonly property color color10: "#C2D94C"
readonly property color color11: "#FF8F40"
readonly property color color12: "#59C2FF"
readonly property color color13: "#FFEE99"
readonly property color color14: "#95E6CB"
readonly property color color15: "#B3B1AD"
readonly property color color0: "#414868"
readonly property color color1: "#F7768E"
readonly property color color2: "#9ECE6A"
readonly property color color3: "#E0AF68"
readonly property color color4: "#7AA2F7"
readonly property color color5: "#BB9AF7"
readonly property color color6: "#7DCFFF"
readonly property color color7: "#A9B1D6"
readonly property color color8: "#414868"
readonly property color color9: "#F7768E"
readonly property color color10: "#9ECE6A"
readonly property color color11: "#E0AF68"
readonly property color color12: "#7AA2F7"
readonly property color color13: "#BB9AF7"
readonly property color color14: "#7DCFFF"
readonly property color color15: "#C0CAF5"
}

View File

@ -1,14 +1,12 @@
import Quickshell
import QtQuick
import QtQuick.Layouts
import qs
import "../../"
PanelWindow {
id: root
required property var modelData
implicitHeight: 35
//color: Colors.background
implicitHeight: 34
color: Colors.background
anchors {
top: true

View File

@ -9,17 +9,41 @@ import Quickshell.Widgets
import "../settings/"
import "../../"
RowLayout {
Item {
id: root
implicitWidth: mprisRepeater.implicitWidth + 10
implicitHeight: 34
// 1. Let Repeater loop through the ObjectModel for us
Repeater {
id: mprisRepeater
model: Mpris.players
delegate: RowLayout {
id: delegateLayout
delegate: Item {
required property var modelData
implicitHeight: 34
implicitWidth: delegateLayout.implicitWidth
MouseArea {
id: playbackControl
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: mouse => {
if (mouse.button == Qt.LeftButton) {
console.log("Left button press");
}
if (mouse.button == Qt.RightButton) {
parent.modelData.togglePlaying();
}
}
onDoubleClicked: mouse => {
if (mouse.button == Qt.LeftButton) {
parent.modelData.next();
}
}
}
RowLayout {
id: delegateLayout
// 2. 🕵 FILTER LOGIC
// Check if this specific player is Spotify.
// We verify 'modelData' exists and check the name.
@ -32,11 +56,6 @@ RowLayout {
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
@ -45,6 +64,7 @@ RowLayout {
spacing: 10
// 🖼 ALBUM ART
ClippingWrapperRectangle {
Layout.alignment: Qt.AlignVCenter
@ -53,7 +73,7 @@ RowLayout {
IconImage {
source: delegateLayout.artUrl // Access property from delegate
asynchronous: true
implicitSize: 24
implicitSize: root.implicitHeight * 0.6
}
}
@ -82,8 +102,7 @@ RowLayout {
Layout.preferredWidth: implicitWidth
}
}
// CONTROLS
}
}
}
}

View File

@ -1,23 +1,17 @@
import QtQuick
import Quickshell.Services.UPower
import QtQuick.Layouts
import "../settings/"
import "../../"
Item {
id: root
implicitWidth: 80
Text {
id: powerProfile
text: PowerProfile.toString(PowerProfiles.profile)
font.weight: 900
color: Colors.foreground
font.family: Settings.font
font.pixelSize: Settings.fontSize
anchors.centerIn: parent
implicitWidth: powerLayout.implicitWidth + 10
implicitHeight: 34
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
onClicked: mouse => {
const modes = [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance];
let current = PowerProfiles.profile;
@ -30,5 +24,25 @@ Item {
PowerProfiles.profile = modes[prevIndex];
}
}
ColumnLayout {
id: powerLayout
anchors.centerIn: parent
spacing: 0
Text {
id: powerProfile
text: PowerProfile.toString(PowerProfiles.profile)
font.weight: 900
color: Colors.foreground
font.family: Settings.font
font.pixelSize: Settings.fontSize
}
Text {
text: "Profile"
font.weight: 900
color: Colors.foreground
font.family: Settings.font
font.pixelSize: Settings.fontSize - 2
opacity: 0.7
}
}
}

View File

@ -1,30 +1,29 @@
import QtQuick
import Quickshell.Services.Pipewire
import Quickshell.Widgets
import QtQuick.Layouts
import Quickshell.Io
import "../../"
import "../settings/"
Item {
id: root
implicitWidth: volRow.implicitWidth + 10
implicitHeight: volRow.implicitHeight
// grab the default speaker (Sink)
property var sink: Pipewire.defaultAudioSink
Process {
id: pavu
command: ["pavucontrol"] // The command and args list
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: mouse => {
if (mouse.button === Qt.LeftButton) {
pavu.startDetached();
}
}
anchors.fill: parent
// Scroll to change volume (The fancy stuff!)
}
implicitWidth: styleLayout.implicitWidth + 10
implicitHeight: 34
property var sink: Pipewire.defaultAudioSink
Process {
id: pavu
command: ["pavucontrol"] // The command and args list
}
// Logic to pick the correct icon name
function getVolumeIcon() {
@ -50,29 +49,37 @@ Item {
return "audio-volume-high";
}
Row {
id: volRow
ColumnLayout {
id: styleLayout
anchors.centerIn: parent
spacing: 5
spacing: 0
Row {
spacing: 10
Text {
PwObjectTracker {
objects: Pipewire.ready ? root.sink : []
}
font.weight: 900
color: Colors.foreground
font.family: Settings.font
font.pixelSize: Settings.fontSize
text: Pipewire.ready ? Math.round(root.sink.audio.volume * 100) + "%" : "0%"
}
IconImage {
anchors.verticalCenter: parent.verticalCenter
width: 12
height: 12
source: "root:/icons/" + root.getVolumeIcon() + "-symbolic.svg"
}
Text {
PwObjectTracker {
objects: Pipewire.ready ? Pipewire.defaultAudioSink : []
}
width: 20
Text {
font.weight: 900
color: Colors.foreground
font.family: Settings.font
font.pixelSize: Settings.fontSize
text: Pipewire.ready ? Math.round(Pipewire.defaultAudioSink.audio.volume * 100) + "%" : "0%"
font.pixelSize: Settings.fontSize - 2
opacity: 0.7
text: Pipewire.ready ? Pipewire.defaultAudioSink.nickname : "failure"
}
}
}

View File

@ -6,6 +6,8 @@ import Quickshell.Hyprland
import "."
import "../../"
import QtQuick.Layouts
import Quickshell.Widgets
import "../settings/"
WlrLayershell {
id: root
@ -29,7 +31,7 @@ WlrLayershell {
right: true
}
margins {
top: 30
top: 45
right: 10
}
@ -52,7 +54,7 @@ WlrLayershell {
ListView {
id: notifList
anchors.fill: parent
anchors.margins: 10
anchors.margins: 0
// Use 'spacing' to put gaps between notifications
spacing: 10
@ -68,12 +70,12 @@ WlrLayershell {
delegate: Item {
id: notifyItem
implicitWidth: ListView.view.width
implicitHeight: 80 // Fixed height is usually better for icon layouts
implicitHeight: 85 // Fixed height is usually better for icon layouts
required property var modelData
Timer {
id: timout
interval: 3000000
interval: 3000
running: true
onRunningChanged: notifyItem.modelData.dismiss()
}
@ -81,18 +83,24 @@ WlrLayershell {
Rectangle {
anchors.fill: parent
color: Colors.background
radius: 10
radius: 20
border.color: Colors.color5
border.width: 2
// 2. Use RowLayout to put Image | Text side-by-side
RowLayout {
id: fullLayout
anchors.margins: 10
anchors.fill: parent
spacing: 15
spacing: 10
// 🖼 THE IMAGE ON THE LEFT
Image {
ClippingWrapperRectangle {
radius: 10
implicitWidth: 64
implicitHeight: 64
visible: notifyItem.modelData.image !== ""
IconImage {
// Use the image if available, otherwise hide this space?
// Or you could use an icon fallback.
@ -102,29 +110,28 @@ WlrLayershell {
visible: notifyItem.modelData.image !== ""
// Fixed size for consistency
sourceSize.width: 48
sourceSize.height: 48
Layout.preferredWidth: 48
Layout.preferredHeight: 48
implicitSize: 30
// Crop it nicely so it doesn't stretch
fillMode: Image.PreserveAspectCrop
// Optional: Cache it for performance
asynchronous: true
}
}
// 📝 THE TEXT ON THE RIGHT
ColumnLayout {
id: textLayout
// Take up all remaining width
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignTop // Center vertically
Layout.alignment: Qt.AlignVCenter // Center vertically
spacing: 2
Text {
text: notifyItem.modelData.summary
color: Colors.foreground
font.family: Settings.font
font.pixelSize: Settings.fontSize
font.bold: true
elide: Text.ElideRight
Layout.fillWidth: true
@ -135,7 +142,9 @@ WlrLayershell {
color: Colors.foreground
// Limit to 2 lines
maximumLineCount: 2
font.family: Settings.font
font.pixelSize: Settings.fontSize - 2
maximumLineCount: 3
wrapMode: Text.WordWrap
elide: Text.ElideRight
Layout.fillWidth: true