diff options
| author | Freya Murphy <freya@freyacat.org> | 2026-01-10 17:29:29 -0500 |
|---|---|---|
| committer | Freya Murphy <freya@freyacat.org> | 2026-01-10 17:29:29 -0500 |
| commit | 3ee6dcd9611986864e78df8dd06cc364e346f4a6 (patch) | |
| tree | beb0e2959e66b7f0f5a57d3377b339b8381f6181 | |
| parent | remove more things, make lock screen use wallpaper not screenshot (diff) | |
| download | caelestia-shell-3ee6dcd9611986864e78df8dd06cc364e346f4a6.tar.gz caelestia-shell-3ee6dcd9611986864e78df8dd06cc364e346f4a6.tar.bz2 caelestia-shell-3ee6dcd9611986864e78df8dd06cc364e346f4a6.zip | |
remove more things again lol
26 files changed, 5 insertions, 1866 deletions
diff --git a/components/filedialog/CurrentItem.qml b/components/filedialog/CurrentItem.qml deleted file mode 100644 index bb87133..0000000 --- a/components/filedialog/CurrentItem.qml +++ /dev/null @@ -1,102 +0,0 @@ -import ".." -import qs.services -import qs.config -import QtQuick -import QtQuick.Shapes - -Item { - id: root - - required property var currentItem - - implicitWidth: content.implicitWidth + Appearance.padding.larger + content.anchors.rightMargin - implicitHeight: currentItem ? content.implicitHeight + Appearance.padding.normal + content.anchors.bottomMargin : 0 - - Shape { - preferredRendererType: Shape.CurveRenderer - - ShapePath { - id: path - - readonly property real rounding: Appearance.rounding.small - readonly property bool flatten: root.implicitHeight < rounding * 2 - readonly property real roundingY: flatten ? root.implicitHeight / 2 : rounding - - strokeWidth: -1 - fillColor: Colours.tPalette.m3surfaceContainer - - startX: root.implicitWidth - startY: root.implicitHeight - - PathLine { - relativeX: -(root.implicitWidth + path.rounding) - relativeY: 0 - } - PathArc { - relativeX: path.rounding - relativeY: -path.roundingY - radiusX: path.rounding - radiusY: Math.min(path.rounding, root.implicitHeight) - direction: PathArc.Counterclockwise - } - PathLine { - relativeX: 0 - relativeY: -(root.implicitHeight - path.roundingY * 2) - } - PathArc { - relativeX: path.rounding - relativeY: -path.roundingY - radiusX: path.rounding - radiusY: Math.min(path.rounding, root.implicitHeight) - } - PathLine { - relativeX: root.implicitHeight > 0 ? root.implicitWidth - path.rounding * 2 : root.implicitWidth - relativeY: 0 - } - PathArc { - relativeX: path.rounding - relativeY: -path.rounding - radiusX: path.rounding - radiusY: path.rounding - direction: PathArc.Counterclockwise - } - - Behavior on fillColor { - CAnim {} - } - } - } - - Item { - anchors.fill: parent - clip: true - - StyledText { - id: content - - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.rightMargin: Appearance.padding.larger - Appearance.padding.small - anchors.bottomMargin: Appearance.padding.normal - Appearance.padding.small - - Connections { - target: root - - function onCurrentItemChanged(): void { - if (root.currentItem) - content.text = qsTr(`"%1" selected`).arg(root.currentItem.modelData.name); - } - } - } - } - - Behavior on implicitWidth { - enabled: !!root.currentItem - - Anim {} - } - - Behavior on implicitHeight { - Anim {} - } -} diff --git a/components/filedialog/DialogButtons.qml b/components/filedialog/DialogButtons.qml deleted file mode 100644 index bde9ac2..0000000 --- a/components/filedialog/DialogButtons.qml +++ /dev/null @@ -1,93 +0,0 @@ -import ".." -import qs.services -import qs.config -import QtQuick.Layouts - -StyledRect { - id: root - - required property var dialog - required property FolderContents folder - - implicitHeight: inner.implicitHeight + Appearance.padding.normal * 2 - - color: Colours.tPalette.m3surfaceContainer - - RowLayout { - id: inner - - anchors.fill: parent - anchors.margins: Appearance.padding.normal - - spacing: Appearance.spacing.small - - StyledText { - text: qsTr("Filter:") - } - - StyledRect { - Layout.fillWidth: true - Layout.fillHeight: true - Layout.rightMargin: Appearance.spacing.normal - - color: Colours.tPalette.m3surfaceContainerHigh - radius: Appearance.rounding.small - - StyledText { - anchors.fill: parent - anchors.margins: Appearance.padding.normal - - text: `${root.dialog.filterLabel} (${root.dialog.filters.map(f => `*.${f}`).join(", ")})` - } - } - - StyledRect { - color: Colours.tPalette.m3surfaceContainerHigh - radius: Appearance.rounding.small - - implicitWidth: cancelText.implicitWidth + Appearance.padding.normal * 2 - implicitHeight: cancelText.implicitHeight + Appearance.padding.normal * 2 - - StateLayer { - disabled: !root.dialog.selectionValid - - function onClicked(): void { - root.dialog.accepted(root.folder.currentItem.modelData.path); - } - } - - StyledText { - id: selectText - - anchors.centerIn: parent - anchors.margins: Appearance.padding.normal - - text: qsTr("Select") - color: root.dialog.selectionValid ? Colours.palette.m3onSurface : Colours.palette.m3outline - } - } - - StyledRect { - color: Colours.tPalette.m3surfaceContainerHigh - radius: Appearance.rounding.small - - implicitWidth: cancelText.implicitWidth + Appearance.padding.normal * 2 - implicitHeight: cancelText.implicitHeight + Appearance.padding.normal * 2 - - StateLayer { - function onClicked(): void { - root.dialog.rejected(); - } - } - - StyledText { - id: cancelText - - anchors.centerIn: parent - anchors.margins: Appearance.padding.normal - - text: qsTr("Cancel") - } - } - } -} diff --git a/components/filedialog/FileDialog.qml b/components/filedialog/FileDialog.qml deleted file mode 100644 index f3187a5..0000000 --- a/components/filedialog/FileDialog.qml +++ /dev/null @@ -1,102 +0,0 @@ -pragma ComponentBehavior: Bound - -import qs.components -import qs.services -import Quickshell -import QtQuick -import QtQuick.Layouts - -LazyLoader { - id: loader - - property list<string> cwd: ["Home"] - property string filterLabel: "All files" - property list<string> filters: ["*"] - property string title: qsTr("Select a file") - - signal accepted(path: string) - signal rejected - - function open(): void { - activeAsync = true; - } - - function close(): void { - rejected(); - } - - onAccepted: activeAsync = false - onRejected: activeAsync = false - - FloatingWindow { - id: root - - property list<string> cwd: loader.cwd - property string filterLabel: loader.filterLabel - property list<string> filters: loader.filters - - readonly property bool selectionValid: { - const file = folderContents.currentItem?.modelData; - return (file && !file.isDir && (filters.includes("*") || filters.includes(file.suffix))) ?? false; - } - - function accepted(path: string): void { - loader.accepted(path); - } - - function rejected(): void { - loader.rejected(); - } - - implicitWidth: 1000 - implicitHeight: 600 - color: Colours.tPalette.m3surface - title: loader.title - - onVisibleChanged: { - if (!visible) - rejected(); - } - - RowLayout { - anchors.fill: parent - - spacing: 0 - - Sidebar { - Layout.fillHeight: true - dialog: root - } - - ColumnLayout { - Layout.fillWidth: true - Layout.fillHeight: true - - spacing: 0 - - HeaderBar { - Layout.fillWidth: true - dialog: root - } - - FolderContents { - id: folderContents - - Layout.fillWidth: true - Layout.fillHeight: true - dialog: root - } - - DialogButtons { - Layout.fillWidth: true - dialog: root - folder: folderContents - } - } - } - - Behavior on color { - CAnim {} - } - } -} diff --git a/components/filedialog/FolderContents.qml b/components/filedialog/FolderContents.qml deleted file mode 100644 index c3b371b..0000000 --- a/components/filedialog/FolderContents.qml +++ /dev/null @@ -1,229 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import "../controls" -import "../images" -import qs.services -import qs.config -import qs.utils -import Caelestia.Models -import Quickshell -import QtQuick -import QtQuick.Layouts -import QtQuick.Effects - -Item { - id: root - - required property var dialog - property alias currentItem: view.currentItem - - StyledRect { - anchors.fill: parent - color: Colours.tPalette.m3surfaceContainer - - layer.enabled: true - layer.effect: MultiEffect { - maskSource: mask - maskEnabled: true - maskInverted: true - maskThresholdMin: 0.5 - maskSpreadAtMin: 1 - } - } - - Item { - id: mask - - anchors.fill: parent - layer.enabled: true - visible: false - - Rectangle { - anchors.fill: parent - anchors.margins: Appearance.padding.small - radius: Appearance.rounding.small - } - } - - Loader { - anchors.centerIn: parent - - opacity: view.count === 0 ? 1 : 0 - active: opacity > 0 - asynchronous: true - - sourceComponent: ColumnLayout { - MaterialIcon { - Layout.alignment: Qt.AlignHCenter - text: "scan_delete" - color: Colours.palette.m3outline - font.pointSize: Appearance.font.size.extraLarge * 2 - font.weight: 500 - } - - StyledText { - text: qsTr("This folder is empty") - color: Colours.palette.m3outline - font.pointSize: Appearance.font.size.large - font.weight: 500 - } - } - - Behavior on opacity { - Anim {} - } - } - - GridView { - id: view - - anchors.fill: parent - anchors.margins: Appearance.padding.small + Appearance.padding.normal - - cellWidth: Sizes.itemWidth + Appearance.spacing.small - cellHeight: Sizes.itemWidth + Appearance.spacing.small * 2 + Appearance.padding.normal * 2 + 1 - - clip: true - focus: true - currentIndex: -1 - Keys.onEscapePressed: currentIndex = -1 - - Keys.onReturnPressed: { - if (root.dialog.selectionValid) - root.dialog.accepted(currentItem.modelData.path); - } - Keys.onEnterPressed: { - if (root.dialog.selectionValid) - root.dialog.accepted(currentItem.modelData.path); - } - - StyledScrollBar.vertical: StyledScrollBar { - flickable: view - } - - model: FileSystemModel { - path: { - if (root.dialog.cwd[0] === "Home") - return `${Paths.home}/${root.dialog.cwd.slice(1).join("/")}`; - else - return root.dialog.cwd.join("/"); - } - onPathChanged: view.currentIndex = -1 - } - - delegate: StyledRect { - id: item - - required property int index - required property FileSystemEntry modelData - - readonly property real nonAnimHeight: icon.implicitHeight + name.anchors.topMargin + name.implicitHeight + Appearance.padding.normal * 2 - - implicitWidth: Sizes.itemWidth - implicitHeight: nonAnimHeight - - radius: Appearance.rounding.normal - color: Qt.alpha(Colours.tPalette.m3surfaceContainerHighest, GridView.isCurrentItem ? Colours.tPalette.m3surfaceContainerHighest.a : 0) - z: GridView.isCurrentItem || implicitHeight !== nonAnimHeight ? 1 : 0 - clip: true - - StateLayer { - onDoubleClicked: { - if (item.modelData.isDir) - root.dialog.cwd.push(item.modelData.name); - else if (root.dialog.selectionValid) - root.dialog.accepted(item.modelData.path); - } - - function onClicked(): void { - view.currentIndex = item.index; - } - } - - CachingIconImage { - id: icon - - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - anchors.topMargin: Appearance.padding.normal - - implicitSize: Sizes.itemWidth - Appearance.padding.normal * 2 - - Component.onCompleted: { - const file = item.modelData; - if (file.isImage) - source = Qt.resolvedUrl(file.path); - else if (!file.isDir) - source = Quickshell.iconPath(file.mimeType.replace("/", "-"), "application-x-zerosize"); - else if (root.dialog.cwd.length === 1 && ["Desktop", "Documents", "Downloads", "Music", "Pictures", "Public", "Templates", "Videos"].includes(file.name)) - source = Quickshell.iconPath(`folder-${file.name.toLowerCase()}`); - else - source = Quickshell.iconPath("inode-directory"); - } - } - - StyledText { - id: name - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: icon.bottom - anchors.topMargin: Appearance.spacing.small - anchors.margins: Appearance.padding.normal - - horizontalAlignment: Text.AlignHCenter - elide: item.GridView.isCurrentItem ? Text.ElideNone : Text.ElideRight - wrapMode: item.GridView.isCurrentItem ? Text.WrapAtWordBoundaryOrAnywhere : Text.NoWrap - - Component.onCompleted: text = item.modelData.name - } - - Behavior on implicitHeight { - Anim {} - } - } - - add: Transition { - Anim { - properties: "opacity,scale" - from: 0 - to: 1 - duration: Appearance.anim.durations.expressiveDefaultSpatial - easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial - } - } - - remove: Transition { - Anim { - property: "opacity" - to: 0 - } - Anim { - property: "scale" - to: 0.5 - } - } - - displaced: Transition { - Anim { - properties: "opacity,scale" - to: 1 - easing.bezierCurve: Appearance.anim.curves.standardDecel - } - Anim { - properties: "x,y" - duration: Appearance.anim.durations.expressiveDefaultSpatial - easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial - } - } - } - - CurrentItem { - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: Appearance.padding.small - - currentItem: view.currentItem - } -} diff --git a/components/filedialog/HeaderBar.qml b/components/filedialog/HeaderBar.qml deleted file mode 100644 index b6e5dba..0000000 --- a/components/filedialog/HeaderBar.qml +++ /dev/null @@ -1,142 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import qs.services -import qs.config -import QtQuick -import QtQuick.Layouts - -StyledRect { - id: root - - required property var dialog - - implicitWidth: inner.implicitWidth + Appearance.padding.normal * 2 - implicitHeight: inner.implicitHeight + Appearance.padding.normal * 2 - - color: Colours.tPalette.m3surfaceContainer - - RowLayout { - id: inner - - anchors.fill: parent - anchors.margins: Appearance.padding.normal - spacing: Appearance.spacing.small - - Item { - implicitWidth: implicitHeight - implicitHeight: upIcon.implicitHeight + Appearance.padding.small * 2 - - StateLayer { - radius: Appearance.rounding.small - disabled: root.dialog.cwd.length === 1 - - function onClicked(): void { - root.dialog.cwd.pop(); - } - } - - MaterialIcon { - id: upIcon - - anchors.centerIn: parent - text: "drive_folder_upload" - color: root.dialog.cwd.length === 1 ? Colours.palette.m3outline : Colours.palette.m3onSurface - grade: 200 - } - } - - StyledRect { - Layout.fillWidth: true - - radius: Appearance.rounding.small - color: Colours.tPalette.m3surfaceContainerHigh - - implicitHeight: pathComponents.implicitHeight + pathComponents.anchors.margins * 2 - - RowLayout { - id: pathComponents - - anchors.fill: parent - anchors.margins: Appearance.padding.small / 2 - anchors.leftMargin: 0 - - spacing: Appearance.spacing.small - - Repeater { - model: root.dialog.cwd - - RowLayout { - id: folder - - required property string modelData - required property int index - - spacing: 0 - - Loader { - Layout.rightMargin: Appearance.spacing.small - active: folder.index > 0 - asynchronous: true - sourceComponent: StyledText { - text: "/" - color: Colours.palette.m3onSurfaceVariant - font.bold: true - } - } - - Item { - implicitWidth: homeIcon.implicitWidth + (homeIcon.active ? Appearance.padding.small : 0) + folderName.implicitWidth + Appearance.padding.normal * 2 - implicitHeight: folderName.implicitHeight + Appearance.padding.small * 2 - - Loader { - anchors.fill: parent - active: folder.index < root.dialog.cwd.length - 1 - asynchronous: true - sourceComponent: StateLayer { - radius: Appearance.rounding.small - - function onClicked(): void { - root.dialog.cwd = root.dialog.cwd.slice(0, folder.index + 1); - } - } - } - - Loader { - id: homeIcon - - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Appearance.padding.normal - - active: folder.index === 0 && folder.modelData === "Home" - asynchronous: true - sourceComponent: MaterialIcon { - text: "home" - color: root.dialog.cwd.length === 1 ? Colours.palette.m3onSurface : Colours.palette.m3onSurfaceVariant - fill: 1 - } - } - - StyledText { - id: folderName - - anchors.left: homeIcon.right - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: homeIcon.active ? Appearance.padding.small : 0 - - text: folder.modelData - color: folder.index < root.dialog.cwd.length - 1 ? Colours.palette.m3onSurfaceVariant : Colours.palette.m3onSurface - font.bold: true - } - } - } - } - - Item { - Layout.fillWidth: true - } - } - } - } -} diff --git a/components/filedialog/Sidebar.qml b/components/filedialog/Sidebar.qml deleted file mode 100644 index b55d7b3..0000000 --- a/components/filedialog/Sidebar.qml +++ /dev/null @@ -1,113 +0,0 @@ -pragma ComponentBehavior: Bound - -import ".." -import qs.services -import qs.config -import QtQuick -import QtQuick.Layouts - -StyledRect { - id: root - - required property var dialog - - implicitWidth: Sizes.sidebarWidth - implicitHeight: inner.implicitHeight + Appearance.padding.normal * 2 - - color: Colours.tPalette.m3surfaceContainer - - ColumnLayout { - id: inner - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.margins: Appearance.padding.normal - spacing: Appearance.spacing.small / 2 - - StyledText { - Layout.alignment: Qt.AlignHCenter - Layout.topMargin: Appearance.padding.small / 2 - Layout.bottomMargin: Appearance.spacing.normal - text: qsTr("Files") - color: Colours.palette.m3onSurface - font.pointSize: Appearance.font.size.larger - font.bold: true - } - - Repeater { - model: ["Home", "Downloads", "Desktop", "Documents", "Music", "Pictures", "Videos"] - - StyledRect { - id: place - - required property string modelData - readonly property bool selected: modelData === root.dialog.cwd[root.dialog.cwd.length - 1] - - Layout.fillWidth: true - implicitHeight: placeInner.implicitHeight + Appearance.padding.normal * 2 - - radius: Appearance.rounding.full - color: Qt.alpha(Colours.palette.m3secondaryContainer, selected ? 1 : 0) - - StateLayer { - color: place.selected ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface - - function onClicked(): void { - if (place.modelData === "Home") - root.dialog.cwd = ["Home"]; - else - root.dialog.cwd = ["Home", place.modelData]; - } - } - - RowLayout { - id: placeInner - - anchors.fill: parent - anchors.margins: Appearance.padding.normal - anchors.leftMargin: Appearance.padding.large - anchors.rightMargin: Appearance.padding.large - - spacing: Appearance.spacing.normal - - MaterialIcon { - text: { - const p = place.modelData; - if (p === "Home") - return "home"; - if (p === "Downloads") - return "file_download"; - if (p === "Desktop") - return "desktop_windows"; - if (p === "Documents") - return "description"; - if (p === "Music") - return "music_note"; - if (p === "Pictures") - return "image"; - if (p === "Videos") - return "video_library"; - return "folder"; - } - color: place.selected ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface - font.pointSize: Appearance.font.size.large - fill: place.selected ? 1 : 0 - - Behavior on fill { - Anim {} - } - } - - StyledText { - Layout.fillWidth: true - text: place.modelData - color: place.selected ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface - font.pointSize: Appearance.font.size.normal - elide: Text.ElideRight - } - } - } - } - } -} diff --git a/components/filedialog/Sizes.qml b/components/filedialog/Sizes.qml deleted file mode 100644 index 2ad31f9..0000000 --- a/components/filedialog/Sizes.qml +++ /dev/null @@ -1,8 +0,0 @@ -pragma Singleton - -import Quickshell - -Singleton { - property int itemWidth: 103 - property int sidebarWidth: 200 -} diff --git a/components/images/CachingIconImage.qml b/components/images/CachingIconImage.qml deleted file mode 100644 index 1acc6a1..0000000 --- a/components/images/CachingIconImage.qml +++ /dev/null @@ -1,42 +0,0 @@ -pragma ComponentBehavior: Bound - -import qs.utils -import Quickshell.Widgets -import QtQuick - -Item { - id: root - - readonly property int status: loader.item?.status ?? Image.Null - readonly property real actualSize: Math.min(width, height) - property real implicitSize - property url source - - implicitWidth: implicitSize - implicitHeight: implicitSize - - Loader { - id: loader - - anchors.fill: parent - sourceComponent: root.source ? root.source.toString().startsWith("image://icon/") ? iconImage : cachingImage : null - } - - Component { - id: cachingImage - - CachingImage { - path: Paths.toLocalFile(root.source) - fillMode: Image.PreserveAspectFit - } - } - - Component { - id: iconImage - - IconImage { - source: root.source - asynchronous: true - } - } -} diff --git a/components/images/CachingImage.qml b/components/images/CachingImage.qml deleted file mode 100644 index e8f957a..0000000 --- a/components/images/CachingImage.qml +++ /dev/null @@ -1,28 +0,0 @@ -import qs.utils -import Caelestia.Internal -import Quickshell -import QtQuick - -Image { - id: root - - property alias path: manager.path - - asynchronous: true - fillMode: Image.PreserveAspectCrop - - Connections { - target: QsWindow.window - - function onDevicePixelRatioChanged(): void { - manager.updateSource(); - } - } - - CachingImageManager { - id: manager - - item: root - cacheDir: Qt.resolvedUrl(Paths.imagecache) - } -} diff --git a/config/Config.qml b/config/Config.qml index 8927a16..c49240e 100644 --- a/config/Config.qml +++ b/config/Config.qml @@ -394,6 +394,7 @@ Singleton { function serializePaths(): var { return { wallpaper: paths.wallpaper, + face: paths.face, sessionGif: paths.sessionGif, mediaGif: paths.mediaGif }; diff --git a/config/UserPaths.qml b/config/UserPaths.qml index 5e35933..f334890 100644 --- a/config/UserPaths.qml +++ b/config/UserPaths.qml @@ -3,6 +3,7 @@ import Quickshell.Io JsonObject { property string wallpaper: `${Paths.config}/wallpaper.png` + property string face: `${Paths.config}/face.png` property string sessionGif: "root:/assets/len.gif" property string mediaGif: "root:/assets/bongocat.gif" } diff --git a/modules/dashboard/Content.qml b/modules/dashboard/Content.qml index 70cfaf9..f5f0e46 100644 --- a/modules/dashboard/Content.qml +++ b/modules/dashboard/Content.qml @@ -1,7 +1,6 @@ pragma ComponentBehavior: Bound import qs.components -import qs.components.filedialog import qs.config import Quickshell import Quickshell.Widgets diff --git a/modules/dashboard/Dash.qml b/modules/dashboard/Dash.qml index 0bc81b4..7617ed8 100644 --- a/modules/dashboard/Dash.qml +++ b/modules/dashboard/Dash.qml @@ -1,5 +1,4 @@ import qs.components -import qs.components.filedialog import qs.services import qs.config import "dash" diff --git a/modules/dashboard/Wrapper.qml b/modules/dashboard/Wrapper.qml index 3f8f2bd..9758d27 100644 --- a/modules/dashboard/Wrapper.qml +++ b/modules/dashboard/Wrapper.qml @@ -1,7 +1,6 @@ pragma ComponentBehavior: Bound import qs.components -import qs.components.filedialog import qs.config import qs.utils import Caelestia diff --git a/modules/dashboard/dash/User.qml b/modules/dashboard/dash/User.qml index 6cb06f2..0d40873 100644 --- a/modules/dashboard/dash/User.qml +++ b/modules/dashboard/dash/User.qml @@ -1,7 +1,5 @@ import qs.components import qs.components.effects -import qs.components.images -import qs.components.filedialog import qs.services import qs.config import qs.utils diff --git a/modules/lock/Center.qml b/modules/lock/Center.qml index 748504b..5885252 100644 --- a/modules/lock/Center.qml +++ b/modules/lock/Center.qml @@ -2,7 +2,6 @@ pragma ComponentBehavior: Bound import qs.components import qs.components.controls -import qs.components.images import qs.services import qs.config import qs.utils @@ -101,11 +100,11 @@ ColumnLayout { font.pointSize: Math.floor(root.centerWidth / 4) } - CachingImage { + Image { id: pfp anchors.fill: parent - path: `${Paths.home}/.face` + source: Paths.face ?? "" } } diff --git a/plugin/src/Caelestia/CMakeLists.txt b/plugin/src/Caelestia/CMakeLists.txt index 18c7315..22d4b97 100644 --- a/plugin/src/Caelestia/CMakeLists.txt +++ b/plugin/src/Caelestia/CMakeLists.txt @@ -1,6 +1,5 @@ find_package(Qt6 REQUIRED COMPONENTS Core Qml Gui Quick Concurrent Sql Network DBus) find_package(PkgConfig REQUIRED) -pkg_check_modules(Qalculate IMPORTED_TARGET libqalculate REQUIRED) pkg_check_modules(Pipewire IMPORTED_TARGET libpipewire-0.3 REQUIRED) pkg_check_modules(Aubio IMPORTED_TARGET aubio REQUIRED) pkg_check_modules(Cava IMPORTED_TARGET cava REQUIRED) @@ -41,7 +40,6 @@ qml_module(caelestia URI Caelestia SOURCES cutils.hpp cutils.cpp - qalculator.hpp qalculator.cpp appdb.hpp appdb.cpp requests.hpp requests.cpp toaster.hpp toaster.cpp @@ -51,9 +49,7 @@ qml_module(caelestia Qt::Quick Qt::Concurrent Qt::Sql - PkgConfig::Qalculate ) add_subdirectory(Internal) -add_subdirectory(Models) add_subdirectory(Services) diff --git a/plugin/src/Caelestia/Internal/CMakeLists.txt b/plugin/src/Caelestia/Internal/CMakeLists.txt index bdc58db..0240de8 100644 --- a/plugin/src/Caelestia/Internal/CMakeLists.txt +++ b/plugin/src/Caelestia/Internal/CMakeLists.txt @@ -1,7 +1,6 @@ qml_module(caelestia-internal URI Caelestia.Internal SOURCES - cachingimagemanager.hpp cachingimagemanager.cpp circularindicatormanager.hpp circularindicatormanager.cpp hyprdevices.hpp hyprdevices.cpp hyprextras.hpp hyprextras.cpp diff --git a/plugin/src/Caelestia/Internal/cachingimagemanager.cpp b/plugin/src/Caelestia/Internal/cachingimagemanager.cpp deleted file mode 100644 index 1c15cd2..0000000 --- a/plugin/src/Caelestia/Internal/cachingimagemanager.cpp +++ /dev/null @@ -1,223 +0,0 @@ -#include "cachingimagemanager.hpp" - -#include <QtQuick/qquickwindow.h> -#include <qcryptographichash.h> -#include <qdir.h> -#include <qfileinfo.h> -#include <qfuturewatcher.h> -#include <qimagereader.h> -#include <qpainter.h> -#include <qtconcurrentrun.h> - -namespace caelestia::internal { - -qreal CachingImageManager::effectiveScale() const { - if (m_item && m_item->window()) { - return m_item->window()->devicePixelRatio(); - } - - return 1.0; -} - -QSize CachingImageManager::effectiveSize() const { - if (!m_item) { - return QSize(); - } - - const qreal scale = effectiveScale(); - const QSize size = QSizeF(m_item->width() * scale, m_item->height() * scale).toSize(); - m_item->setProperty("sourceSize", size); - return size; -} - -QQuickItem* CachingImageManager::item() const { - return m_item; -} - -void CachingImageManager::setItem(QQuickItem* item) { - if (m_item == item) { - return; - } - - if (m_widthConn) { - disconnect(m_widthConn); - } - if (m_heightConn) { - disconnect(m_heightConn); - } - - m_item = item; - emit itemChanged(); - - if (item) { - m_widthConn = connect(item, &QQuickItem::widthChanged, this, [this]() { - updateSource(); - }); - m_heightConn = connect(item, &QQuickItem::heightChanged, this, [this]() { - updateSource(); - }); - updateSource(); - } -} - -QUrl CachingImageManager::cacheDir() const { - return m_cacheDir; -} - -void CachingImageManager::setCacheDir(const QUrl& cacheDir) { - if (m_cacheDir == cacheDir) { - return; - } - - m_cacheDir = cacheDir; - if (!m_cacheDir.path().endsWith("/")) { - m_cacheDir.setPath(m_cacheDir.path() + "/"); - } - emit cacheDirChanged(); -} - -QString CachingImageManager::path() const { - return m_path; -} - -void CachingImageManager::setPath(const QString& path) { - if (m_path == path) { - return; - } - - m_path = path; - emit pathChanged(); - - if (!path.isEmpty()) { - updateSource(path); - } -} - -void CachingImageManager::updateSource() { - updateSource(m_path); -} - -void CachingImageManager::updateSource(const QString& path) { - if (path.isEmpty() || path == m_shaPath) { - // Path is empty or already calculating sha for path - return; - } - - m_shaPath = path; - - const auto future = QtConcurrent::run(&CachingImageManager::sha256sum, path); - - const auto watcher = new QFutureWatcher<QString>(this); - - connect(watcher, &QFutureWatcher<QString>::finished, this, [watcher, path, this]() { - if (m_path != path) { - // Object is destroyed or path has changed, ignore - watcher->deleteLater(); - return; - } - - const QSize size = effectiveSize(); - - if (!m_item || !size.width() || !size.height()) { - watcher->deleteLater(); - return; - } - - const QString fillMode = m_item->property("fillMode").toString(); - // clang-format off - const QString filename = QString("%1@%2x%3-%4.png") - .arg(watcher->result()).arg(size.width()).arg(size.height()) - .arg(fillMode == "PreserveAspectCrop" ? "crop" : fillMode == "PreserveAspectFit" ? "fit" : "stretch"); - // clang-format on - - const QUrl cache = m_cacheDir.resolved(QUrl(filename)); - if (m_cachePath == cache) { - watcher->deleteLater(); - return; - } - - m_cachePath = cache; - emit cachePathChanged(); - - if (!cache.isLocalFile()) { - qWarning() << "CachingImageManager::updateSource: cachePath" << cache << "is not a local file"; - watcher->deleteLater(); - return; - } - - const QImageReader reader(cache.toLocalFile()); - if (reader.canRead()) { - m_item->setProperty("source", cache); - } else { - m_item->setProperty("source", QUrl::fromLocalFile(path)); - createCache(path, cache.toLocalFile(), fillMode, size); - } - - // Clear current running sha if same - if (m_shaPath == path) { - m_shaPath = QString(); - } - - watcher->deleteLater(); - }); - - watcher->setFuture(future); -} - -QUrl CachingImageManager::cachePath() const { - return m_cachePath; -} - -void CachingImageManager::createCache( - const QString& path, const QString& cache, const QString& fillMode, const QSize& size) const { - QThreadPool::globalInstance()->start([path, cache, fillMode, size] { - QImage image(path); - - if (image.isNull()) { - qWarning() << "CachingImageManager::createCache: failed to read" << path; - return; - } - - image.convertTo(QImage::Format_ARGB32); - - if (fillMode == "PreserveAspectCrop") { - image = image.scaled(size, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); - } else if (fillMode == "PreserveAspectFit") { - image = image.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); - } else { - image = image.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - } - - if (fillMode == "PreserveAspectCrop" || fillMode == "PreserveAspectFit") { - QImage canvas(size, QImage::Format_ARGB32); - canvas.fill(Qt::transparent); - - QPainter painter(&canvas); - painter.drawImage((size.width() - image.width()) / 2, (size.height() - image.height()) / 2, image); - painter.end(); - - image = canvas; - } - - const QString parent = QFileInfo(cache).absolutePath(); - if (!QDir().mkpath(parent) || !image.save(cache)) { - qWarning() << "CachingImageManager::createCache: failed to save to" << cache; - } - }); -} - -QString CachingImageManager::sha256sum(const QString& path) { - QFile file(path); - if (!file.open(QIODevice::ReadOnly)) { - qWarning() << "CachingImageManager::sha256sum: failed to open" << path; - return ""; - } - - QCryptographicHash hash(QCryptographicHash::Sha256); - hash.addData(&file); - file.close(); - - return hash.result().toHex(); -} - -} // namespace caelestia::internal diff --git a/plugin/src/Caelestia/Internal/cachingimagemanager.hpp b/plugin/src/Caelestia/Internal/cachingimagemanager.hpp deleted file mode 100644 index 3611699..0000000 --- a/plugin/src/Caelestia/Internal/cachingimagemanager.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include <QtQuick/qquickitem.h> -#include <qobject.h> -#include <qqmlintegration.h> - -namespace caelestia::internal { - -class CachingImageManager : public QObject { - Q_OBJECT - QML_ELEMENT - - Q_PROPERTY(QQuickItem* item READ item WRITE setItem NOTIFY itemChanged REQUIRED) - Q_PROPERTY(QUrl cacheDir READ cacheDir WRITE setCacheDir NOTIFY cacheDirChanged REQUIRED) - - Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) - Q_PROPERTY(QUrl cachePath READ cachePath NOTIFY cachePathChanged) - -public: - explicit CachingImageManager(QObject* parent = nullptr) - : QObject(parent) - , m_item(nullptr) {} - - [[nodiscard]] QQuickItem* item() const; - void setItem(QQuickItem* item); - - [[nodiscard]] QUrl cacheDir() const; - void setCacheDir(const QUrl& cacheDir); - - [[nodiscard]] QString path() const; - void setPath(const QString& path); - - [[nodiscard]] QUrl cachePath() const; - - Q_INVOKABLE void updateSource(); - Q_INVOKABLE void updateSource(const QString& path); - -signals: - void itemChanged(); - void cacheDirChanged(); - - void pathChanged(); - void cachePathChanged(); - void usingCacheChanged(); - -private: - QString m_shaPath; - - QQuickItem* m_item; - QUrl m_cacheDir; - - QString m_path; - QUrl m_cachePath; - - QMetaObject::Connection m_widthConn; - QMetaObject::Connection m_heightConn; - - [[nodiscard]] qreal effectiveScale() const; - [[nodiscard]] QSize effectiveSize() const; - - void createCache(const QString& path, const QString& cache, const QString& fillMode, const QSize& size) const; - [[nodiscard]] static QString sha256sum(const QString& path); -}; - -} // namespace caelestia::internal diff --git a/plugin/src/Caelestia/Models/CMakeLists.txt b/plugin/src/Caelestia/Models/CMakeLists.txt deleted file mode 100644 index 640e29e..0000000 --- a/plugin/src/Caelestia/Models/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -qml_module(caelestia-models - URI Caelestia.Models - SOURCES - filesystemmodel.hpp filesystemmodel.cpp - LIBRARIES - Qt::Gui - Qt::Concurrent -) diff --git a/plugin/src/Caelestia/Models/filesystemmodel.cpp b/plugin/src/Caelestia/Models/filesystemmodel.cpp deleted file mode 100644 index e387ecd..0000000 --- a/plugin/src/Caelestia/Models/filesystemmodel.cpp +++ /dev/null @@ -1,479 +0,0 @@ -#include "filesystemmodel.hpp" - -#include <qdiriterator.h> -#include <qfuturewatcher.h> -#include <qtconcurrentrun.h> - -namespace caelestia::models { - -FileSystemEntry::FileSystemEntry(const QString& path, const QString& relativePath, QObject* parent) - : QObject(parent) - , m_fileInfo(path) - , m_path(path) - , m_relativePath(relativePath) - , m_isImageInitialised(false) - , m_mimeTypeInitialised(false) {} - -QString FileSystemEntry::path() const { - return m_path; -}; - -QString FileSystemEntry::relativePath() const { - return m_relativePath; -}; - -QString FileSystemEntry::name() const { - return m_fileInfo.fileName(); -}; - -QString FileSystemEntry::baseName() const { - return m_fileInfo.baseName(); -}; - -QString FileSystemEntry::parentDir() const { - return m_fileInfo.absolutePath(); -}; - -QString FileSystemEntry::suffix() const { - return m_fileInfo.completeSuffix(); -}; - -qint64 FileSystemEntry::size() const { - return m_fileInfo.size(); -}; - -bool FileSystemEntry::isDir() const { - return m_fileInfo.isDir(); -}; - -bool FileSystemEntry::isImage() const { - if (!m_isImageInitialised) { - QImageReader reader(m_path); - m_isImage = reader.canRead(); - m_isImageInitialised = true; - } - return m_isImage; -} - -QString FileSystemEntry::mimeType() const { - if (!m_mimeTypeInitialised) { - const QMimeDatabase db; - m_mimeType = db.mimeTypeForFile(m_path).name(); - m_mimeTypeInitialised = true; - } - return m_mimeType; -} - -void FileSystemEntry::updateRelativePath(const QDir& dir) { - const auto relPath = dir.relativeFilePath(m_path); - if (m_relativePath != relPath) { - m_relativePath = relPath; - emit relativePathChanged(); - } -} - -FileSystemModel::FileSystemModel(QObject* parent) - : QAbstractListModel(parent) - , m_recursive(false) - , m_watchChanges(true) - , m_showHidden(false) - , m_filter(NoFilter) { - connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::watchDirIfRecursive); - connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::updateEntriesForDir); -} - -int FileSystemModel::rowCount(const QModelIndex& parent) const { - if (parent != QModelIndex()) { - return 0; - } - return static_cast<int>(m_entries.size()); -} - -QVariant FileSystemModel::data(const QModelIndex& index, int role) const { - if (role != Qt::UserRole || !index.isValid() || index.row() >= m_entries.size()) { - return QVariant(); - } - return QVariant::fromValue(m_entries.at(index.row())); -} - -QHash<int, QByteArray> FileSystemModel::roleNames() const { - return { { Qt::UserRole, "modelData" } }; -} - -QString FileSystemModel::path() const { - return m_path; -} - -void FileSystemModel::setPath(const QString& path) { - if (m_path == path) { - return; - } - - m_path = path; - emit pathChanged(); - - m_dir.setPath(m_path); - - for (const auto& entry : std::as_const(m_entries)) { - entry->updateRelativePath(m_dir); - } - - update(); -} - -bool FileSystemModel::recursive() const { - return m_recursive; -} - -void FileSystemModel::setRecursive(bool recursive) { - if (m_recursive == recursive) { - return; - } - - m_recursive = recursive; - emit recursiveChanged(); - - update(); -} - -bool FileSystemModel::watchChanges() const { - return m_watchChanges; -} - -void FileSystemModel::setWatchChanges(bool watchChanges) { - if (m_watchChanges == watchChanges) { - return; - } - - m_watchChanges = watchChanges; - emit watchChangesChanged(); - - update(); -} - -bool FileSystemModel::showHidden() const { - return m_showHidden; -} - -void FileSystemModel::setShowHidden(bool showHidden) { - if (m_showHidden == showHidden) { - return; - } - - m_showHidden = showHidden; - emit showHiddenChanged(); - - update(); -} - -bool FileSystemModel::sortReverse() const { - return m_sortReverse; -} - -void FileSystemModel::setSortReverse(bool sortReverse) { - if (m_sortReverse == sortReverse) { - return; - } - - m_sortReverse = sortReverse; - emit sortReverseChanged(); - - update(); -} - -FileSystemModel::Filter FileSystemModel::filter() const { - return m_filter; -} - -void FileSystemModel::setFilter(Filter filter) { - if (m_filter == filter) { - return; - } - - m_filter = filter; - emit filterChanged(); - - update(); -} - -QStringList FileSystemModel::nameFilters() const { - return m_nameFilters; -} - -void FileSystemModel::setNameFilters(const QStringList& nameFilters) { - if (m_nameFilters == nameFilters) { - return; - } - - m_nameFilters = nameFilters; - emit nameFiltersChanged(); - - update(); -} - -QQmlListProperty<FileSystemEntry> FileSystemModel::entries() { - return QQmlListProperty<FileSystemEntry>(this, &m_entries); -} - -void FileSystemModel::watchDirIfRecursive(const QString& path) { - if (m_recursive && m_watchChanges) { - const auto currentDir = m_dir; - const bool showHidden = m_showHidden; - const auto future = QtConcurrent::run([showHidden, path]() { - QDir::Filters filters = QDir::Dirs | QDir::NoDotAndDotDot; - if (showHidden) { - filters |= QDir::Hidden; - } - - QDirIterator iter(path, filters, QDirIterator::Subdirectories); - QStringList dirs; - while (iter.hasNext()) { - dirs << iter.next(); - } - return dirs; - }); - const auto watcher = new QFutureWatcher<QStringList>(this); - connect(watcher, &QFutureWatcher<QStringList>::finished, this, [currentDir, showHidden, watcher, this]() { - const auto paths = watcher->result(); - if (currentDir == m_dir && showHidden == m_showHidden && !paths.isEmpty()) { - // Ignore if dir or showHidden has changed - m_watcher.addPaths(paths); - } - watcher->deleteLater(); - }); - watcher->setFuture(future); - } -} - -void FileSystemModel::update() { - updateWatcher(); - updateEntries(); -} - -void FileSystemModel::updateWatcher() { - if (!m_watcher.directories().isEmpty()) { - m_watcher.removePaths(m_watcher.directories()); - } - - if (!m_watchChanges || m_path.isEmpty()) { - return; - } - - m_watcher.addPath(m_path); - watchDirIfRecursive(m_path); -} - -void FileSystemModel::updateEntries() { - if (m_path.isEmpty()) { - if (!m_entries.isEmpty()) { - beginResetModel(); - qDeleteAll(m_entries); - m_entries.clear(); - endResetModel(); - emit entriesChanged(); - } - - return; - } - - for (auto& future : m_futures) { - future.cancel(); - } - m_futures.clear(); - - updateEntriesForDir(m_path); -} - -void FileSystemModel::updateEntriesForDir(const QString& dir) { - const auto recursive = m_recursive; - const auto showHidden = m_showHidden; - const auto filter = m_filter; - const auto nameFilters = m_nameFilters; - - QSet<QString> oldPaths; - for (const auto& entry : std::as_const(m_entries)) { - oldPaths << entry->path(); - } - - const auto future = QtConcurrent::run([=](QPromise<QPair<QSet<QString>, QSet<QString>>>& promise) { - const auto flags = recursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; - - std::optional<QDirIterator> iter; - - if (filter == Images) { - QStringList extraNameFilters = nameFilters; - const auto formats = QImageReader::supportedImageFormats(); - for (const auto& format : formats) { - extraNameFilters << "*." + format; - } - - QDir::Filters filters = QDir::Files; - if (showHidden) { - filters |= QDir::Hidden; - } - - iter.emplace(dir, extraNameFilters, filters, flags); - } else { - QDir::Filters filters; - - if (filter == Files) { - filters = QDir::Files; - } else if (filter == Dirs) { - filters = QDir::Dirs | QDir::NoDotAndDotDot; - } else { - filters = QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot; - } - - if (showHidden) { - filters |= QDir::Hidden; - } - - if (nameFilters.isEmpty()) { - iter.emplace(dir, filters, flags); - } else { - iter.emplace(dir, nameFilters, filters, flags); - } - } - - QSet<QString> newPaths; - while (iter->hasNext()) { - if (promise.isCanceled()) { - return; - } - - QString path = iter->next(); - - if (filter == Images) { - QImageReader reader(path); - if (!reader.canRead()) { - continue; - } - } - - newPaths.insert(path); - } - - if (promise.isCanceled() || newPaths == oldPaths) { - return; - } - - promise.addResult(qMakePair(oldPaths - newPaths, newPaths - oldPaths)); - }); - - if (m_futures.contains(dir)) { - m_futures[dir].cancel(); - } - m_futures.insert(dir, future); - - const auto watcher = new QFutureWatcher<QPair<QSet<QString>, QSet<QString>>>(this); - - connect(watcher, &QFutureWatcher<QPair<QSet<QString>, QSet<QString>>>::finished, this, [dir, watcher, this]() { - m_futures.remove(dir); - - if (!watcher->future().isResultReadyAt(0)) { - watcher->deleteLater(); - return; - } - - const auto result = watcher->result(); - applyChanges(result.first, result.second); - - watcher->deleteLater(); - }); - - watcher->setFuture(future); -} - -void FileSystemModel::applyChanges(const QSet<QString>& removedPaths, const QSet<QString>& addedPaths) { - QList<int> removedIndices; - for (int i = 0; i < m_entries.size(); ++i) { - if (removedPaths.contains(m_entries[i]->path())) { - removedIndices << i; - } - } - std::sort(removedIndices.begin(), removedIndices.end(), std::greater<int>()); - - // Batch remove old entries - int start = -1; - int end = -1; - for (int idx : std::as_const(removedIndices)) { - if (start == -1) { - start = idx; - end = idx; - } else if (idx == end - 1) { - end = idx; - } else { - beginRemoveRows(QModelIndex(), end, start); - for (int i = start; i >= end; --i) { - m_entries.takeAt(i)->deleteLater(); - } - endRemoveRows(); - - start = idx; - end = idx; - } - } - if (start != -1) { - beginRemoveRows(QModelIndex(), end, start); - for (int i = start; i >= end; --i) { - m_entries.takeAt(i)->deleteLater(); - } - endRemoveRows(); - } - - // Create new entries - QList<FileSystemEntry*> newEntries; - for (const auto& path : addedPaths) { - newEntries << new FileSystemEntry(path, m_dir.relativeFilePath(path), this); - } - std::sort(newEntries.begin(), newEntries.end(), [this](const FileSystemEntry* a, const FileSystemEntry* b) { - return compareEntries(a, b); - }); - - // Batch insert new entries - int insertStart = -1; - QList<FileSystemEntry*> batchItems; - for (const auto& entry : std::as_const(newEntries)) { - const auto it = std::lower_bound( - m_entries.begin(), m_entries.end(), entry, [this](const FileSystemEntry* a, const FileSystemEntry* b) { - return compareEntries(a, b); - }); - const auto row = static_cast<int>(it - m_entries.begin()); - - if (insertStart == -1) { - insertStart = row; - batchItems << entry; - } else if (row == insertStart + batchItems.size()) { - batchItems << entry; - } else { - beginInsertRows(QModelIndex(), insertStart, insertStart + static_cast<int>(batchItems.size()) - 1); - for (int i = 0; i < batchItems.size(); ++i) { - m_entries.insert(insertStart + i, batchItems[i]); - } - endInsertRows(); - - insertStart = row; - batchItems.clear(); - batchItems << entry; - } - } - if (!batchItems.isEmpty()) { - beginInsertRows(QModelIndex(), insertStart, insertStart + static_cast<int>(batchItems.size()) - 1); - for (int i = 0; i < batchItems.size(); ++i) { - m_entries.insert(insertStart + i, batchItems[i]); - } - endInsertRows(); - } - - emit entriesChanged(); -} - -bool FileSystemModel::compareEntries(const FileSystemEntry* a, const FileSystemEntry* b) const { - if (a->isDir() != b->isDir()) { - return m_sortReverse ^ a->isDir(); - } - const auto cmp = a->relativePath().localeAwareCompare(b->relativePath()); - return m_sortReverse ? cmp > 0 : cmp < 0; -} - -} // namespace caelestia::models diff --git a/plugin/src/Caelestia/Models/filesystemmodel.hpp b/plugin/src/Caelestia/Models/filesystemmodel.hpp deleted file mode 100644 index cf8eae8..0000000 --- a/plugin/src/Caelestia/Models/filesystemmodel.hpp +++ /dev/null @@ -1,148 +0,0 @@ -#pragma once - -#include <qabstractitemmodel.h> -#include <qdir.h> -#include <qfilesystemwatcher.h> -#include <qfuture.h> -#include <qimagereader.h> -#include <qmimedatabase.h> -#include <qobject.h> -#include <qqmlintegration.h> -#include <qqmllist.h> - -namespace caelestia::models { - -class FileSystemEntry : public QObject { - Q_OBJECT - QML_ELEMENT - QML_UNCREATABLE("FileSystemEntry instances can only be retrieved from a FileSystemModel") - - Q_PROPERTY(QString path READ path CONSTANT) - Q_PROPERTY(QString relativePath READ relativePath NOTIFY relativePathChanged) - Q_PROPERTY(QString name READ name CONSTANT) - Q_PROPERTY(QString baseName READ baseName CONSTANT) - Q_PROPERTY(QString parentDir READ parentDir CONSTANT) - Q_PROPERTY(QString suffix READ suffix CONSTANT) - Q_PROPERTY(qint64 size READ size CONSTANT) - Q_PROPERTY(bool isDir READ isDir CONSTANT) - Q_PROPERTY(bool isImage READ isImage CONSTANT) - Q_PROPERTY(QString mimeType READ mimeType CONSTANT) - -public: - explicit FileSystemEntry(const QString& path, const QString& relativePath, QObject* parent = nullptr); - - [[nodiscard]] QString path() const; - [[nodiscard]] QString relativePath() const; - [[nodiscard]] QString name() const; - [[nodiscard]] QString baseName() const; - [[nodiscard]] QString parentDir() const; - [[nodiscard]] QString suffix() const; - [[nodiscard]] qint64 size() const; - [[nodiscard]] bool isDir() const; - [[nodiscard]] bool isImage() const; - [[nodiscard]] QString mimeType() const; - - void updateRelativePath(const QDir& dir); - -signals: - void relativePathChanged(); - -private: - const QFileInfo m_fileInfo; - - const QString m_path; - QString m_relativePath; - - mutable bool m_isImage; - mutable bool m_isImageInitialised; - - mutable QString m_mimeType; - mutable bool m_mimeTypeInitialised; -}; - -class FileSystemModel : public QAbstractListModel { - Q_OBJECT - QML_ELEMENT - - Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) - Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged) - Q_PROPERTY(bool watchChanges READ watchChanges WRITE setWatchChanges NOTIFY watchChangesChanged) - Q_PROPERTY(bool showHidden READ showHidden WRITE setShowHidden NOTIFY showHiddenChanged) - Q_PROPERTY(bool sortReverse READ sortReverse WRITE setSortReverse NOTIFY sortReverseChanged) - Q_PROPERTY(Filter filter READ filter WRITE setFilter NOTIFY filterChanged) - Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged) - - Q_PROPERTY(QQmlListProperty<caelestia::models::FileSystemEntry> entries READ entries NOTIFY entriesChanged) - -public: - enum Filter { - NoFilter, - Images, - Files, - Dirs - }; - Q_ENUM(Filter) - - explicit FileSystemModel(QObject* parent = nullptr); - - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - QHash<int, QByteArray> roleNames() const override; - - [[nodiscard]] QString path() const; - void setPath(const QString& path); - - [[nodiscard]] bool recursive() const; - void setRecursive(bool recursive); - - [[nodiscard]] bool watchChanges() const; - void setWatchChanges(bool watchChanges); - - [[nodiscard]] bool showHidden() const; - void setShowHidden(bool showHidden); - - [[nodiscard]] bool sortReverse() const; - void setSortReverse(bool sortReverse); - - [[nodiscard]] Filter filter() const; - void setFilter(Filter filter); - - [[nodiscard]] QStringList nameFilters() const; - void setNameFilters(const QStringList& nameFilters); - - [[nodiscard]] QQmlListProperty<FileSystemEntry> entries(); - -signals: - void pathChanged(); - void recursiveChanged(); - void watchChangesChanged(); - void showHiddenChanged(); - void sortReverseChanged(); - void filterChanged(); - void nameFiltersChanged(); - void entriesChanged(); - -private: - QDir m_dir; - QFileSystemWatcher m_watcher; - QList<FileSystemEntry*> m_entries; - QHash<QString, QFuture<QPair<QSet<QString>, QSet<QString>>>> m_futures; - - QString m_path; - bool m_recursive; - bool m_watchChanges; - bool m_showHidden; - bool m_sortReverse; - Filter m_filter; - QStringList m_nameFilters; - - void watchDirIfRecursive(const QString& path); - void update(); - void updateWatcher(); - void updateEntries(); - void updateEntriesForDir(const QString& dir); - void applyChanges(const QSet<QString>& removedPaths, const QSet<QString>& addedPaths); - [[nodiscard]] bool compareEntries(const FileSystemEntry* a, const FileSystemEntry* b) const; -}; - -} // namespace caelestia::models diff --git a/plugin/src/Caelestia/qalculator.cpp b/plugin/src/Caelestia/qalculator.cpp deleted file mode 100644 index 44e8d21..0000000 --- a/plugin/src/Caelestia/qalculator.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "qalculator.hpp" - -#include <libqalculate/qalculate.h> - -namespace caelestia { - -Qalculator::Qalculator(QObject* parent) - : QObject(parent) { - if (!CALCULATOR) { - new Calculator(); - CALCULATOR->loadExchangeRates(); - CALCULATOR->loadGlobalDefinitions(); - CALCULATOR->loadLocalDefinitions(); - } -} - -QString Qalculator::eval(const QString& expr, bool printExpr) const { - if (expr.isEmpty()) { - return QString(); - } - - EvaluationOptions eo; - PrintOptions po; - - std::string parsed; - std::string result = CALCULATOR->calculateAndPrint( - CALCULATOR->unlocalizeExpression(expr.toStdString(), eo.parse_options), 100, eo, po, &parsed); - - std::string error; - while (CALCULATOR->message()) { - if (!CALCULATOR->message()->message().empty()) { - if (CALCULATOR->message()->type() == MESSAGE_ERROR) { - error += "error: "; - } else if (CALCULATOR->message()->type() == MESSAGE_WARNING) { - error += "warning: "; - } - error += CALCULATOR->message()->message(); - } - CALCULATOR->nextMessage(); - } - if (!error.empty()) { - return QString::fromStdString(error); - } - - if (printExpr) { - return QString("%1 = %2").arg(parsed).arg(result); - } - - return QString::fromStdString(result); -} - -} // namespace caelestia diff --git a/plugin/src/Caelestia/qalculator.hpp b/plugin/src/Caelestia/qalculator.hpp deleted file mode 100644 index a07a8a2..0000000 --- a/plugin/src/Caelestia/qalculator.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include <qobject.h> -#include <qqmlintegration.h> - -namespace caelestia { - -class Qalculator : public QObject { - Q_OBJECT - QML_ELEMENT - QML_SINGLETON - -public: - explicit Qalculator(QObject* parent = nullptr); - - Q_INVOKABLE QString eval(const QString& expr, bool printExpr = true) const; -}; - -} // namespace caelestia diff --git a/utils/Paths.qml b/utils/Paths.qml index c8f74d7..3b7e84f 100644 --- a/utils/Paths.qml +++ b/utils/Paths.qml @@ -19,6 +19,7 @@ Singleton { readonly property string imagecache: `${cache}/imagecache` readonly property string notifimagecache: `${imagecache}/notifs` readonly property string wallpaper: Quickshell.env("CAELESTIA_WALLPAPER") || absolutePath(Config.paths.wallpaper) + readonly property string face: Quickshell.env("CAELESTIA_FACE") || absolutePath(Config.paths.face) readonly property string libdir: Quickshell.env("CAELESTIA_LIB_DIR") || "/usr/lib/caelestia" function toLocalFile(path: url): string { |