change to using loaders

This commit is contained in:
Zacharias-Brohn
2025-11-12 13:16:01 +01:00
parent 01d22e582a
commit 14b01ad539
9 changed files with 350 additions and 208 deletions
+2
View File
@@ -8,6 +8,7 @@ Singleton {
property alias appCount: adapter.appCount property alias appCount: adapter.appCount
property alias baseBgColor: adapter.baseBgColor property alias baseBgColor: adapter.baseBgColor
property alias accentColor: adapter.accentColor property alias accentColor: adapter.accentColor
property alias wallpaperPath: adapter.wallpaperPath
FileView { FileView {
id: root id: root
@@ -23,6 +24,7 @@ Singleton {
JsonAdapter { JsonAdapter {
id: adapter id: adapter
property int appCount: 20 property int appCount: 20
property string wallpaperPath: Quickshell.env("HOME") + "/Pictures/Wallpapers"
property string baseBgColor: "#801a1a1a" property string baseBgColor: "#801a1a1a"
property AccentColor accentColor: AccentColor {} property AccentColor accentColor: AccentColor {}
} }
+22
View File
@@ -0,0 +1,22 @@
pragma Singleton
import Quickshell.Io
import Quickshell
Singleton {
function getInitialTitle(callback) {
initialTitleProc.running = true
initialTitleProc.stdout.streamFinished.connect( function() {
let cleaned = initialTitleProc.stdout.text.trim().replace(/\"/g, "")
callback(cleaned === "null" ? "" : cleaned)
})
}
Process {
id: initialTitleProc
command: ["./scripts/initialTitle.sh"]
running: false
stdout: StdioCollector {
}
}
}
+35
View File
@@ -0,0 +1,35 @@
pragma Singleton
import Quickshell
import Quickshell.Io
import qs.Config
import qs.Modules
import Caelestia.Models
Searcher {
id: root
list: wallpapers.entries
key: "relativePath"
useFuzzy: true
extraOpts: useFuzzy ? ({}) : ({
forward: false
})
// FileView {
// path: root.currentNamePath
// watchChanges: true
// onFileChanged: reload()
// onLoaded: {
// root.actualCurrent = text().trim();
// }
// }
FileSystemModel {
id: wallpapers
recursive: true
path: Config.wallpaperPath
filter: FileSystemModel.Images
}
}
+260 -189
View File
@@ -6,6 +6,7 @@ import QtQuick.Controls
import QtQuick.Effects import QtQuick.Effects
import QtQuick.Layouts import QtQuick.Layouts
import qs.Config import qs.Config
import qs.Helpers
Scope { Scope {
id: root id: root
@@ -187,8 +188,8 @@ Scope {
Rectangle { Rectangle {
id: appListRect id: appListRect
x: Math.round(( parent.width - width ) / 2 ) x: Math.round(( parent.width - width ) / 2 )
implicitWidth: backgroundRect.implicitWidth implicitWidth: appListContainer.implicitWidth + 20
implicitHeight: appListView.implicitHeight + 20 implicitHeight: appListContainer.implicitHeight + 20
anchors.bottom: backgroundRect.top anchors.bottom: backgroundRect.top
anchors.bottomMargin: -1 anchors.bottomMargin: -1
color: backgroundRect.color color: backgroundRect.color
@@ -204,217 +205,287 @@ Scope {
} }
Item { Item {
anchors.fill: parent anchors.centerIn: parent
id: appListContainer
visible: appListView.count > 0 visible: appListView.count > 0
anchors.margins: 10
clip: true clip: true
ListView { property var showWallpapers: searchInput.text.startsWith(">")
id: appListView state: showWallpapers ? "wallpaperpicker" : "apps"
states: [
State {
name: "apps"
PropertyChanges {
appListLoader.active: true
appListContainer.implicitHeight: appListView.implicitHeight + 20
appListContainer.implicitWidth: 600
}
},
State {
name: "wallpaperpicker"
PropertyChanges {
wallpaperPickerLoader.active: true
appListContainer.implicitHeight: wallpaperPickerView.implicitHeight + 20
appListContainer.implicitWidth: wallpaperPickerView.implicitWidth + 20
}
}
]
Loader {
id: wallpaperPickerLoader
active: false
anchors.fill: parent anchors.fill: parent
model: ScriptModel { sourceComponent: ListView {
id: appModel id: wallpaperPickerView
anchors.fill: parent
model: ScriptModel {
id: wallpaperModel
readonly property string search: searchInput.text.split(" ").slice(1).join(" ")
onValuesChanged: { values: SearchWallpapers.query( search )
appListView.currentIndex = 0;
} }
orientation: ListView.Horizontal
spacing: 10
implicitHeight: 300
implicitWidth: Math.min( wallpaperModel.count, 7 ) * 192 + Math.max(0, wallpaperModel.count -1) * 10
focus: true
delegate: WallpaperItem { }
} }
}
Loader {
id: appListLoader
active: false
anchors.fill: parent
sourceComponent: ListView {
id: appListView
anchors.fill: parent
model: ScriptModel {
id: appModel
verticalLayoutDirection: ListView.BottomToTop onValuesChanged: {
implicitHeight: Math.min( count, Config.appCount ) * 48 appListView.currentIndex = 0;
}
}
preferredHighlightBegin: 0 verticalLayoutDirection: ListView.BottomToTop
preferredHighlightEnd: appListView.height implicitHeight: Math.min( count, Config.appCount ) * 48
highlightFollowsCurrentItem: false
highlightRangeMode: ListView.ApplyRange
focus: true
highlight: Rectangle {
radius: 4
color: "#FFFFFF"
opacity: 0.08
y: appListView.currentItem?.y preferredHighlightBegin: 0
implicitWidth: appListView.width preferredHighlightEnd: appListView.height
implicitHeight: appListView.currentItem?.implicitHeight ?? 0 highlightFollowsCurrentItem: false
highlightRangeMode: ListView.ApplyRange
focus: true
highlight: Rectangle {
radius: 4
color: "#FFFFFF"
opacity: 0.08
Behavior on y { y: appListView.currentItem?.y
implicitWidth: appListView.width
implicitHeight: appListView.currentItem?.implicitHeight ?? 0
Behavior on y {
Anim {
duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: MaterialEasing.expressiveEffects
}
}
}
property list<var> search: Search.search( searchInput.text )
state: {
const text = searchInput.text
if ( search.length === 0 ) {
return "noresults"
} else {
return "apps"
}
}
states: [
State {
name: "apps"
PropertyChanges {
appModel.values: Search.search(searchInput.text)
appListView.delegate: appItem
}
},
State {
name: "noresults"
PropertyChanges {
appModel.values: [1]
appListView.delegate: noResultsItem
}
}
// State {
// name: "wallpaperpicker"
// PropertyChanges {
// appModel.values: SearchWallpapers.query( searchInput.text.split(" ").slice(1).join(" ") )
// appListView.delegate: wallpaperItem
// appListView.orientation: ListView.Horizontal
// }
// }
]
Component {
id: appItem
AppItem {
}
}
Component {
id: noResultsItem
Item {
width: appListView.width
height: 48
Text {
id: icon
anchors.verticalCenter: parent.verticalCenter
property real fill: 0
text: "\ue000"
color: "#cccccc"
renderType: Text.NativeRendering
font.pointSize: 28
font.family: "Material Symbols Outlined"
font.variableAxes: ({
FILL: fill.toFixed(1),
GRAD: -25,
opsz: fontInfo.pixelSize,
wght: fontInfo.weight
})
}
Text {
anchors.left: icon.right
anchors.leftMargin: 10
anchors.verticalCenter: parent.verticalCenter
text: "No results found"
color: "#cccccc"
renderType: Text.NativeRendering
font.pointSize: 12
font.family: "Rubik"
}
}
}
Component {
id: wallpaperItem
WallpaperItem { }
}
transitions: Transition {
SequentialAnimation {
ParallelAnimation {
Anim {
target: appListView
property: "opacity"
from: 1
to: 0
duration: 200
easing.bezierCurve: MaterialEasing.standardAccel
}
Anim {
target: appListView
property: "scale"
from: 1
to: 0.9
duration: 200
easing.bezierCurve: MaterialEasing.standardAccel
}
}
PropertyAction {
targets: [model, appListView]
properties: "values,delegate"
}
ParallelAnimation {
Anim {
target: appListView
property: "opacity"
from: 0
to: 1
duration: 200
easing.bezierCurve: MaterialEasing.standardDecel
}
Anim {
target: appListView
property: "scale"
from: 0.9
to: 1
duration: 200
easing.bezierCurve: MaterialEasing.standardDecel
}
}
PropertyAction {
targets: [appListView.add, appListView.remove]
property: "enabled"
value: true
}
}
}
add: Transition {
enabled: !appListView.state
Anim { Anim {
duration: MaterialEasing.expressiveEffectsTime properties: "opacity"
easing.bezierCurve: MaterialEasing.expressiveEffects from: 0
} to: 1
}
}
property list<var> search: Search.search( searchInput.text )
state: search.length === 0 ? "noresults" : "apps"
states: [
State {
name: "apps"
PropertyChanges {
appModel.values: Search.search(searchInput.text)
appListView.delegate: appItem
}
},
State {
name: "noresults"
PropertyChanges {
appModel.values: [1]
appListView.delegate: noResultsItem
}
}
]
Component {
id: appItem
AppItem {
}
}
Component {
id: noResultsItem
Item {
width: appListView.width
height: 48
Text {
id: icon
anchors.verticalCenter: parent.verticalCenter
property real fill: 0
text: "\ue000"
color: "#cccccc"
renderType: Text.NativeRendering
font.pointSize: 28
font.family: "Material Symbols Outlined"
font.variableAxes: ({
FILL: fill.toFixed(1),
GRAD: -25,
opsz: fontInfo.pixelSize,
wght: fontInfo.weight
})
} }
Text { Anim {
anchors.left: icon.right properties: "scale"
anchors.leftMargin: 10 from: 0.95
anchors.verticalCenter: parent.verticalCenter to: 1
text: "No results found"
color: "#cccccc"
renderType: Text.NativeRendering
font.pointSize: 12
font.family: "Rubik"
} }
} }
}
transitions: Transition { remove: Transition {
SequentialAnimation { enabled: !appListView.state
ParallelAnimation { Anim {
Anim { properties: "opacity"
target: appListView from: 1
property: "opacity" to: 0
from: 1
to: 0
duration: 200
easing.bezierCurve: MaterialEasing.standardAccel
}
Anim {
target: appListView
property: "scale"
from: 1
to: 0.9
duration: 200
easing.bezierCurve: MaterialEasing.standardAccel
}
} }
PropertyAction {
targets: [model, appListView] Anim {
properties: "values,delegate" properties: "scale"
} from: 1
ParallelAnimation { to: 0.95
Anim {
target: appListView
property: "opacity"
from: 0
to: 1
duration: 200
easing.bezierCurve: MaterialEasing.standardDecel
}
Anim {
target: appListView
property: "scale"
from: 0.9
to: 1
duration: 200
easing.bezierCurve: MaterialEasing.standardDecel
}
}
PropertyAction {
targets: [appListView.add, appListView.remove]
property: "enabled"
value: true
} }
} }
}
add: Transition { move: Transition {
enabled: !appListView.state Anim {
Anim { property: "y"
properties: "opacity" }
from: 0 Anim {
to: 1 properties: "opacity,scale"
to: 1
}
} }
Anim { addDisplaced: Transition {
properties: "scale" Anim {
from: 0.95 property: "y"
to: 1 duration: 200
} }
} Anim {
properties: "opacity,scale"
remove: Transition { to: 1
enabled: !appListView.state }
Anim {
properties: "opacity"
from: 1
to: 0
} }
Anim { displaced: Transition {
properties: "scale" Anim {
from: 1 property: "y"
to: 0.95 }
} Anim {
} properties: "opacity,scale"
to: 1
move: Transition { }
Anim {
property: "y"
}
Anim {
properties: "opacity,scale"
to: 1
}
}
addDisplaced: Transition {
Anim {
property: "y"
duration: 200
}
Anim {
properties: "opacity,scale"
to: 1
}
}
displaced: Transition {
Anim {
property: "y"
}
Anim {
properties: "opacity,scale"
to: 1
} }
} }
} }
+2
View File
@@ -143,6 +143,8 @@ PanelWindow {
Layout.fillWidth: true Layout.fillWidth: true
text: "Do Not Disturb" text: "Do Not Disturb"
focus: false focus: false
activeFocusOnTab: false
focusPolicy: Qt.NoFocus
} }
RowLayout { RowLayout {
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+3 -1
View File
@@ -59,8 +59,10 @@ MouseArea {
if ( mouse.button === Qt.LeftButton ) { if ( mouse.button === Qt.LeftButton ) {
root.item.activate(); root.item.activate();
} else if ( mouse.button === Qt.RightButton ) { } else if ( mouse.button === Qt.RightButton ) {
if ( root.item?.menu !== trayMenu.trayMenu ) {
trayMenu.trayMenu = root.item?.menu;
}
trayMenu.visible = !trayMenu.visible; trayMenu.visible = !trayMenu.visible;
trayMenu.trayMenu = root.item?.menu;
trayMenu.focusGrab = true; trayMenu.focusGrab = true;
} }
} }
+4 -4
View File
@@ -163,15 +163,15 @@ PanelWindow {
Behavior on implicitWidth { Behavior on implicitWidth {
NumberAnimation { NumberAnimation {
duration: MaterialEasing.standardTime duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: MaterialEasing.standard easing.bezierCurve: MaterialEasing.expressiveEffects
} }
} }
Behavior on implicitHeight { Behavior on implicitHeight {
NumberAnimation { NumberAnimation {
duration: MaterialEasing.standardTime duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: MaterialEasing.standard easing.bezierCurve: MaterialEasing.expressiveEffects
} }
} }
+18
View File
@@ -0,0 +1,18 @@
import Quickshell
import QtQuick
import Caelestia.Models
Item {
id: root
required property FileSystemEntry modelData
implicitWidth: 192
implicitHeight: 108
Image {
id: thumbnailImage
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
source: root.modelData.path
}
}
+4 -14
View File
@@ -1,7 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Hyprland import Quickshell.Hyprland
import qs.Helpers
Item { Item {
id: root id: root
@@ -12,22 +12,12 @@ Item {
property bool showFirst: true property bool showFirst: true
Process {
id: initialTitleProc
command: ["./scripts/initialTitle.sh"]
running: false
stdout: StdioCollector {
onStreamFinished: {
let cleaned = this.text.trim().replace(/\"/g, "")
root.currentTitle = ( cleaned === "null" ) ? "" : cleaned
}
}
}
Component.onCompleted: { Component.onCompleted: {
Hyprland.rawEvent.connect(( event ) => { Hyprland.rawEvent.connect(( event ) => {
if (event.name === "activewindow") { if (event.name === "activewindow") {
initialTitleProc.running = true InitialTitle.getInitialTitle( function( initialTitle ) {
root.currentTitle = initialTitle
})
} }
}) })
} }