From 9065d693ef928abe46659aec1626c47ad1e9aaff Mon Sep 17 00:00:00 2001 From: Zacharias-Brohn Date: Mon, 2 Mar 2026 14:42:03 +0100 Subject: [PATCH] stuff --- Config/Config.qml | 17 +++++- Config/DockConfig.qml | 10 ++++ Helpers/DockApps.qml | 70 ++++++++++++++++++++++ Modules/Dashboard/Background.qml | 1 - Modules/Dock/Background.qml | 66 ++++++++++++++++++++ Modules/Dock/Content.qml | 28 +++++++++ Modules/Dock/Wrapper.qml | 100 +++++++++++++++++++++++++++++++ Modules/Launcher/Wrapper.qml | 6 +- 8 files changed, 294 insertions(+), 4 deletions(-) create mode 100644 Config/DockConfig.qml create mode 100644 Helpers/DockApps.qml create mode 100644 Modules/Dock/Background.qml create mode 100644 Modules/Dock/Content.qml create mode 100644 Modules/Dock/Wrapper.qml diff --git a/Config/Config.qml b/Config/Config.qml index a995ca9..9455d7d 100644 --- a/Config/Config.qml +++ b/Config/Config.qml @@ -15,6 +15,7 @@ Singleton { property alias barConfig: adapter.barConfig property alias colors: adapter.colors property alias dashboard: adapter.dashboard + property alias dock: adapter.dock property alias general: adapter.general property alias launcher: adapter.launcher property alias lock: adapter.lock @@ -113,7 +114,8 @@ Singleton { osd: serializeOsd(), background: serializeBackground(), launcher: serializeLauncher(), - colors: serializeColors() + colors: serializeColors(), + dock: serializeDock() }; } @@ -149,6 +151,17 @@ Singleton { }; } + function serializeDock(): var { + return { + enable: dock.enable, + height: dock.height, + hoverRegionHeight: dock.hoverRegionHeight, + hoverToReveal: dock.hoverToReveal, + pinnedApps: dock.pinnedApps, + pinnedOnStartup: dock.pinnedOnStartup + }; + } + function serializeGeneral(): var { return { logo: general.logo, @@ -381,6 +394,8 @@ Singleton { } property DashboardConfig dashboard: DashboardConfig { } + property DockConfig dock: DockConfig { + } property General general: General { } property Launcher launcher: Launcher { diff --git a/Config/DockConfig.qml b/Config/DockConfig.qml new file mode 100644 index 0000000..135a3e0 --- /dev/null +++ b/Config/DockConfig.qml @@ -0,0 +1,10 @@ +import Quickshell.Io + +JsonObject { + property bool enable: false + property real height: 60 + property real hoverRegionHeight: 2 + property bool hoverToReveal: true + property list pinnedApps: ["org.kde.dolphin", "kitty",] + property bool pinnedOnStartup: false +} diff --git a/Helpers/DockApps.qml b/Helpers/DockApps.qml new file mode 100644 index 0000000..1bdf96a --- /dev/null +++ b/Helpers/DockApps.qml @@ -0,0 +1,70 @@ +pragma Singleton + +import QtQuick +import Quickshell +import Quickshell.Wayland +import qs.Components +import qs.Config + +Singleton { + id: root + + property list apps: { + var map = new Map(); + + const pinnedApps = Config.dock?.pinnedApps ?? []; + for (const appId of pinnedApps) { + if (!map.has(appId.toLowerCase())) + map.set(appId.toLowerCase(), ({ + pinned: true, + toplevels: [] + })); + } + + if (pinnedApps.length > 0) { + map.set("SEPARATOR", { + pinned: false, + toplevels: [] + }); + } + + var values = []; + + for (const [key, value] of map) { + values.push(appEntryComp.createObject(null, { + appId: key, + toplevels: value.toplevels, + pinned: value.pinned + })); + } + + return values; + } + + function isPinned(appId) { + return Config.dock.pinnedApps.indexOf(appId) !== -1; + } + + function togglePin(appId) { + if (root.isPinned(appId)) { + Config.dock.pinnedApps = Config.dock.pinnedApps.filter(id => id !== appId); + } else { + Config.dock.pinnedApps = Config.dock.pinnedApps.concat([appId]); + } + } + + Component { + id: appEntryComp + + TaskbarAppEntry { + } + } + + component TaskbarAppEntry: QtObject { + id: wrapper + + required property string appId + required property bool pinned + required property list toplevels + } +} diff --git a/Modules/Dashboard/Background.qml b/Modules/Dashboard/Background.qml index f192a11..b97793b 100644 --- a/Modules/Dashboard/Background.qml +++ b/Modules/Dashboard/Background.qml @@ -45,7 +45,6 @@ ShapePath { } PathArc { - direction: PathArc.Counterclockwise radiusX: root.rounding radiusY: Math.min(root.rounding, root.wrapper.height) relativeX: root.rounding diff --git a/Modules/Dock/Background.qml b/Modules/Dock/Background.qml new file mode 100644 index 0000000..37f8c08 --- /dev/null +++ b/Modules/Dock/Background.qml @@ -0,0 +1,66 @@ +import QtQuick +import QtQuick.Shapes +import qs.Components +import qs.Config + +ShapePath { + id: root + + readonly property bool flatten: wrapper.height < rounding * 2 + readonly property real rounding: Appearance.rounding.normal + readonly property real roundingY: flatten ? wrapper.height / 2 : rounding + required property Wrapper wrapper + + fillColor: DynamicColors.palette.m3surface + strokeWidth: -1 + + Behavior on fillColor { + CAnim { + } + } + + PathArc { + direction: PathArc.Counterclockwise + radiusX: root.rounding + radiusY: Math.min(root.rounding, root.wrapper.height) + relativeX: root.rounding + relativeY: -root.roundingY + } + + PathLine { + relativeX: 0 + relativeY: -(root.wrapper.height - root.roundingY * 2) + } + + PathArc { + radiusX: root.rounding + radiusY: Math.min(root.rounding, root.wrapper.height) + relativeX: root.rounding + relativeY: -root.roundingY + } + + PathLine { + relativeX: root.wrapper.width - root.rounding * 2 + relativeY: 0 + } + + PathArc { + radiusX: root.rounding + radiusY: Math.min(root.rounding, root.wrapper.height) + relativeX: root.rounding + relativeY: root.roundingY + } + + PathLine { + relativeX: 0 + relativeY: root.wrapper.height - root.roundingY * 2 + } + + PathArc { + direction: PathArc.Counterclockwise + radiusX: root.rounding + radiusY: Math.min(root.rounding, root.wrapper.height) + relativeX: root.rounding + relativeY: root.roundingY + } +} diff --git a/Modules/Dock/Content.qml b/Modules/Dock/Content.qml new file mode 100644 index 0000000..6089700 --- /dev/null +++ b/Modules/Dock/Content.qml @@ -0,0 +1,28 @@ +pragma ComponentBehavior: Bound + +import Quickshell +import QtQuick +import qs.Components +import qs.Helpers +import qs.Config + +Item { + id: root + + readonly property int padding: Appearance.padding.small + required property var panels + readonly property int rounding: Appearance.rounding.large + required property PersistentProperties visibilities + + implicitHeight: Config.dock.height + root.padding * 2 + implicitWidth: dockRow.implicitWidth + root.padding * 2 + + RowLayout { + id: dockRow + + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + spacing: Appearance.spacing.small + } +} diff --git a/Modules/Dock/Wrapper.qml b/Modules/Dock/Wrapper.qml new file mode 100644 index 0000000..5d7e36d --- /dev/null +++ b/Modules/Dock/Wrapper.qml @@ -0,0 +1,100 @@ +pragma ComponentBehavior: Bound + +import Quickshell +import QtQuick +import qs.Components +import qs.Config + +Item { + id: root + + property int contentHeight + required property var panels + required property ShellScreen screen + readonly property bool shouldBeActive: visibilities.dock + required property PersistentProperties visibilities + + implicitHeight: 0 + implicitWidth: content.implicitWidth + visible: height > 0 + + onShouldBeActiveChanged: { + if (shouldBeActive) { + timer.stop(); + hideAnim.stop(); + showAnim.start(); + } else { + showAnim.stop(); + hideAnim.start(); + } + } + + SequentialAnimation { + id: showAnim + + Anim { + duration: Appearance.anim.durations.small + easing.bezierCurve: Appearance.anim.curves.expressiveEffects + property: "implicitHeight" + target: root + to: root.contentHeight + } + + ScriptAction { + script: root.implicitHeight = Qt.binding(() => content.implicitHeight) + } + } + + SequentialAnimation { + id: hideAnim + + ScriptAction { + script: root.implicitHeight = root.implicitHeight + } + + Anim { + easing.bezierCurve: Appearance.anim.curves.expressiveEffects + property: "implicitHeight" + target: root + to: 0 + } + } + + Timer { + id: timer + + interval: Appearance.anim.durations.small + + onRunningChanged: { + if (running && !root.shouldBeActive) { + content.visible = false; + content.active = true; + } else { + content.active = Qt.binding(() => root.shouldBeActive || root.visible); + content.visible = true; + if (showAnim.running) { + showAnim.stop(); + showAnim.start(); + } + } + } + } + + Loader { + id: content + + active: false + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + visible: false + + sourceComponent: Content { + panels: root.panels + visibilities: root.visibilities + + Component.onCompleted: root.contentHeight = implicitHeight + } + + Component.onCompleted: timer.start() + } +} diff --git a/Modules/Launcher/Wrapper.qml b/Modules/Launcher/Wrapper.qml index d06afd4..4c5b6e5 100644 --- a/Modules/Launcher/Wrapper.qml +++ b/Modules/Launcher/Wrapper.qml @@ -10,8 +10,10 @@ Item { property int contentHeight readonly property real maxHeight: { - let max = screen.height - Appearance.spacing.large; - if (visibilities.dashboard) + let max = screen.height - Appearance.spacing.large * 2; + if (visibilities.resources) + max -= panels.resources.nonAnimHeight; + if (visibilities.dashboard && panels.dashboard.x < root.x + root.implicitWidth) max -= panels.dashboard.nonAnimHeight; return max; }