Compare commits
No commits in common. "d72adec2efdb44cb0916b32f9489a669fe557159" and "b97ac0276c3ebc35a1a952ba9bb2aeaba6c2c49c" have entirely different histories.
d72adec2ef
...
b97ac0276c
29
Colors.qml
29
Colors.qml
@ -1,29 +0,0 @@
|
|||||||
pragma Singleton
|
|
||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
|
|
||||||
Singleton {
|
|
||||||
id: customColors
|
|
||||||
// Core Backgrounds
|
|
||||||
readonly property color background: "#24283B"
|
|
||||||
readonly property color foreground: "#C0CAF5"
|
|
||||||
readonly property color cursor: "#C0CAF5"
|
|
||||||
|
|
||||||
// The 16 Colors of the Apocalypse
|
|
||||||
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: "#C0CAF5"
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
@ -2,6 +2,6 @@ pragma Singleton
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
readonly property string font: "Iosevka Nerd Font Propo"
|
readonly property string font: "JetBrainsMono Nerd Font"
|
||||||
readonly property real fontSize: 14
|
readonly property real fontSize: 14
|
||||||
}
|
}
|
||||||
@ -1,13 +1,11 @@
|
|||||||
import Quickshell
|
import Quickshell
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
import qs.modules.bar
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import qs
|
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: root
|
id: root
|
||||||
required property var modelData
|
|
||||||
implicitHeight: 30
|
implicitHeight: 30
|
||||||
//color: Colors.background
|
|
||||||
color: Colors.background
|
color: Colors.background
|
||||||
anchors {
|
anchors {
|
||||||
top: true
|
top: true
|
||||||
@ -17,31 +15,25 @@ 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 {
|
Workspaces {}
|
||||||
Layout.leftMargin: 30
|
|
||||||
}
|
|
||||||
Mpris {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: centerLayout
|
id: centerLayout
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
Workspaces {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: rightLayout
|
id: rightLayout
|
||||||
spacing: 20
|
spacing: 0
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
Volume {}
|
Volume {}
|
||||||
Battery {}
|
Battery {}
|
||||||
PowerProfiles {}
|
|
||||||
SystemTray {
|
SystemTray {
|
||||||
Layout.rightMargin: 30
|
Layout.rightMargin: 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
import Quickshell.Services.UPower
|
import Quickshell.Services.UPower
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell.Widgets
|
import Quickshell.Widgets
|
||||||
import "."
|
|
||||||
import qs
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@ -11,17 +9,14 @@ Item {
|
|||||||
Row {
|
Row {
|
||||||
id: batRow
|
id: batRow
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: 5
|
spacing: 0
|
||||||
IconImage {
|
IconImage {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
source: "root:/icons/" + UPower.displayDevice.iconName + ".svg"
|
source: "root:/icons/" + UPower.displayDevice.iconName + ".svg"
|
||||||
width: 12
|
implicitWidth: 16
|
||||||
height: 12
|
implicitHeight: 16
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
id: batteryText
|
id: batteryText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
font.weight: 900
|
|
||||||
font.family: Appearance.font
|
font.family: Appearance.font
|
||||||
font.pixelSize: Appearance.fontSize
|
font.pixelSize: Appearance.fontSize
|
||||||
color: Colors.foreground
|
color: Colors.foreground
|
||||||
|
|||||||
@ -1,26 +1,12 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import qs
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
// FIX: Real pixels please!
|
implicitWidth: clockText.text.length + 10
|
||||||
implicitWidth: clockText.implicitWidth
|
|
||||||
implicitHeight: 30
|
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: clockText
|
id: clockText
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
font.weight: 900
|
text: "sigma balls"
|
||||||
font.family: Appearance.font
|
|
||||||
font.pixelSize: Appearance.fontSize
|
|
||||||
color: Colors.foreground
|
|
||||||
|
|
||||||
text: Qt.formatDateTime(clock.date, "hh:mm")
|
|
||||||
|
|
||||||
SystemClock {
|
|
||||||
id: clock
|
|
||||||
precision: SystemClock.Minutes
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
29
modules/bar/Colors.qml
Normal file
29
modules/bar/Colors.qml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
pragma Singleton
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: customColors
|
||||||
|
// Core Backgrounds
|
||||||
|
readonly property color background: "#1F1F28"
|
||||||
|
readonly property color foreground: "#DCD7BA"
|
||||||
|
readonly property color cursor: "#DCD7BA"
|
||||||
|
|
||||||
|
// The 16 Colors of the Apocalypse
|
||||||
|
readonly property color color0: "#090618"
|
||||||
|
readonly property color color1: "#C34043"
|
||||||
|
readonly property color color2: "#76946A"
|
||||||
|
readonly property color color3: "#C0A36E"
|
||||||
|
readonly property color color4: "#7E9CD8"
|
||||||
|
readonly property color color5: "#957FB8"
|
||||||
|
readonly property color color6: "#6A9589"
|
||||||
|
readonly property color color7: "#C8C093"
|
||||||
|
readonly property color color8: "#727169"
|
||||||
|
readonly property color color9: "#E82424"
|
||||||
|
readonly property color color10: "#98BB6C"
|
||||||
|
readonly property color color11: "#E6C384"
|
||||||
|
readonly property color color12: "#7FB4CA"
|
||||||
|
readonly property color color13: "#938AA9"
|
||||||
|
readonly property color color14: "#7AA89F"
|
||||||
|
readonly property color color15: "#DCD7BA"
|
||||||
|
}
|
||||||
@ -1,134 +0,0 @@
|
|||||||
// ⚠️ 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -6,7 +6,7 @@ Item {
|
|||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
// This was already correct in your last file, but keep it this way!
|
// This was already correct in your last file, but keep it this way!
|
||||||
implicitWidth: layout.implicitWidth
|
implicitWidth: layout.implicitWidth + 10
|
||||||
implicitHeight: 30
|
implicitHeight: 30
|
||||||
|
|
||||||
// Hide if empty so we don't have a 50px gap for nothing
|
// Hide if empty so we don't have a 50px gap for nothing
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.SystemTray
|
import Quickshell.Services.SystemTray
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell.Services.Pipewire
|
import Quickshell.Services.Pipewire
|
||||||
import Quickshell.Widgets
|
import Quickshell.Widgets
|
||||||
import Quickshell.Io
|
|
||||||
import qs
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@ -10,23 +8,7 @@ Item {
|
|||||||
implicitHeight: volRow.implicitHeight
|
implicitHeight: volRow.implicitHeight
|
||||||
// grab the default speaker (Sink)
|
// grab the default speaker (Sink)
|
||||||
property var sink: Pipewire.defaultAudioSink
|
property var sink: Pipewire.defaultAudioSink
|
||||||
Process {
|
|
||||||
id: pavu
|
|
||||||
command: ["pavucontrol"] // The command and args list
|
|
||||||
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
cursorShape: Qt.OpenHandCursor
|
|
||||||
onClicked: mouse => {
|
|
||||||
if (mouse.button === Qt.LeftButton) {
|
|
||||||
// Left Click: Summon the Mixer!
|
|
||||||
console.log("Summoning Pavucontrol... Nya!");
|
|
||||||
pavu.startDetached();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
anchors.fill: parent
|
|
||||||
// Scroll to change volume (The fancy stuff!)
|
|
||||||
}
|
|
||||||
// Logic to pick the correct icon name
|
// Logic to pick the correct icon name
|
||||||
function getVolumeIcon() {
|
function getVolumeIcon() {
|
||||||
// Safety check: if Pipewire is dead or sink is missing
|
// Safety check: if Pipewire is dead or sink is missing
|
||||||
@ -57,9 +39,8 @@ Item {
|
|||||||
spacing: 5
|
spacing: 5
|
||||||
|
|
||||||
IconImage {
|
IconImage {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
width: 16
|
||||||
width: 12
|
height: 16
|
||||||
height: 12
|
|
||||||
|
|
||||||
// The magic: 'image://theme/' pulls from your system icon theme (Papirus, Adwaita, etc.)
|
// The magic: 'image://theme/' pulls from your system icon theme (Papirus, Adwaita, etc.)
|
||||||
source: "root:/icons/" + root.getVolumeIcon() + "-symbolic.svg"
|
source: "root:/icons/" + root.getVolumeIcon() + "-symbolic.svg"
|
||||||
@ -70,16 +51,30 @@ Item {
|
|||||||
|
|
||||||
Text {
|
Text {
|
||||||
PwObjectTracker {
|
PwObjectTracker {
|
||||||
|
|
||||||
objects: Pipewire.defaultAudioSink
|
objects: Pipewire.defaultAudioSink
|
||||||
}
|
}
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
width: 20
|
|
||||||
font.weight: 900
|
|
||||||
color: Colors.foreground
|
color: Colors.foreground
|
||||||
font.family: Appearance.font
|
font.family: Appearance.font
|
||||||
font.pixelSize: Appearance.fontSize
|
font.pixelSize: Appearance.fontSize
|
||||||
text: Math.round(Pipewire.defaultAudioSink.audio.volume * 100) + "%"
|
text: Math.round(Pipewire.defaultAudioSink.audio.volume * 100) + "%"
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
if (root.sink) {
|
||||||
|
root.sink.audio.muted = !root.sink.audio.muted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Scroll to change volume (The fancy stuff!)
|
||||||
|
onWheel: wheel => {
|
||||||
|
if (root.sink) {
|
||||||
|
if (wheel.angleDelta.y > 0) {
|
||||||
|
root.sink.audio.volume += 0.05; // Up 5%
|
||||||
|
} else {
|
||||||
|
root.sink.audio.volume -= 0.05; // Down 5%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Click to toggle mute! (Bonus feature)
|
// Click to toggle mute! (Bonus feature)
|
||||||
|
|||||||
@ -1,37 +1,38 @@
|
|||||||
|
|
||||||
|
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import qs
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
property var modelData
|
implicitWidth: workspaceRepeater.count * 30
|
||||||
implicitWidth: workspaceRow.implicitWidth
|
|
||||||
height: 30
|
height: 30
|
||||||
Row {
|
Row {
|
||||||
id: workspaceRow
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: 10 // Slightly increase spacing between workspace buttons
|
spacing: 10 // Slightly increase spacing between workspace buttons
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
anchors.centerIn: parent
|
id: workspaceRepeater
|
||||||
|
model: Hyprland.workspaces
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: workspaceNumber
|
width: 20
|
||||||
width: 16
|
height: 20
|
||||||
height: 16
|
|
||||||
radius: 20
|
radius: 20
|
||||||
|
//color: modelData.active ? myPallete.accent : myPallete.window
|
||||||
color: modelData.active ? Colors.foreground : "transparent"
|
color: modelData.active ? Colors.foreground : "transparent"
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
id: workspaceNumber
|
||||||
font.weight: 900
|
font.weight: 900
|
||||||
font.family: Appearance.font
|
font.family: Appearance.font
|
||||||
font.pixelSize: Appearance.fontSize
|
font.pixelSize: Appearance.fontSize
|
||||||
anchors.centerIn: workspaceNumber
|
anchors.centerIn: parent
|
||||||
text: modelData.id
|
text: modelData.id
|
||||||
color: modelData.active ? Colors.background : Colors.foreground // Set contrasting color for workspace number
|
color: modelData.active ? Colors.background : Colors.foreground // Set contrasting color for workspace number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
model: Hyprland.workspaces
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,142 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Wayland
|
|
||||||
import qs
|
|
||||||
import "."
|
|
||||||
import QtQuick.Layouts
|
|
||||||
|
|
||||||
WlrLayershell {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
// 1. Position: Top Right Corner, covering the full height
|
|
||||||
// We make it a fixed width (e.g., 400px) so it doesn't block the whole screen
|
|
||||||
anchors {
|
|
||||||
top: true
|
|
||||||
right: true
|
|
||||||
}
|
|
||||||
margins {
|
|
||||||
top: 30
|
|
||||||
}
|
|
||||||
|
|
||||||
implicitWidth: 400
|
|
||||||
implicitHeight: notifList.contentHeight + 10
|
|
||||||
|
|
||||||
// 2. Layer: Put it ABOVE normal windows
|
|
||||||
layer: WlrLayer.Overlay
|
|
||||||
exclusionMode: ExclusionMode.Ignore
|
|
||||||
|
|
||||||
// 3. CRITICAL: Make the window itself invisible!
|
|
||||||
// We only want to see the notifications, not the container.
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
// 4. Input: Let clicks pass through empty areas
|
|
||||||
// (This is default behavior if the background is transparent in some compositors,
|
|
||||||
// but usually you need to be careful with handling mouse events here)
|
|
||||||
|
|
||||||
// THE SPAWNER
|
|
||||||
ListView {
|
|
||||||
id: notifList
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 10
|
|
||||||
// Use 'spacing' to put gaps between notifications
|
|
||||||
spacing: 10
|
|
||||||
|
|
||||||
// Align to the bottom (like Windows) or Top (like GNOME)?
|
|
||||||
// verticalLayoutDirection: ListView.BottomToTop
|
|
||||||
|
|
||||||
// 🔗 CONNECT TO THE SERVER
|
|
||||||
// Assuming your NotificationServer is a singleton or globally accessible
|
|
||||||
// ... other imports
|
|
||||||
|
|
||||||
// Inside your ListView...
|
|
||||||
model: NotifServer.trackedNotifications
|
|
||||||
delegate: Item {
|
|
||||||
id: notifyItem
|
|
||||||
implicitWidth: ListView.view.width
|
|
||||||
implicitHeight: 60 // Fixed height is usually better for icon layouts
|
|
||||||
|
|
||||||
required property var modelData
|
|
||||||
Timer {
|
|
||||||
id: timout
|
|
||||||
interval: 30000
|
|
||||||
running: true
|
|
||||||
onRunningChanged: notifyItem.modelData.dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: Colors.background
|
|
||||||
radius: 10
|
|
||||||
border.color: Colors.color5
|
|
||||||
|
|
||||||
// 2. Use RowLayout to put Image | Text side-by-side
|
|
||||||
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
|
|
||||||
width: 48
|
|
||||||
height: 48
|
|
||||||
|
|
||||||
// Crop it nicely so it doesn't stretch
|
|
||||||
fillMode: Image.PreserveAspectCrop
|
|
||||||
|
|
||||||
// Optional: Cache it for performance
|
|
||||||
asynchronous: true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 📝 THE TEXT ON THE RIGHT
|
|
||||||
ColumnLayout {
|
|
||||||
// Take up all remaining width
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignTop // Center vertically
|
|
||||||
spacing: 2
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: notifyItem.modelData.summary
|
|
||||||
color: Colors.foreground
|
|
||||||
font.bold: true
|
|
||||||
elide: Text.ElideRight
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: notifyItem.modelData.body
|
|
||||||
color: Colors.foreground
|
|
||||||
|
|
||||||
// Limit to 2 lines
|
|
||||||
maximumLineCount: 2
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
elide: Text.ElideRight
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// (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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
pragma Singleton
|
|
||||||
import Quickshell.Services.Notifications
|
|
||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
|
|
||||||
NotificationServer {
|
|
||||||
bodyMarkupSupported: true
|
|
||||||
persistenceSupported: true
|
|
||||||
imageSupported: true
|
|
||||||
onNotification: notification => {
|
|
||||||
notification.tracked = true;
|
|
||||||
console.log("got notification!!! arf woof");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
singleton NotifServer 1.0 NotifServer.qml
|
|
||||||
NotiPopup 1.0 NotiPopup.qml
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Wayland
|
|
||||||
import "../../"
|
|
||||||
import "."
|
|
||||||
|
|
||||||
WlrLayershell {
|
|
||||||
id: overlayRoot
|
|
||||||
|
|
||||||
// 1. Fill the entire screen
|
|
||||||
anchors {
|
|
||||||
top: true
|
|
||||||
bottom: true
|
|
||||||
left: true
|
|
||||||
right: true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Sit on top of EVERYTHING (even fullscreen apps if compositor allows)
|
|
||||||
layer: WlrLayer.Top
|
|
||||||
|
|
||||||
// 3. Invisible background
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
// 4. 👻 GHOST MODE ENABLED 👻
|
|
||||||
// An empty Region means "I accept mouse events nowhere".
|
|
||||||
// This guarantees you can click through the black corners.
|
|
||||||
mask: Region {}
|
|
||||||
|
|
||||||
// 5. Load the corners!
|
|
||||||
ScreenCorners {
|
|
||||||
// Adjust these to match your screen's aesthetic
|
|
||||||
cornerRadius: 25
|
|
||||||
cornerColor: Colors.background
|
|
||||||
shouldShow: true
|
|
||||||
|
|
||||||
// Ensure it stays on top of any other items in this window
|
|
||||||
z: 999
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,175 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Shapes
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
// ---------------------------------------------------------
|
|
||||||
// 🛠️ CONFIGURATION (Tweaked to match your setup)
|
|
||||||
// ---------------------------------------------------------
|
|
||||||
|
|
||||||
// How round do you want the screen?
|
|
||||||
property real cornerRadius: 20
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// Enable/Disable toggle
|
|
||||||
property bool shouldShow: true
|
|
||||||
|
|
||||||
// ---------------------------------------------------------
|
|
||||||
|
|
||||||
// Wrapper with layer caching to reduce GPU usage
|
|
||||||
Item {
|
|
||||||
anchors.fill: parent
|
|
||||||
layer.enabled: true
|
|
||||||
|
|
||||||
Shape {
|
|
||||||
id: cornersShape
|
|
||||||
anchors.fill: parent
|
|
||||||
preferredRendererType: Shape.CurveRenderer
|
|
||||||
enabled: false // Click-through
|
|
||||||
|
|
||||||
ShapePath {
|
|
||||||
id: cornersPath
|
|
||||||
|
|
||||||
// Map our local properties to the variables the code expects
|
|
||||||
readonly property real cornerRadius: root.cornerRadius
|
|
||||||
readonly property real cornerSize: root.cornerRadius // Usually same as radius
|
|
||||||
|
|
||||||
// Margins (Leave 0 unless your bar overlaps)
|
|
||||||
readonly property real topMargin: 0
|
|
||||||
readonly property real bottomMargin: 0
|
|
||||||
readonly property real leftMargin: 0
|
|
||||||
readonly property real rightMargin: 0
|
|
||||||
|
|
||||||
readonly property real screenWidth: cornersShape.width
|
|
||||||
readonly property real screenHeight: cornersShape.height
|
|
||||||
|
|
||||||
strokeWidth: -1 // No outline
|
|
||||||
fillColor: cornerColor
|
|
||||||
|
|
||||||
// Smooth fade if you toggle it
|
|
||||||
|
|
||||||
// ==========================================
|
|
||||||
// 📐 GEOMETRY LOGIC (Untouched)
|
|
||||||
// ==========================================
|
|
||||||
|
|
||||||
// Top-Left
|
|
||||||
startX: leftMargin
|
|
||||||
startY: topMargin
|
|
||||||
PathLine {
|
|
||||||
relativeX: cornersPath.cornerSize
|
|
||||||
relativeY: 0
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: 0
|
|
||||||
relativeY: cornersPath.cornerSize - cornersPath.cornerRadius
|
|
||||||
}
|
|
||||||
PathArc {
|
|
||||||
relativeX: -cornersPath.cornerRadius
|
|
||||||
relativeY: cornersPath.cornerRadius
|
|
||||||
radiusX: cornersPath.cornerRadius
|
|
||||||
radiusY: cornersPath.cornerRadius
|
|
||||||
direction: PathArc.Counterclockwise
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: -(cornersPath.cornerSize - cornersPath.cornerRadius)
|
|
||||||
relativeY: 0
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: 0
|
|
||||||
relativeY: -cornersPath.cornerSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// Top-Right
|
|
||||||
PathMove {
|
|
||||||
x: cornersPath.screenWidth - cornersPath.rightMargin - cornersPath.cornerSize
|
|
||||||
y: cornersPath.topMargin
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: cornersPath.cornerSize
|
|
||||||
relativeY: 0
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: 0
|
|
||||||
relativeY: cornersPath.cornerSize
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: -(cornersPath.cornerSize - cornersPath.cornerRadius)
|
|
||||||
relativeY: 0
|
|
||||||
}
|
|
||||||
PathArc {
|
|
||||||
relativeX: -cornersPath.cornerRadius
|
|
||||||
relativeY: -cornersPath.cornerRadius
|
|
||||||
radiusX: cornersPath.cornerRadius
|
|
||||||
radiusY: cornersPath.cornerRadius
|
|
||||||
direction: PathArc.Counterclockwise
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: 0
|
|
||||||
relativeY: -(cornersPath.cornerSize - cornersPath.cornerRadius)
|
|
||||||
}
|
|
||||||
// Bottom-Left
|
|
||||||
PathMove {
|
|
||||||
x: cornersPath.leftMargin
|
|
||||||
y: cornersPath.screenHeight - cornersPath.bottomMargin - cornersPath.cornerSize
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: cornersPath.cornerSize - cornersPath.cornerRadius
|
|
||||||
relativeY: 0
|
|
||||||
}
|
|
||||||
PathArc {
|
|
||||||
relativeX: cornersPath.cornerRadius
|
|
||||||
relativeY: cornersPath.cornerRadius
|
|
||||||
radiusX: cornersPath.cornerRadius
|
|
||||||
radiusY: cornersPath.cornerRadius
|
|
||||||
direction: PathArc.Counterclockwise
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: 0
|
|
||||||
relativeY: cornersPath.cornerSize - cornersPath.cornerRadius
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: -cornersPath.cornerSize
|
|
||||||
relativeY: 0
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: 0
|
|
||||||
relativeY: -cornersPath.cornerSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bottom-Right
|
|
||||||
PathMove {
|
|
||||||
x: cornersPath.screenWidth - cornersPath.rightMargin
|
|
||||||
y: cornersPath.screenHeight - cornersPath.bottomMargin
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: -cornersPath.cornerSize
|
|
||||||
relativeY: 0
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: 0
|
|
||||||
relativeY: -(cornersPath.cornerSize - cornersPath.cornerRadius)
|
|
||||||
}
|
|
||||||
PathArc {
|
|
||||||
relativeX: cornersPath.cornerRadius
|
|
||||||
relativeY: -cornersPath.cornerRadius
|
|
||||||
radiusX: cornersPath.cornerRadius
|
|
||||||
radiusY: cornersPath.cornerRadius
|
|
||||||
direction: PathArc.Counterclockwise
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: cornersPath.cornerSize - cornersPath.cornerRadius
|
|
||||||
relativeY: 0
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
relativeX: 0
|
|
||||||
relativeY: cornersPath.cornerSize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import Qt.labs.folderlistmodel 2.15 // <--- The magic file scanner!
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Hyprland
|
|
||||||
import Quickshell.Io
|
|
||||||
import "."
|
|
||||||
import qs.modules.bar
|
|
||||||
import qs
|
|
||||||
|
|
||||||
FloatingWindow {
|
|
||||||
id: root
|
|
||||||
title: "quickshell-WallSwitcher"
|
|
||||||
visible: false
|
|
||||||
implicitWidth: 840
|
|
||||||
implicitHeight: 640
|
|
||||||
|
|
||||||
GlobalShortcut {
|
|
||||||
// This is the "Secret Password" Hyprland will use
|
|
||||||
name: "toggle-walls"
|
|
||||||
|
|
||||||
onPressed: {
|
|
||||||
// Toggle visibility!
|
|
||||||
root.visible = !root.visible;
|
|
||||||
|
|
||||||
console.log("Shortcut pressed! Switcher is now: " + (root.visible ? "Visible" : "Hidden"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make it float above everything else
|
|
||||||
Text {
|
|
||||||
id: titleText
|
|
||||||
text: "Wallpapers in " + WallpaperStore.wallDir
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.top: parent.top
|
|
||||||
font.pixelSize: 20
|
|
||||||
topPadding: 20
|
|
||||||
bottomPadding: 10
|
|
||||||
font.family: Appearance.font
|
|
||||||
color: Colors.foreground
|
|
||||||
}
|
|
||||||
|
|
||||||
color: Colors.background // Dark background
|
|
||||||
|
|
||||||
// 1. The File Scanner
|
|
||||||
FolderListModel {
|
|
||||||
id: folderModel
|
|
||||||
folder: "file:///home/lucy/.walls/" // <--- Your stash!
|
|
||||||
nameFilters: ["*.png", "*.jpg", "*.jpeg"]
|
|
||||||
showDirs: false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. The Grid Display
|
|
||||||
GridView {
|
|
||||||
anchors.top: titleText.bottom // Sit below the title!
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.margins: 20
|
|
||||||
cellWidth: 200
|
|
||||||
cellHeight: 100
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
model: folderModel
|
|
||||||
|
|
||||||
delegate: Item {
|
|
||||||
width: 200
|
|
||||||
height: 100
|
|
||||||
|
|
||||||
Image {
|
|
||||||
width: 180
|
|
||||||
height: 90
|
|
||||||
anchors.centerIn: parent
|
|
||||||
// "fileUrl" is provided by FolderListModel
|
|
||||||
source: fileUrl
|
|
||||||
|
|
||||||
// IMPORTANT: Downscale the image for the thumbnail!
|
|
||||||
// If you don't do this, loading 50 4K images will eat your RAM
|
|
||||||
// faster than Chrome eats memory! 🙀
|
|
||||||
sourceSize.width: 140
|
|
||||||
sourceSize.height: 90
|
|
||||||
|
|
||||||
fillMode: Image.PreserveAspectCrop
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
Process {
|
|
||||||
id: generateScheme
|
|
||||||
property string cleanPath: fileUrl.toString().replace("file://", "")
|
|
||||||
command: ["wallust", "run", cleanPath]
|
|
||||||
}
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
let cleanPath = fileUrl.toString().replace("file://", "");
|
|
||||||
// Update the Singleton!
|
|
||||||
WallpaperStore.currentWall = fileUrl.toString();
|
|
||||||
//generateScheme.startDetached();
|
|
||||||
console.log(generateScheme.stdout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls // <--- Needed for StackView
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Wayland
|
|
||||||
|
|
||||||
WlrLayershell {
|
|
||||||
id: root
|
|
||||||
layer: WlrLayer.Background
|
|
||||||
keyboardFocus: WlrKeyboardFocus.None
|
|
||||||
anchors {
|
|
||||||
top: true
|
|
||||||
bottom: true
|
|
||||||
left: true
|
|
||||||
right: true
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to accept the screen from Variants
|
|
||||||
property var screen
|
|
||||||
property var modelData
|
|
||||||
|
|
||||||
// 1. The StackView manages the images
|
|
||||||
StackView {
|
|
||||||
id: wallStack
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height
|
|
||||||
|
|
||||||
// 2. Define what a "Wallpaper" looks like
|
|
||||||
Component {
|
|
||||||
id: wallComponent
|
|
||||||
Image {
|
|
||||||
fillMode: Image.PreserveAspectCrop
|
|
||||||
width: StackView.view.width
|
|
||||||
height: StackView.view.height
|
|
||||||
asynchronous: true // ⚡ VERY IMPORTANT: Prevents lag while loading!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Load the initial wallpaper immediately (No animation on boot)
|
|
||||||
initialItem: wallComponent.createObject(wallStack, {
|
|
||||||
"source": WallpaperStore.currentWall
|
|
||||||
})
|
|
||||||
|
|
||||||
// 4. THE ANIMATIONS 🎬
|
|
||||||
// When a new wall replaces the old one:
|
|
||||||
|
|
||||||
// New One: Fades In (0 -> 1)
|
|
||||||
replaceEnter: Transition {
|
|
||||||
NumberAnimation {
|
|
||||||
property: "x"
|
|
||||||
from: wallStack.width
|
|
||||||
to: 0
|
|
||||||
duration: 800 // Slower = Smoother
|
|
||||||
easing.type: Easing.OutQuad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Old One: Fades Out (1 -> 0)
|
|
||||||
replaceExit: Transition {
|
|
||||||
NumberAnimation {
|
|
||||||
property: "x"
|
|
||||||
from: 0
|
|
||||||
to: -wallStack.width
|
|
||||||
duration: 800
|
|
||||||
easing.type: Easing.OutQuad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. The Trigger 🔫
|
|
||||||
// We listen for the singleton to change, then tell the Stack to update
|
|
||||||
Connections {
|
|
||||||
target: WallpaperStore
|
|
||||||
|
|
||||||
function onCurrentWallChanged() {
|
|
||||||
// "Replace the current item with a new wallComponent using the new source"
|
|
||||||
wallStack.replace(wallComponent, {
|
|
||||||
"source": WallpaperStore.currentWall
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
pragma Singleton
|
|
||||||
import QtQuick
|
|
||||||
import Quickshell.Io // <--- Import for FileView and JsonAdapter
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: store
|
|
||||||
|
|
||||||
// 1. The File Manager
|
|
||||||
property string wallDir: "~/.walls/"
|
|
||||||
property var settings: FileView {
|
|
||||||
path: "/home/lucy/.cache/quickshell_settings.json"
|
|
||||||
|
|
||||||
// Auto-save when properties change
|
|
||||||
onAdapterUpdated: writeAdapter()
|
|
||||||
|
|
||||||
// Auto-load when the file changes on disk
|
|
||||||
watchChanges: true
|
|
||||||
onFileChanged: reload()
|
|
||||||
|
|
||||||
// 2. The Magic Adapter
|
|
||||||
JsonAdapter {
|
|
||||||
id: adapter
|
|
||||||
// This property corresponds to a key in your JSON file!
|
|
||||||
property string lastWallpaper: "/home/lucy/.walls/frieren_river.jpg"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Create a helper property for the rest of your app to use
|
|
||||||
// This keeps the "WallpaperStore.currentWall" name working!
|
|
||||||
property alias currentWall: adapter.lastWallpaper
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
singleton WallpaperStore 1.0 WallpaperStore.qml
|
|
||||||
Wallpaper 1.0 Wallpaper.qml
|
|
||||||
WallSwitcher 1.0 WallSwitcher.qml
|
|
||||||
Overlay 1.0 Overlay.qml
|
|
||||||
ScreenCorners 1.0 ScreenCorners.qml
|
|
||||||
23
shell.qml
23
shell.qml
@ -1,23 +1,4 @@
|
|||||||
//@ pragma UseQApplication
|
//@ pragma UseQApplication
|
||||||
//pragma ComponentBehavior: Bound
|
import qs.modules.bar
|
||||||
pragma ComponentBehavior: Bound
|
|
||||||
import Quickshell
|
|
||||||
import "./modules/bar/"
|
|
||||||
import "./modules/wallpaper/"
|
|
||||||
import "./modules/notifications/"
|
|
||||||
|
|
||||||
Scope {
|
Bar {}
|
||||||
WallSwitcher {}
|
|
||||||
Variants {
|
|
||||||
id: wallVariants
|
|
||||||
model: Quickshell.screens
|
|
||||||
delegate: Wallpaper {}
|
|
||||||
}
|
|
||||||
Variants {
|
|
||||||
id: barVariants
|
|
||||||
model: Quickshell.screens
|
|
||||||
delegate: Bar {}
|
|
||||||
}
|
|
||||||
NotiPopup {}
|
|
||||||
Overlay {}
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user