adds overview, removes old stuff

This commit is contained in:
2026-08-19 20:47:29 +02:00
parent 6a9ae98c26
commit 67d50fb504
75 changed files with 3558 additions and 1691 deletions
@@ -0,0 +1,197 @@
// WallpaperPopup.qml - A popup for browsing and setting wallpapers from /usr/share/wallpapers
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import ".."
PanelWindow {
id: root
required property var screen
property bool logicalOpen: GlobalStates.popups.active === "wallpaper"
property bool _keepVisible: false
visible: logicalOpen || _keepVisible
onLogicalOpenChanged: {
if (logicalOpen) {
closeTimer.stop()
_keepVisible = false
if (wallpaperModel.count === 0) scanProc.running = true
openY.start()
openOpacity.start()
focusTimer.start()
} else {
_keepVisible = true
closeY.start()
closeOpacity.start()
closeTimer.restart()
}
}
Timer { id: closeTimer; interval: 280; onTriggered: root._keepVisible = false }
Timer { id: focusTimer; interval: 50; onTriggered: grid.forceActiveFocus() }
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.namespace: "quickshell-popup-wallpaper"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
anchors { top: true; left: true; right: true; bottom: true }
color: Qt.rgba(0, 0, 0, 0)
MouseArea { anchors.fill: parent; onClicked: GlobalStates.popups.close() }
NumberAnimation { id: openY; target: box; property: "y"; to: 1; duration: 250; easing.type: Easing.OutCubic }
NumberAnimation { id: closeY; target: box; property: "y"; to: -340; duration: 200; easing.type: Easing.InCubic }
NumberAnimation { id: openOpacity; target: box; property: "opacity"; to: Theme.popupOpacity; duration: 200 }
NumberAnimation { id: closeOpacity; target: box; property: "opacity"; to: 0.0; duration: 200 }
// ── Named-pipe IPC ────────────────────────────────────────
// Trigger from Hyprland keybind: echo 1 > /tmp/qs-wallpaper-ipc
// Trigger from another QML popup: Exec.run(["bash", "-c", "echo 1 > /tmp/qs-wallpaper-ipc"])
Process {
id: ipcReader
running: true
command: ["bash", "-c",
"rm -f /tmp/qs-wallpaper-ipc && " +
"mkfifo /tmp/qs-wallpaper-ipc && " +
"while true; do cat /tmp/qs-wallpaper-ipc; done"]
stdout: SplitParser {
onRead: () => GlobalStates.popups.toggle("wallpaper", 0)
}
onExited: running = true
}
// ── Wallpaper scanner ─────────────────────────────────────
ListModel { id: wallpaperModel }
Process {
id: scanProc
running: false
command: ["bash", "-c",
"find /usr/share/wallpapers -type f " +
"\\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.webp' \\) " +
"| sort"]
stdout: SplitParser {
onRead: (line) => {
var p = line.trim()
if (p) wallpaperModel.append({ path: p })
}
}
}
Process { id: setProc; running: false }
// ── Popup box ─────────────────────────────────────────────
Rectangle {
id: box
// anchorX = 0 → centered; anchorX > 0 → centered under widget
x: {
var ax = GlobalStates.popups.anchorX
var cx = ax > 0 ? ax - width / 2 : parent.width / 2 - width / 2
return Math.max(4, Math.min(parent.width - width - 4, cx))
}
y: -340
opacity: 0.0
width: 324
height: 500
color: Theme.popupBackground
radius: Theme.radius * 2
clip: true
border.color: Theme.popupBorderColor
border.width: Theme.popupBorderWidth
MouseArea { anchors.fill: parent }
Text {
anchors.centerIn: parent
visible: wallpaperModel.count === 0
text: "Scanning..."
font { family: Theme.fontSans; pixelSize: Theme.fontSize }
color: Theme.pillText
opacity: 0.5
}
GridView {
id: grid
anchors { fill: parent; margins: 8 }
clip: true
cellWidth: Math.floor(width / 2)
cellHeight: 104
focus: true
keyNavigationEnabled: true
currentIndex: 0
Keys.onReturnPressed: {
var item = wallpaperModel.get(grid.currentIndex)
if (item) {
setProc.command = ["waypaper", "--wallpaper", item.path]
setProc.running = true
GlobalStates.popups.close()
}
}
Keys.onEscapePressed: GlobalStates.popups.close()
model: wallpaperModel
highlight: Rectangle {
z: 2
radius: Theme.radius + 1
color: "transparent"
border.color: Theme.accent ?? "#cba6f7"
border.width: 2
}
highlightFollowsCurrentItem: true
highlightMoveDuration: 80
delegate: Item {
required property string path
required property int index
width: grid.cellWidth - 4
height: 100
Rectangle {
anchors { fill: parent; margins: 2 }
radius: Theme.radius
color: "black"
clip: true
Image {
anchors.fill: parent
source: "file://" + path
fillMode: Image.PreserveAspectCrop
sourceSize: Qt.size(152, 96)
smooth: true
asynchronous: true
opacity: status === Image.Ready ? 1.0 : 0.0
Behavior on opacity { NumberAnimation { duration: 150 } }
}
Rectangle {
anchors.fill: parent
radius: Theme.radius
color: hover.containsMouse ? Qt.rgba(1, 1, 1, 0.2) : "transparent"
Behavior on color { ColorAnimation { duration: 100 } }
}
MouseArea {
id: hover
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
grid.currentIndex = index
setProc.command = ["waypaper", "--wallpaper", path]
setProc.running = true
GlobalStates.popups.close()
}
onEntered: grid.currentIndex = index
}
}
}
}
}
}