From 58826b7deb07f187d2c2c8cac3bf651a008b4646 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sat, 19 Jul 2025 16:59:32 +1000 Subject: internal: move launcher stuff into subfolders --- modules/launcher/ActionItem.qml | 69 ------------- modules/launcher/Actions.qml | 156 ----------------------------- modules/launcher/AppItem.qml | 72 -------------- modules/launcher/AppList.qml | 2 + modules/launcher/CalcItem.qml | 162 ------------------------------- modules/launcher/M3Variants.qml | 84 ---------------- modules/launcher/SchemeItem.qml | 93 ------------------ modules/launcher/Schemes.qml | 66 ------------- modules/launcher/VariantItem.qml | 69 ------------- modules/launcher/WallpaperItem.qml | 96 ------------------ modules/launcher/WallpaperList.qml | 2 +- modules/launcher/items/ActionItem.qml | 70 +++++++++++++ modules/launcher/items/AppItem.qml | 73 ++++++++++++++ modules/launcher/items/CalcItem.qml | 162 +++++++++++++++++++++++++++++++ modules/launcher/items/SchemeItem.qml | 92 ++++++++++++++++++ modules/launcher/items/VariantItem.qml | 70 +++++++++++++ modules/launcher/items/WallpaperItem.qml | 96 ++++++++++++++++++ modules/launcher/services/Actions.qml | 155 +++++++++++++++++++++++++++++ modules/launcher/services/Apps.qml | 25 +++++ modules/launcher/services/M3Variants.qml | 84 ++++++++++++++++ modules/launcher/services/Schemes.qml | 66 +++++++++++++ services/Apps.qml | 25 ----- 22 files changed, 896 insertions(+), 893 deletions(-) delete mode 100644 modules/launcher/ActionItem.qml delete mode 100644 modules/launcher/Actions.qml delete mode 100644 modules/launcher/AppItem.qml delete mode 100644 modules/launcher/CalcItem.qml delete mode 100644 modules/launcher/M3Variants.qml delete mode 100644 modules/launcher/SchemeItem.qml delete mode 100644 modules/launcher/Schemes.qml delete mode 100644 modules/launcher/VariantItem.qml delete mode 100644 modules/launcher/WallpaperItem.qml create mode 100644 modules/launcher/items/ActionItem.qml create mode 100644 modules/launcher/items/AppItem.qml create mode 100644 modules/launcher/items/CalcItem.qml create mode 100644 modules/launcher/items/SchemeItem.qml create mode 100644 modules/launcher/items/VariantItem.qml create mode 100644 modules/launcher/items/WallpaperItem.qml create mode 100644 modules/launcher/services/Actions.qml create mode 100644 modules/launcher/services/Apps.qml create mode 100644 modules/launcher/services/M3Variants.qml create mode 100644 modules/launcher/services/Schemes.qml delete mode 100644 services/Apps.qml diff --git a/modules/launcher/ActionItem.qml b/modules/launcher/ActionItem.qml deleted file mode 100644 index 82f5caa..0000000 --- a/modules/launcher/ActionItem.qml +++ /dev/null @@ -1,69 +0,0 @@ -import qs.widgets -import qs.services -import qs.config -import QtQuick - -Item { - id: root - - required property Actions.Action modelData - required property var list - - implicitHeight: Config.launcher.sizes.itemHeight - - anchors.left: parent?.left - anchors.right: parent?.right - - StateLayer { - radius: Appearance.rounding.full - - function onClicked(): void { - root.modelData?.onClicked(root.list); - } - } - - Item { - anchors.fill: parent - anchors.leftMargin: Appearance.padding.larger - anchors.rightMargin: Appearance.padding.larger - anchors.margins: Appearance.padding.smaller - - MaterialIcon { - id: icon - - text: root.modelData?.icon ?? "" - font.pointSize: Appearance.font.size.extraLarge - - anchors.verticalCenter: parent.verticalCenter - } - - Item { - anchors.left: icon.right - anchors.leftMargin: Appearance.spacing.normal - anchors.verticalCenter: icon.verticalCenter - - implicitWidth: parent.width - icon.width - implicitHeight: name.implicitHeight + desc.implicitHeight - - StyledText { - id: name - - text: root.modelData?.name ?? "" - font.pointSize: Appearance.font.size.normal - } - - StyledText { - id: desc - - text: root.modelData?.desc ?? "" - font.pointSize: Appearance.font.size.small - color: Colours.alpha(Colours.palette.m3outline, true) - - elide: Text.ElideRight - width: root.width - icon.width - Appearance.rounding.normal * 2 - - anchors.top: name.bottom - } - } - } -} diff --git a/modules/launcher/Actions.qml b/modules/launcher/Actions.qml deleted file mode 100644 index afe831b..0000000 --- a/modules/launcher/Actions.qml +++ /dev/null @@ -1,156 +0,0 @@ -pragma Singleton - -import qs.services -import qs.config -import qs.utils -import Quickshell -import QtQuick - -Searcher { - id: root - - property string qalcResult - - readonly property list actions: [ - Action { - name: qsTr("Calculator") - desc: qsTr("Do simple math equations (powered by Qalc)") - icon: "calculate" - - function onClicked(list: AppList): void { - root.autocomplete(list, "calc"); - } - }, - Action { - name: qsTr("Scheme") - desc: qsTr("Change the current colour scheme") - icon: "palette" - - function onClicked(list: AppList): void { - root.autocomplete(list, "scheme"); - } - }, - Action { - name: qsTr("Wallpaper") - desc: qsTr("Change the current wallpaper") - icon: "image" - - function onClicked(list: AppList): void { - root.autocomplete(list, "wallpaper"); - } - }, - Action { - name: qsTr("Variant") - desc: qsTr("Change the current scheme variant") - icon: "colors" - - function onClicked(list: AppList): void { - root.autocomplete(list, "variant"); - } - }, - Action { - name: qsTr("Transparency") - desc: qsTr("Change shell transparency") - icon: "opacity" - disabled: true - - function onClicked(list: AppList): void { - root.autocomplete(list, "transparency"); - } - }, - Action { - name: qsTr("Light") - desc: qsTr("Change the scheme to light mode") - icon: "light_mode" - - function onClicked(list: AppList): void { - list.visibilities.launcher = false; - Colours.setMode("light"); - } - }, - Action { - name: qsTr("Dark") - desc: qsTr("Change the scheme to dark mode") - icon: "dark_mode" - - function onClicked(list: AppList): void { - list.visibilities.launcher = false; - Colours.setMode("dark"); - } - }, - Action { - name: qsTr("Shutdown") - desc: qsTr("Shutdown the system") - icon: "power_settings_new" - disabled: !Config.launcher.enableDangerousActions - - function onClicked(list: AppList): void { - list.visibilities.launcher = false; - Quickshell.execDetached(["systemctl", "poweroff"]); - } - }, - Action { - name: qsTr("Reboot") - desc: qsTr("Reboot the system") - icon: "cached" - disabled: !Config.launcher.enableDangerousActions - - function onClicked(list: AppList): void { - list.visibilities.launcher = false; - Quickshell.execDetached(["systemctl", "reboot"]); - } - }, - Action { - name: qsTr("Logout") - desc: qsTr("Log out of the current session") - icon: "exit_to_app" - disabled: !Config.launcher.enableDangerousActions - - function onClicked(list: AppList): void { - list.visibilities.launcher = false; - Quickshell.execDetached(["loginctl", "terminate-user", ""]); - } - }, - Action { - name: qsTr("Lock") - desc: qsTr("Lock the current session") - icon: "lock" - - function onClicked(list: AppList): void { - list.visibilities.launcher = false; - Quickshell.execDetached(["loginctl", "lock-session"]); - } - }, - Action { - name: qsTr("Sleep") - desc: qsTr("Suspend then hibernate") - icon: "bedtime" - - function onClicked(list: AppList): void { - list.visibilities.launcher = false; - Quickshell.execDetached(["systemctl", "suspend-then-hibernate"]); - } - } - ] - - function transformSearch(search: string): string { - return search.slice(Config.launcher.actionPrefix.length); - } - - function autocomplete(list: AppList, text: string): void { - list.search.text = `${Config.launcher.actionPrefix}${text} `; - } - - list: actions.filter(a => !a.disabled) - useFuzzy: Config.launcher.useFuzzy.actions - - component Action: QtObject { - required property string name - required property string desc - required property string icon - property bool disabled - - function onClicked(list: AppList): void { - } - } -} diff --git a/modules/launcher/AppItem.qml b/modules/launcher/AppItem.qml deleted file mode 100644 index 2bb6b04..0000000 --- a/modules/launcher/AppItem.qml +++ /dev/null @@ -1,72 +0,0 @@ -import qs.widgets -import qs.services -import qs.config -import Quickshell -import Quickshell.Widgets -import QtQuick - -Item { - id: root - - required property DesktopEntry modelData - required property PersistentProperties visibilities - - implicitHeight: Config.launcher.sizes.itemHeight - - anchors.left: parent?.left - anchors.right: parent?.right - - StateLayer { - radius: Appearance.rounding.full - - function onClicked(): void { - Apps.launch(root.modelData); - root.visibilities.launcher = false; - } - } - - Item { - anchors.fill: parent - anchors.leftMargin: Appearance.padding.larger - anchors.rightMargin: Appearance.padding.larger - anchors.margins: Appearance.padding.smaller - - IconImage { - id: icon - - source: Quickshell.iconPath(root.modelData?.icon, "image-missing") - implicitSize: parent.height * 0.8 - - anchors.verticalCenter: parent.verticalCenter - } - - Item { - anchors.left: icon.right - anchors.leftMargin: Appearance.spacing.normal - anchors.verticalCenter: icon.verticalCenter - - implicitWidth: parent.width - icon.width - implicitHeight: name.implicitHeight + comment.implicitHeight - - StyledText { - id: name - - text: root.modelData?.name ?? "" - font.pointSize: Appearance.font.size.normal - } - - StyledText { - id: comment - - text: (root.modelData?.comment || root.modelData?.genericName || root.modelData?.name) ?? "" - font.pointSize: Appearance.font.size.small - color: Colours.alpha(Colours.palette.m3outline, true) - - elide: Text.ElideRight - width: root.width - icon.width - Appearance.rounding.normal * 2 - - anchors.top: name.bottom - } - } - } -} diff --git a/modules/launcher/AppList.qml b/modules/launcher/AppList.qml index 857515a..3a994d3 100644 --- a/modules/launcher/AppList.qml +++ b/modules/launcher/AppList.qml @@ -1,5 +1,7 @@ pragma ComponentBehavior: Bound +import "items" +import "services" import qs.widgets import qs.services import qs.config diff --git a/modules/launcher/CalcItem.qml b/modules/launcher/CalcItem.qml deleted file mode 100644 index 2e3c901..0000000 --- a/modules/launcher/CalcItem.qml +++ /dev/null @@ -1,162 +0,0 @@ -import qs.widgets -import qs.services -import qs.config -import Quickshell -import Quickshell.Io -import QtQuick -import QtQuick.Layouts - -Item { - id: root - - required property var list - readonly property string math: list.search.text.slice(`${Config.launcher.actionPrefix}calc `.length) - - function onClicked(): void { - Quickshell.execDetached(["sh", "-c", `qalc -t -m 100 '${root.math}' | wl-copy`]); - root.list.visibilities.launcher = false; - } - - implicitHeight: Config.launcher.sizes.itemHeight - - anchors.left: parent?.left - anchors.right: parent?.right - - onMathChanged: { - if (math) { - qalcProc.command = ["qalc", "-m", "100", math]; - qalcProc.running = true; - } - } - - StateLayer { - radius: Appearance.rounding.full - - function onClicked(): void { - root.onClicked(); - } - } - - Binding { - id: binding - - when: root.math.length > 0 - target: metrics - property: "text" - } - - Process { - id: qalcProc - - stdout: StdioCollector { - onStreamFinished: binding.value = text.trim() - } - } - - RowLayout { - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.margins: Appearance.padding.larger - - spacing: Appearance.spacing.normal - - MaterialIcon { - text: "function" - font.pointSize: Appearance.font.size.extraLarge - Layout.alignment: Qt.AlignVCenter - } - - StyledText { - id: result - - color: { - if (metrics.text.includes("error: ")) - return Colours.palette.m3error; - if (!root.math) - return Colours.palette.m3onSurfaceVariant; - return Colours.palette.m3onSurface; - } - - text: metrics.elidedText - font.pointSize: Appearance.font.size.normal - - Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter - - TextMetrics { - id: metrics - - text: qsTr("Type an expression to calculate") - font.family: result.font.family - font.pointSize: result.font.pointSize - elide: Text.ElideRight - elideWidth: result.width - } - } - - StyledRect { - color: Colours.palette.m3tertiary - radius: Appearance.rounding.normal - clip: true - - implicitWidth: (stateLayer.containsMouse ? label.implicitWidth + label.anchors.rightMargin : 0) + icon.implicitWidth + Appearance.padding.normal * 2 - implicitHeight: Math.max(label.implicitHeight, icon.implicitHeight) + Appearance.padding.small * 2 - - Layout.alignment: Qt.AlignVCenter - - StateLayer { - id: stateLayer - - color: Colours.palette.m3onTertiary - - function onClicked(): void { - Quickshell.execDetached(["app2unit", "--", "foot", "fish", "-C", `exec qalc -i '${root.math}'`]); - root.list.visibilities.launcher = false; - } - } - - StyledText { - id: label - - anchors.verticalCenter: parent.verticalCenter - anchors.right: icon.left - anchors.rightMargin: Appearance.spacing.small - - text: qsTr("Open in calculator") - color: Colours.palette.m3onTertiary - font.pointSize: Appearance.font.size.normal - - opacity: stateLayer.containsMouse ? 1 : 0 - - Behavior on opacity { - NumberAnimation { - duration: Appearance.anim.durations.normal - easing.type: Easing.BezierSpline - easing.bezierCurve: Appearance.anim.curves.standard - } - } - } - - MaterialIcon { - id: icon - - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: Appearance.padding.normal - - text: "open_in_new" - color: Colours.palette.m3onTertiary - font.pointSize: Appearance.font.size.large - } - - Behavior on implicitWidth { - NumberAnimation { - duration: Appearance.anim.durations.normal - easing.type: Easing.BezierSpline - easing.bezierCurve: Appearance.anim.curves.emphasized - } - } - } - } -} diff --git a/modules/launcher/M3Variants.qml b/modules/launcher/M3Variants.qml deleted file mode 100644 index 69bd805..0000000 --- a/modules/launcher/M3Variants.qml +++ /dev/null @@ -1,84 +0,0 @@ -pragma Singleton - -import qs.config -import qs.utils -import Quickshell -import QtQuick - -Searcher { - id: root - - function transformSearch(search: string): string { - return search.slice(`${Config.launcher.actionPrefix}variant `.length); - } - - list: [ - Variant { - variant: "vibrant" - icon: "sentiment_very_dissatisfied" - name: "Vibrant" - description: "A high chroma palette. The primary palette's chroma is at maximum." - }, - Variant { - variant: "tonalspot" - icon: "android" - name: "Tonal Spot" - description: "Default for Material theme colours. A pastel palette with a low chroma." - }, - Variant { - variant: "expressive" - icon: "compare_arrows" - name: "Expressive" - description: "A medium chroma palette. The primary palette's hue is different from the seed colour, for variety." - }, - Variant { - variant: "fidelity" - icon: "compare" - name: "Fidelity" - description: "Matches the seed colour, even if the seed colour is very bright (high chroma)." - }, - Variant { - variant: "content" - icon: "sentiment_calm" - name: "Content" - description: "Almost identical to fidelity." - }, - Variant { - variant: "fruitsalad" - icon: "nutrition" - name: "Fruit Salad" - description: "A playful theme - the seed colour's hue does not appear in the theme." - }, - Variant { - variant: "rainbow" - icon: "looks" - name: "Rainbow" - description: "A playful theme - the seed colour's hue does not appear in the theme." - }, - Variant { - variant: "neutral" - icon: "contrast" - name: "Neutral" - description: "Close to grayscale, a hint of chroma." - }, - Variant { - variant: "monochrome" - icon: "filter_b_and_w" - name: "Monochrome" - description: "All colours are grayscale, no chroma." - } - ] - useFuzzy: Config.launcher.useFuzzy.variants - - component Variant: QtObject { - required property string variant - required property string icon - required property string name - required property string description - - function onClicked(list: AppList): void { - list.visibilities.launcher = false; - Quickshell.execDetached(["caelestia", "scheme", "set", "-v", variant]); - } - } -} diff --git a/modules/launcher/SchemeItem.qml b/modules/launcher/SchemeItem.qml deleted file mode 100644 index 33ec672..0000000 --- a/modules/launcher/SchemeItem.qml +++ /dev/null @@ -1,93 +0,0 @@ -import qs.widgets -import qs.services -import qs.config -import Quickshell -import Quickshell.Widgets -import QtQuick - -Item { - id: root - - required property Schemes.Scheme modelData - required property var list - - implicitHeight: Config.launcher.sizes.itemHeight - - anchors.left: parent?.left - anchors.right: parent?.right - - StateLayer { - radius: Appearance.rounding.full - - function onClicked(): void { - root.modelData?.onClicked(root.list); - } - } - - Item { - anchors.fill: parent - anchors.leftMargin: Appearance.padding.larger - anchors.rightMargin: Appearance.padding.larger - anchors.margins: Appearance.padding.smaller - - StyledRect { - id: preview - - anchors.verticalCenter: parent.verticalCenter - - border.width: 1 - border.color: Qt.alpha(`#${root.modelData?.colours?.outline}`, 0.5) - - color: `#${root.modelData?.colours?.surface}` - radius: Appearance.rounding.full - implicitWidth: parent.height * 0.8 - implicitHeight: parent.height * 0.8 - - Item { - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: parent.right - - implicitWidth: parent.implicitWidth / 2 - clip: true - - StyledRect { - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: parent.right - - implicitWidth: preview.implicitWidth - color: `#${root.modelData?.colours?.primary}` - radius: Appearance.rounding.full - } - } - } - - Column { - anchors.left: preview.right - anchors.leftMargin: Appearance.spacing.normal - anchors.verticalCenter: parent.verticalCenter - - width: parent.width - preview.width - spacing: 0 - - StyledText { - id: name - - text: root.modelData?.name ?? "" - font.pointSize: Appearance.font.size.normal - } - - StyledText { - id: comment - - text: root.modelData?.flavour ?? "" - font.pointSize: Appearance.font.size.small - color: Colours.palette.m3outline - - elide: Text.ElideRight - width: parent.width - Appearance.rounding.normal * 2 - } - } - } -} diff --git a/modules/launcher/Schemes.qml b/modules/launcher/Schemes.qml deleted file mode 100644 index 8494437..0000000 --- a/modules/launcher/Schemes.qml +++ /dev/null @@ -1,66 +0,0 @@ -pragma Singleton - -import qs.config -import qs.utils -import Quickshell -import Quickshell.Io -import QtQuick - -Searcher { - id: root - - function transformSearch(search: string): string { - return search.slice(`${Config.launcher.actionPrefix}scheme `.length); - } - - function selector(item: var): string { - return `${item.name} ${item.flavour}`; - } - - list: schemes.instances - useFuzzy: Config.launcher.useFuzzy.schemes - keys: ["name", "flavour"] - weights: [0.9, 0.1] - - Variants { - id: schemes - - Scheme {} - } - - Process { - id: getSchemes - - running: true - command: ["caelestia", "scheme", "list"] - stdout: StdioCollector { - onStreamFinished: { - const schemeData = JSON.parse(text); - const list = Object.entries(schemeData).map(([name, f]) => Object.entries(f).map(([flavour, colours]) => ({ - name, - flavour, - colours - }))); - - const flat = []; - for (const s of list) - for (const f of s) - flat.push(f); - - schemes.model = flat; - } - } - } - - component Scheme: QtObject { - required property var modelData - readonly property string name: modelData.name - readonly property string flavour: modelData.flavour - readonly property var colours: modelData.colours - - function onClicked(list: AppList): void { - list.visibilities.launcher = false; - Quickshell.execDetached(["caelestia", "scheme", "set", "-n", name, "-f", flavour]); - } - } -} diff --git a/modules/launcher/VariantItem.qml b/modules/launcher/VariantItem.qml deleted file mode 100644 index a44983f..0000000 --- a/modules/launcher/VariantItem.qml +++ /dev/null @@ -1,69 +0,0 @@ -import qs.widgets -import qs.services -import qs.config -import QtQuick - -Item { - id: root - - required property M3Variants.Variant modelData - required property var list - - implicitHeight: Config.launcher.sizes.itemHeight - - anchors.left: parent?.left - anchors.right: parent?.right - - StateLayer { - radius: Appearance.rounding.full - - function onClicked(): void { - root.modelData?.onClicked(root.list); - } - } - - Item { - anchors.fill: parent - anchors.leftMargin: Appearance.padding.larger - anchors.rightMargin: Appearance.padding.larger - anchors.margins: Appearance.padding.smaller - - MaterialIcon { - id: icon - - text: root.modelData?.icon ?? "" - font.pointSize: Appearance.font.size.extraLarge - - anchors.verticalCenter: parent.verticalCenter - } - - Item { - anchors.left: icon.right - anchors.leftMargin: Appearance.spacing.larger - anchors.verticalCenter: icon.verticalCenter - - implicitWidth: parent.width - icon.width - implicitHeight: name.implicitHeight + desc.implicitHeight - - StyledText { - id: name - - text: root.modelData?.name ?? "" - font.pointSize: Appearance.font.size.normal - } - - StyledText { - id: desc - - text: root.modelData?.description ?? "" - font.pointSize: Appearance.font.size.small - color: Colours.alpha(Colours.palette.m3outline, true) - - elide: Text.ElideRight - width: root.width - icon.width - Appearance.rounding.normal * 2 - - anchors.top: name.bottom - } - } - } -} diff --git a/modules/launcher/WallpaperItem.qml b/modules/launcher/WallpaperItem.qml deleted file mode 100644 index e3d84d4..0000000 --- a/modules/launcher/WallpaperItem.qml +++ /dev/null @@ -1,96 +0,0 @@ -import qs.widgets -import qs.services -import qs.config -import Quickshell -import Quickshell.Widgets -import QtQuick -import QtQuick.Effects - -StyledRect { - id: root - - required property Wallpapers.Wallpaper modelData - required property PersistentProperties visibilities - - scale: 0.5 - opacity: 0 - z: PathView.z ?? 0 - - Component.onCompleted: { - scale = Qt.binding(() => PathView.isCurrentItem ? 1 : PathView.onPath ? 0.8 : 0); - opacity = Qt.binding(() => PathView.onPath ? 1 : 0); - } - - implicitWidth: image.width + Appearance.padding.larger * 2 - implicitHeight: image.height + label.height + Appearance.spacing.small / 2 + Appearance.padding.large + Appearance.padding.normal - - StateLayer { - radius: Appearance.rounding.normal - - function onClicked(): void { - Wallpapers.setWallpaper(root.modelData.path); - root.visibilities.launcher = false; - } - } - - RectangularShadow { - opacity: root.PathView.isCurrentItem ? 0.7 : 0 - anchors.fill: image - radius: image.radius - color: Colours.palette.m3shadow - blur: 10 - spread: 3 - - Behavior on opacity { - Anim {} - } - } - - ClippingRectangle { - id: image - - anchors.horizontalCenter: parent.horizontalCenter - y: Appearance.padding.large - color: "transparent" - radius: Appearance.rounding.normal - - implicitWidth: Config.launcher.sizes.wallpaperWidth - implicitHeight: implicitWidth / 16 * 9 - - CachingImage { - path: root.modelData.path - smooth: !root.PathView.view.moving - - anchors.fill: parent - } - } - - StyledText { - id: label - - anchors.top: image.bottom - anchors.topMargin: Appearance.spacing.small / 2 - anchors.horizontalCenter: parent.horizontalCenter - - width: image.width - Appearance.padding.normal * 2 - horizontalAlignment: Text.AlignHCenter - elide: Text.ElideRight - renderType: Text.QtRendering - text: root.modelData.name - font.pointSize: Appearance.font.size.normal - } - - Behavior on scale { - Anim {} - } - - Behavior on opacity { - Anim {} - } - - component Anim: NumberAnimation { - duration: Appearance.anim.durations.normal - easing.type: Easing.BezierSpline - easing.bezierCurve: Appearance.anim.curves.standard - } -} diff --git a/modules/launcher/WallpaperList.qml b/modules/launcher/WallpaperList.qml index f59dd29..5979b69 100644 --- a/modules/launcher/WallpaperList.qml +++ b/modules/launcher/WallpaperList.qml @@ -1,4 +1,4 @@ -import qs.widgets +import "items" import qs.services import qs.config import Quickshell diff --git a/modules/launcher/items/ActionItem.qml b/modules/launcher/items/ActionItem.qml new file mode 100644 index 0000000..acacede --- /dev/null +++ b/modules/launcher/items/ActionItem.qml @@ -0,0 +1,70 @@ +import "../services" +import qs.widgets +import qs.services +import qs.config +import QtQuick + +Item { + id: root + + required property Actions.Action modelData + required property var list + + implicitHeight: Config.launcher.sizes.itemHeight + + anchors.left: parent?.left + anchors.right: parent?.right + + StateLayer { + radius: Appearance.rounding.full + + function onClicked(): void { + root.modelData?.onClicked(root.list); + } + } + + Item { + anchors.fill: parent + anchors.leftMargin: Appearance.padding.larger + anchors.rightMargin: Appearance.padding.larger + anchors.margins: Appearance.padding.smaller + + MaterialIcon { + id: icon + + text: root.modelData?.icon ?? "" + font.pointSize: Appearance.font.size.extraLarge + + anchors.verticalCenter: parent.verticalCenter + } + + Item { + anchors.left: icon.right + anchors.leftMargin: Appearance.spacing.normal + anchors.verticalCenter: icon.verticalCenter + + implicitWidth: parent.width - icon.width + implicitHeight: name.implicitHeight + desc.implicitHeight + + StyledText { + id: name + + text: root.modelData?.name ?? "" + font.pointSize: Appearance.font.size.normal + } + + StyledText { + id: desc + + text: root.modelData?.desc ?? "" + font.pointSize: Appearance.font.size.small + color: Colours.alpha(Colours.palette.m3outline, true) + + elide: Text.ElideRight + width: root.width - icon.width - Appearance.rounding.normal * 2 + + anchors.top: name.bottom + } + } + } +} diff --git a/modules/launcher/items/AppItem.qml b/modules/launcher/items/AppItem.qml new file mode 100644 index 0000000..6c77166 --- /dev/null +++ b/modules/launcher/items/AppItem.qml @@ -0,0 +1,73 @@ +import "../services" +import qs.widgets +import qs.services +import qs.config +import Quickshell +import Quickshell.Widgets +import QtQuick + +Item { + id: root + + required property DesktopEntry modelData + required property PersistentProperties visibilities + + implicitHeight: Config.launcher.sizes.itemHeight + + anchors.left: parent?.left + anchors.right: parent?.right + + StateLayer { + radius: Appearance.rounding.full + + function onClicked(): void { + Apps.launch(root.modelData); + root.visibilities.launcher = false; + } + } + + Item { + anchors.fill: parent + anchors.leftMargin: Appearance.padding.larger + anchors.rightMargin: Appearance.padding.larger + anchors.margins: Appearance.padding.smaller + + IconImage { + id: icon + + source: Quickshell.iconPath(root.modelData?.icon, "image-missing") + implicitSize: parent.height * 0.8 + + anchors.verticalCenter: parent.verticalCenter + } + + Item { + anchors.left: icon.right + anchors.leftMargin: Appearance.spacing.normal + anchors.verticalCenter: icon.verticalCenter + + implicitWidth: parent.width - icon.width + implicitHeight: name.implicitHeight + comment.implicitHeight + + StyledText { + id: name + + text: root.modelData?.name ?? "" + font.pointSize: Appearance.font.size.normal + } + + StyledText { + id: comment + + text: (root.modelData?.comment || root.modelData?.genericName || root.modelData?.name) ?? "" + font.pointSize: Appearance.font.size.small + color: Colours.alpha(Colours.palette.m3outline, true) + + elide: Text.ElideRight + width: root.width - icon.width - Appearance.rounding.normal * 2 + + anchors.top: name.bottom + } + } + } +} diff --git a/modules/launcher/items/CalcItem.qml b/modules/launcher/items/CalcItem.qml new file mode 100644 index 0000000..2e3c901 --- /dev/null +++ b/modules/launcher/items/CalcItem.qml @@ -0,0 +1,162 @@ +import qs.widgets +import qs.services +import qs.config +import Quickshell +import Quickshell.Io +import QtQuick +import QtQuick.Layouts + +Item { + id: root + + required property var list + readonly property string math: list.search.text.slice(`${Config.launcher.actionPrefix}calc `.length) + + function onClicked(): void { + Quickshell.execDetached(["sh", "-c", `qalc -t -m 100 '${root.math}' | wl-copy`]); + root.list.visibilities.launcher = false; + } + + implicitHeight: Config.launcher.sizes.itemHeight + + anchors.left: parent?.left + anchors.right: parent?.right + + onMathChanged: { + if (math) { + qalcProc.command = ["qalc", "-m", "100", math]; + qalcProc.running = true; + } + } + + StateLayer { + radius: Appearance.rounding.full + + function onClicked(): void { + root.onClicked(); + } + } + + Binding { + id: binding + + when: root.math.length > 0 + target: metrics + property: "text" + } + + Process { + id: qalcProc + + stdout: StdioCollector { + onStreamFinished: binding.value = text.trim() + } + } + + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.margins: Appearance.padding.larger + + spacing: Appearance.spacing.normal + + MaterialIcon { + text: "function" + font.pointSize: Appearance.font.size.extraLarge + Layout.alignment: Qt.AlignVCenter + } + + StyledText { + id: result + + color: { + if (metrics.text.includes("error: ")) + return Colours.palette.m3error; + if (!root.math) + return Colours.palette.m3onSurfaceVariant; + return Colours.palette.m3onSurface; + } + + text: metrics.elidedText + font.pointSize: Appearance.font.size.normal + + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + + TextMetrics { + id: metrics + + text: qsTr("Type an expression to calculate") + font.family: result.font.family + font.pointSize: result.font.pointSize + elide: Text.ElideRight + elideWidth: result.width + } + } + + StyledRect { + color: Colours.palette.m3tertiary + radius: Appearance.rounding.normal + clip: true + + implicitWidth: (stateLayer.containsMouse ? label.implicitWidth + label.anchors.rightMargin : 0) + icon.implicitWidth + Appearance.padding.normal * 2 + implicitHeight: Math.max(label.implicitHeight, icon.implicitHeight) + Appearance.padding.small * 2 + + Layout.alignment: Qt.AlignVCenter + + StateLayer { + id: stateLayer + + color: Colours.palette.m3onTertiary + + function onClicked(): void { + Quickshell.execDetached(["app2unit", "--", "foot", "fish", "-C", `exec qalc -i '${root.math}'`]); + root.list.visibilities.launcher = false; + } + } + + StyledText { + id: label + + anchors.verticalCenter: parent.verticalCenter + anchors.right: icon.left + anchors.rightMargin: Appearance.spacing.small + + text: qsTr("Open in calculator") + color: Colours.palette.m3onTertiary + font.pointSize: Appearance.font.size.normal + + opacity: stateLayer.containsMouse ? 1 : 0 + + Behavior on opacity { + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } + } + + MaterialIcon { + id: icon + + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: Appearance.padding.normal + + text: "open_in_new" + color: Colours.palette.m3onTertiary + font.pointSize: Appearance.font.size.large + } + + Behavior on implicitWidth { + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } + } + } +} diff --git a/modules/launcher/items/SchemeItem.qml b/modules/launcher/items/SchemeItem.qml new file mode 100644 index 0000000..94c1818 --- /dev/null +++ b/modules/launcher/items/SchemeItem.qml @@ -0,0 +1,92 @@ +import "../services" +import qs.widgets +import qs.services +import qs.config +import QtQuick + +Item { + id: root + + required property Schemes.Scheme modelData + required property var list + + implicitHeight: Config.launcher.sizes.itemHeight + + anchors.left: parent?.left + anchors.right: parent?.right + + StateLayer { + radius: Appearance.rounding.full + + function onClicked(): void { + root.modelData?.onClicked(root.list); + } + } + + Item { + anchors.fill: parent + anchors.leftMargin: Appearance.padding.larger + anchors.rightMargin: Appearance.padding.larger + anchors.margins: Appearance.padding.smaller + + StyledRect { + id: preview + + anchors.verticalCenter: parent.verticalCenter + + border.width: 1 + border.color: Qt.alpha(`#${root.modelData?.colours?.outline}`, 0.5) + + color: `#${root.modelData?.colours?.surface}` + radius: Appearance.rounding.full + implicitWidth: parent.height * 0.8 + implicitHeight: parent.height * 0.8 + + Item { + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + + implicitWidth: parent.implicitWidth / 2 + clip: true + + StyledRect { + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + + implicitWidth: preview.implicitWidth + color: `#${root.modelData?.colours?.primary}` + radius: Appearance.rounding.full + } + } + } + + Column { + anchors.left: preview.right + anchors.leftMargin: Appearance.spacing.normal + anchors.verticalCenter: parent.verticalCenter + + width: parent.width - preview.width + spacing: 0 + + StyledText { + id: name + + text: root.modelData?.name ?? "" + font.pointSize: Appearance.font.size.normal + } + + StyledText { + id: comment + + text: root.modelData?.flavour ?? "" + font.pointSize: Appearance.font.size.small + color: Colours.palette.m3outline + + elide: Text.ElideRight + width: parent.width - Appearance.rounding.normal * 2 + } + } + } +} diff --git a/modules/launcher/items/VariantItem.qml b/modules/launcher/items/VariantItem.qml new file mode 100644 index 0000000..973564a --- /dev/null +++ b/modules/launcher/items/VariantItem.qml @@ -0,0 +1,70 @@ +import "../services" +import qs.widgets +import qs.services +import qs.config +import QtQuick + +Item { + id: root + + required property M3Variants.Variant modelData + required property var list + + implicitHeight: Config.launcher.sizes.itemHeight + + anchors.left: parent?.left + anchors.right: parent?.right + + StateLayer { + radius: Appearance.rounding.full + + function onClicked(): void { + root.modelData?.onClicked(root.list); + } + } + + Item { + anchors.fill: parent + anchors.leftMargin: Appearance.padding.larger + anchors.rightMargin: Appearance.padding.larger + anchors.margins: Appearance.padding.smaller + + MaterialIcon { + id: icon + + text: root.modelData?.icon ?? "" + font.pointSize: Appearance.font.size.extraLarge + + anchors.verticalCenter: parent.verticalCenter + } + + Item { + anchors.left: icon.right + anchors.leftMargin: Appearance.spacing.larger + anchors.verticalCenter: icon.verticalCenter + + implicitWidth: parent.width - icon.width + implicitHeight: name.implicitHeight + desc.implicitHeight + + StyledText { + id: name + + text: root.modelData?.name ?? "" + font.pointSize: Appearance.font.size.normal + } + + StyledText { + id: desc + + text: root.modelData?.description ?? "" + font.pointSize: Appearance.font.size.small + color: Colours.alpha(Colours.palette.m3outline, true) + + elide: Text.ElideRight + width: root.width - icon.width - Appearance.rounding.normal * 2 + + anchors.top: name.bottom + } + } + } +} diff --git a/modules/launcher/items/WallpaperItem.qml b/modules/launcher/items/WallpaperItem.qml new file mode 100644 index 0000000..e3d84d4 --- /dev/null +++ b/modules/launcher/items/WallpaperItem.qml @@ -0,0 +1,96 @@ +import qs.widgets +import qs.services +import qs.config +import Quickshell +import Quickshell.Widgets +import QtQuick +import QtQuick.Effects + +StyledRect { + id: root + + required property Wallpapers.Wallpaper modelData + required property PersistentProperties visibilities + + scale: 0.5 + opacity: 0 + z: PathView.z ?? 0 + + Component.onCompleted: { + scale = Qt.binding(() => PathView.isCurrentItem ? 1 : PathView.onPath ? 0.8 : 0); + opacity = Qt.binding(() => PathView.onPath ? 1 : 0); + } + + implicitWidth: image.width + Appearance.padding.larger * 2 + implicitHeight: image.height + label.height + Appearance.spacing.small / 2 + Appearance.padding.large + Appearance.padding.normal + + StateLayer { + radius: Appearance.rounding.normal + + function onClicked(): void { + Wallpapers.setWallpaper(root.modelData.path); + root.visibilities.launcher = false; + } + } + + RectangularShadow { + opacity: root.PathView.isCurrentItem ? 0.7 : 0 + anchors.fill: image + radius: image.radius + color: Colours.palette.m3shadow + blur: 10 + spread: 3 + + Behavior on opacity { + Anim {} + } + } + + ClippingRectangle { + id: image + + anchors.horizontalCenter: parent.horizontalCenter + y: Appearance.padding.large + color: "transparent" + radius: Appearance.rounding.normal + + implicitWidth: Config.launcher.sizes.wallpaperWidth + implicitHeight: implicitWidth / 16 * 9 + + CachingImage { + path: root.modelData.path + smooth: !root.PathView.view.moving + + anchors.fill: parent + } + } + + StyledText { + id: label + + anchors.top: image.bottom + anchors.topMargin: Appearance.spacing.small / 2 + anchors.horizontalCenter: parent.horizontalCenter + + width: image.width - Appearance.padding.normal * 2 + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideRight + renderType: Text.QtRendering + text: root.modelData.name + font.pointSize: Appearance.font.size.normal + } + + Behavior on scale { + Anim {} + } + + Behavior on opacity { + Anim {} + } + + component Anim: NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } +} diff --git a/modules/launcher/services/Actions.qml b/modules/launcher/services/Actions.qml new file mode 100644 index 0000000..be1fc72 --- /dev/null +++ b/modules/launcher/services/Actions.qml @@ -0,0 +1,155 @@ +pragma Singleton + +import ".." +import qs.services +import qs.config +import qs.utils +import Quickshell +import QtQuick + +Searcher { + id: root + + readonly property list actions: [ + Action { + name: qsTr("Calculator") + desc: qsTr("Do simple math equations (powered by Qalc)") + icon: "calculate" + + function onClicked(list: AppList): void { + root.autocomplete(list, "calc"); + } + }, + Action { + name: qsTr("Scheme") + desc: qsTr("Change the current colour scheme") + icon: "palette" + + function onClicked(list: AppList): void { + root.autocomplete(list, "scheme"); + } + }, + Action { + name: qsTr("Wallpaper") + desc: qsTr("Change the current wallpaper") + icon: "image" + + function onClicked(list: AppList): void { + root.autocomplete(list, "wallpaper"); + } + }, + Action { + name: qsTr("Variant") + desc: qsTr("Change the current scheme variant") + icon: "colors" + + function onClicked(list: AppList): void { + root.autocomplete(list, "variant"); + } + }, + Action { + name: qsTr("Transparency") + desc: qsTr("Change shell transparency") + icon: "opacity" + disabled: true + + function onClicked(list: AppList): void { + root.autocomplete(list, "transparency"); + } + }, + Action { + name: qsTr("Light") + desc: qsTr("Change the scheme to light mode") + icon: "light_mode" + + function onClicked(list: AppList): void { + list.visibilities.launcher = false; + Colours.setMode("light"); + } + }, + Action { + name: qsTr("Dark") + desc: qsTr("Change the scheme to dark mode") + icon: "dark_mode" + + function onClicked(list: AppList): void { + list.visibilities.launcher = false; + Colours.setMode("dark"); + } + }, + Action { + name: qsTr("Shutdown") + desc: qsTr("Shutdown the system") + icon: "power_settings_new" + disabled: !Config.launcher.enableDangerousActions + + function onClicked(list: AppList): void { + list.visibilities.launcher = false; + Quickshell.execDetached(["systemctl", "poweroff"]); + } + }, + Action { + name: qsTr("Reboot") + desc: qsTr("Reboot the system") + icon: "cached" + disabled: !Config.launcher.enableDangerousActions + + function onClicked(list: AppList): void { + list.visibilities.launcher = false; + Quickshell.execDetached(["systemctl", "reboot"]); + } + }, + Action { + name: qsTr("Logout") + desc: qsTr("Log out of the current session") + icon: "exit_to_app" + disabled: !Config.launcher.enableDangerousActions + + function onClicked(list: AppList): void { + list.visibilities.launcher = false; + Quickshell.execDetached(["loginctl", "terminate-user", ""]); + } + }, + Action { + name: qsTr("Lock") + desc: qsTr("Lock the current session") + icon: "lock" + + function onClicked(list: AppList): void { + list.visibilities.launcher = false; + Quickshell.execDetached(["loginctl", "lock-session"]); + } + }, + Action { + name: qsTr("Sleep") + desc: qsTr("Suspend then hibernate") + icon: "bedtime" + + function onClicked(list: AppList): void { + list.visibilities.launcher = false; + Quickshell.execDetached(["systemctl", "suspend-then-hibernate"]); + } + } + ] + + function transformSearch(search: string): string { + return search.slice(Config.launcher.actionPrefix.length); + } + + function autocomplete(list: AppList, text: string): void { + list.search.text = `${Config.launcher.actionPrefix}${text} `; + } + + list: actions.filter(a => !a.disabled) + useFuzzy: Config.launcher.useFuzzy.actions + + component Action: QtObject { + required property string name + required property string desc + required property string icon + property bool disabled + + function onClicked(list: AppList): void { + } + } +} diff --git a/modules/launcher/services/Apps.qml b/modules/launcher/services/Apps.qml new file mode 100644 index 0000000..d561d15 --- /dev/null +++ b/modules/launcher/services/Apps.qml @@ -0,0 +1,25 @@ +pragma Singleton + +import qs.config +import qs.utils +import Quickshell + +Searcher { + id: root + + list: DesktopEntries.applications.values.filter(a => !a.noDisplay).sort((a, b) => a.name.localeCompare(b.name)) + useFuzzy: Config.launcher.useFuzzy.apps + + function launch(entry: DesktopEntry): void { + if (entry.runInTerminal) + Quickshell.execDetached({ + command: ["app2unit", "--", "foot", `${Quickshell.configDir}/assets/wrap_term_launch.sh`, ...entry.command], + workingDirectory: entry.workingDirectory + }); + else + Quickshell.execDetached({ + command: ["app2unit", "--", ...entry.command], + workingDirectory: entry.workingDirectory + }); + } +} diff --git a/modules/launcher/services/M3Variants.qml b/modules/launcher/services/M3Variants.qml new file mode 100644 index 0000000..69bd805 --- /dev/null +++ b/modules/launcher/services/M3Variants.qml @@ -0,0 +1,84 @@ +pragma Singleton + +import qs.config +import qs.utils +import Quickshell +import QtQuick + +Searcher { + id: root + + function transformSearch(search: string): string { + return search.slice(`${Config.launcher.actionPrefix}variant `.length); + } + + list: [ + Variant { + variant: "vibrant" + icon: "sentiment_very_dissatisfied" + name: "Vibrant" + description: "A high chroma palette. The primary palette's chroma is at maximum." + }, + Variant { + variant: "tonalspot" + icon: "android" + name: "Tonal Spot" + description: "Default for Material theme colours. A pastel palette with a low chroma." + }, + Variant { + variant: "expressive" + icon: "compare_arrows" + name: "Expressive" + description: "A medium chroma palette. The primary palette's hue is different from the seed colour, for variety." + }, + Variant { + variant: "fidelity" + icon: "compare" + name: "Fidelity" + description: "Matches the seed colour, even if the seed colour is very bright (high chroma)." + }, + Variant { + variant: "content" + icon: "sentiment_calm" + name: "Content" + description: "Almost identical to fidelity." + }, + Variant { + variant: "fruitsalad" + icon: "nutrition" + name: "Fruit Salad" + description: "A playful theme - the seed colour's hue does not appear in the theme." + }, + Variant { + variant: "rainbow" + icon: "looks" + name: "Rainbow" + description: "A playful theme - the seed colour's hue does not appear in the theme." + }, + Variant { + variant: "neutral" + icon: "contrast" + name: "Neutral" + description: "Close to grayscale, a hint of chroma." + }, + Variant { + variant: "monochrome" + icon: "filter_b_and_w" + name: "Monochrome" + description: "All colours are grayscale, no chroma." + } + ] + useFuzzy: Config.launcher.useFuzzy.variants + + component Variant: QtObject { + required property string variant + required property string icon + required property string name + required property string description + + function onClicked(list: AppList): void { + list.visibilities.launcher = false; + Quickshell.execDetached(["caelestia", "scheme", "set", "-v", variant]); + } + } +} diff --git a/modules/launcher/services/Schemes.qml b/modules/launcher/services/Schemes.qml new file mode 100644 index 0000000..8494437 --- /dev/null +++ b/modules/launcher/services/Schemes.qml @@ -0,0 +1,66 @@ +pragma Singleton + +import qs.config +import qs.utils +import Quickshell +import Quickshell.Io +import QtQuick + +Searcher { + id: root + + function transformSearch(search: string): string { + return search.slice(`${Config.launcher.actionPrefix}scheme `.length); + } + + function selector(item: var): string { + return `${item.name} ${item.flavour}`; + } + + list: schemes.instances + useFuzzy: Config.launcher.useFuzzy.schemes + keys: ["name", "flavour"] + weights: [0.9, 0.1] + + Variants { + id: schemes + + Scheme {} + } + + Process { + id: getSchemes + + running: true + command: ["caelestia", "scheme", "list"] + stdout: StdioCollector { + onStreamFinished: { + const schemeData = JSON.parse(text); + const list = Object.entries(schemeData).map(([name, f]) => Object.entries(f).map(([flavour, colours]) => ({ + name, + flavour, + colours + }))); + + const flat = []; + for (const s of list) + for (const f of s) + flat.push(f); + + schemes.model = flat; + } + } + } + + component Scheme: QtObject { + required property var modelData + readonly property string name: modelData.name + readonly property string flavour: modelData.flavour + readonly property var colours: modelData.colours + + function onClicked(list: AppList): void { + list.visibilities.launcher = false; + Quickshell.execDetached(["caelestia", "scheme", "set", "-n", name, "-f", flavour]); + } + } +} diff --git a/services/Apps.qml b/services/Apps.qml deleted file mode 100644 index d561d15..0000000 --- a/services/Apps.qml +++ /dev/null @@ -1,25 +0,0 @@ -pragma Singleton - -import qs.config -import qs.utils -import Quickshell - -Searcher { - id: root - - list: DesktopEntries.applications.values.filter(a => !a.noDisplay).sort((a, b) => a.name.localeCompare(b.name)) - useFuzzy: Config.launcher.useFuzzy.apps - - function launch(entry: DesktopEntry): void { - if (entry.runInTerminal) - Quickshell.execDetached({ - command: ["app2unit", "--", "foot", `${Quickshell.configDir}/assets/wrap_term_launch.sh`, ...entry.command], - workingDirectory: entry.workingDirectory - }); - else - Quickshell.execDetached({ - command: ["app2unit", "--", ...entry.command], - workingDirectory: entry.workingDirectory - }); - } -} -- cgit v1.2.3-freya