From 24392e379161295e037456ba221eda6453728a7c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 3 Feb 2026 22:43:09 +0100 Subject: [PATCH] hefty: bar: allow vertical --- .../quickshell/ii/modules/common/Config.qml | 19 +- .../ii/modules/common/config/HeftyConfig.qml | 2 +- .../modules/hefty/topLayer/HTopLayerPanel.qml | 2 +- .../ii/modules/hefty/topLayer/bar/HBar.qml | 211 +++++++++++++----- .../hefty/topLayer/bar/HBarContent.qml | 12 +- .../hefty/topLayer/bar/widgets/Workspaces.qml | 7 +- .../ii/modules/ii/bar/Workspaces.qml | 8 +- 7 files changed, 177 insertions(+), 84 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index 313a64280..659c3eb22 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -15,6 +15,8 @@ Singleton { property int readWriteDelay: 50 // milliseconds property bool blockWrites: false + signal reloaded() + function setNestedValue(nestedKey, value) { let keys = nestedKey.split("."); let obj = root.options; @@ -70,7 +72,10 @@ Singleton { blockWrites: root.blockWrites onFileChanged: fileReloadTimer.restart() onAdapterUpdated: fileWriteTimer.restart() - onLoaded: root.ready = true + onLoaded: { + if (!root.ready) root.reloaded() + root.ready = true + } onLoadFailed: error => { if (error == FileViewError.FileNotFound) { writeAdapter(); @@ -92,16 +97,12 @@ Singleton { property string tool: "functions" // search, functions, or none property list extraModels: [ { - "api_format": "openai" // Most of the time you want "openai". Use "gemini" for Google's models - , + "api_format": "openai", // Most of the time you want "openai". Use "gemini" for Google's models "description": "This is a custom model. Edit the config to add more! | Anyway, this is DeepSeek R1 Distill LLaMA 70B", "endpoint": "https://openrouter.ai/api/v1/chat/completions", - "homepage": "https://openrouter.ai/deepseek/deepseek-r1-distill-llama-70b:free" // Not mandatory - , - "icon": "spark-symbolic" // Not mandatory - , - "key_get_link": "https://openrouter.ai/settings/keys" // Not mandatory - , + "homepage": "https://openrouter.ai/deepseek/deepseek-r1-distill-llama-70b:free", // Not mandatory + "icon": "spark-symbolic", // Not mandatory + "key_get_link": "https://openrouter.ai/settings/keys", // Not mandatory "key_id": "openrouter", "model": "deepseek/deepseek-r1-distill-llama-70b:free", "name": "Custom: DS R1 Dstl. LLaMA 70B", diff --git a/dots/.config/quickshell/ii/modules/common/config/HeftyConfig.qml b/dots/.config/quickshell/ii/modules/common/config/HeftyConfig.qml index 98091e50f..7d765c1b2 100644 --- a/dots/.config/quickshell/ii/modules/common/config/HeftyConfig.qml +++ b/dots/.config/quickshell/ii/modules/common/config/HeftyConfig.qml @@ -5,7 +5,7 @@ import Quickshell.Io JsonObject { property JsonObject bar: JsonObject { property list leftWidgets: [] - property list centerWidgets: [] + property list centerWidgets: [["Workspaces"]] property list rightWidgets: [] property bool m3ExpressiveGrouping: true } diff --git a/dots/.config/quickshell/ii/modules/hefty/topLayer/HTopLayerPanel.qml b/dots/.config/quickshell/ii/modules/hefty/topLayer/HTopLayerPanel.qml index a96129f7f..0a6e829f8 100644 --- a/dots/.config/quickshell/ii/modules/hefty/topLayer/HTopLayerPanel.qml +++ b/dots/.config/quickshell/ii/modules/hefty/topLayer/HTopLayerPanel.qml @@ -108,7 +108,7 @@ PanelWindow { HBar { id: bar - load: root.currentPanel === this + load: root.currentPanel === this && root.finishedMorphing // the extra condition is to prevent workspace widget from acting up when switching horizontal/vertical... should be fixed later shown: root.finishedMorphing } diff --git a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBar.qml b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBar.qml index 8da64c902..95eade0fe 100644 --- a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBar.qml +++ b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBar.qml @@ -10,8 +10,14 @@ import ".." HAbstractMorphedPanel { id: root + // Config + property bool vertical: Config.options.bar.vertical + property bool atBottom: Config.options.bar.bottom + property int cornerStyle: Config.options.bar.cornerStyle + // Own props property int barHeight: Appearance.sizes.baseBarHeight + property int barVerticalWidth: Appearance.sizes.baseVerticalBarWidth function getRounding(cornerStyle) { switch(cornerStyle) { case 0: return Appearance.rounding.screenRounding; @@ -39,94 +45,174 @@ HAbstractMorphedPanel { function getHug(cornerStyle) { return cornerStyle === 0; } - property int reservedArea: barHeight + getEdgeGap(Config.options.bar.cornerStyle) + property int reservedArea: (vertical ? barVerticalWidth : barHeight) + getEdgeGap(cornerStyle) // Some info - reservedTop: Config.options.bar.bottom ? 0 : reservedArea - reservedBottom: Config.options.bar.bottom ? reservedArea : 0 + reservedTop: (!atBottom && !vertical) ? reservedArea : 0 + reservedBottom: (atBottom && !vertical) ? reservedArea : 0 + reservedLeft: (!atBottom && vertical) ? reservedArea : 0 + reservedRight: (atBottom && vertical) ? reservedArea : 0 // Background - backgroundPolygon: { + function getBackgroundPolygon() { + print("Generating background polygon for HBar") // It's certainly cleaner to have the below props declared outside, but we do this // to make sure a config change only makes this re-evaluate exactly once - const bottom = Config.options.bar.bottom - const cornerStyle = Config.options.bar.cornerStyle - const rounding = root.getRounding(cornerStyle) + const bottom = root.atBottom + const vertical = root.vertical + const cornerStyle = root.cornerStyle + const hug = root.getHug(cornerStyle) const edgeGap = root.getEdgeGap(cornerStyle) const edgeRounding = root.getEdgeRounding(cornerStyle) - const hug = root.getHug(cornerStyle) - const xLeft = edgeGap - const xRight = root.screenWidth - edgeGap - const yTop = bottom ? (root.screenHeight - edgeGap - barHeight) : edgeGap - const yBottom = bottom ? (root.screenHeight - edgeGap) : (edgeGap + barHeight) - const topRounding = bottom ? rounding : edgeRounding - const bottomRounding = bottom ? edgeRounding : rounding - var topCornerDirection, bottomCornerDirection; - if (cornerStyle === 2) { // Rect - topCornerDirection = 0; - bottomCornerDirection = 0; - } else if (cornerStyle === 1) { // Rect - topCornerDirection = 1; - bottomCornerDirection = -1; + const rounding = root.getRounding(cornerStyle) + + const areaHeight = vertical ? root.screenHeight : (root.barHeight + edgeGap * 2) + const areaWidth = vertical ? (root.barVerticalWidth + edgeGap * 2) : root.screenWidth + const height = vertical ? (root.screenHeight - edgeGap * 2) : root.barHeight + const width = vertical ? root.barVerticalWidth : (root.screenWidth - edgeGap * 2) + + const xLeft = (vertical && bottom) ? (root.screenWidth - edgeGap - width) : edgeGap + const xRight = (vertical && !bottom) ? (areaWidth - edgeGap) : (root.screenWidth - edgeGap) + const yTop = (!vertical && bottom) ? (root.screenHeight - edgeGap - height) : edgeGap + const yBottom = (!vertical && !bottom) ? (areaHeight - edgeGap) : (root.screenHeight - edgeGap) + + const topLeftRounding = !bottom ? edgeRounding : rounding + const topRightRounding = !(bottom^vertical) ? edgeRounding : rounding + const bottomLeftRounding = !!(bottom^vertical) ? edgeRounding : rounding + const bottomRightRounding = bottom ? edgeRounding : rounding + + var topCornerYDirection = 0, bottomCornerYDirection = 0, leftCornerXDirection = 0, rightCornerXDirection = 0; + if (vertical) { + topCornerYDirection = 1; + bottomCornerYDirection = -1; + } else if (cornerStyle === 2) { // Rect + topCornerYDirection = 0; + bottomCornerYDirection = 0; + } else if (cornerStyle === 1) { // Rounded + topCornerYDirection = 1; + bottomCornerYDirection = -1; } else { // Hug - topCornerDirection = bottom ? -1 : 1; - bottomCornerDirection = bottom ? -1 : 1; + topCornerYDirection = bottom ? -1 : 1; + bottomCornerYDirection = bottom ? -1 : 1; } - - const points = [ + if (!vertical) { + leftCornerXDirection = 1; + rightCornerXDirection = -1 + } else if (cornerStyle === 2) { // Rect + leftCornerXDirection = 0; + rightCornerXDirection = 0; + } else if (cornerStyle === 1) { // Rounded + leftCornerXDirection = 1; + rightCornerXDirection = -1; + } else { // Hug + leftCornerXDirection = bottom ? -1 : 1; + rightCornerXDirection = bottom ? -1 : 1; + } + var points = [ // bottom-middle - new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth * 1/2, yBottom), new CornerRounding.CornerRounding(0)), - new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth * 0.1, yBottom), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft + width * 1/2, yBottom), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft + width * 0.1, yBottom), new CornerRounding.CornerRounding(0)), - // bottom-left /|| - new MaterialShapes.PointNRound(new Offset.Offset(xLeft + rounding, yBottom), new CornerRounding.CornerRounding(0)), - new MaterialShapes.PointNRound(new Offset.Offset(xLeft, yBottom), new CornerRounding.CornerRounding(bottomRounding)), - new MaterialShapes.PointNRound(new Offset.Offset(xLeft, yBottom + rounding * bottomCornerDirection), new CornerRounding.CornerRounding(edgeRounding)), - // top-left |/- - new MaterialShapes.PointNRound(new Offset.Offset(xLeft, yTop + rounding * topCornerDirection), new CornerRounding.CornerRounding(0)), - new MaterialShapes.PointNRound(new Offset.Offset(xLeft, yTop), new CornerRounding.CornerRounding(topRounding)), - new MaterialShapes.PointNRound(new Offset.Offset(xLeft + rounding, yTop), new CornerRounding.CornerRounding(0)), + // bottom-left + new MaterialShapes.PointNRound(new Offset.Offset(xLeft + rounding * leftCornerXDirection, yBottom), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft, yBottom), new CornerRounding.CornerRounding(bottomLeftRounding)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft, yBottom + rounding * bottomCornerYDirection), new CornerRounding.CornerRounding(edgeRounding)), + + // middle-left + new MaterialShapes.PointNRound(new Offset.Offset(xLeft, yTop + height * 0.9), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft, yTop + height * 1/2), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft, yTop + height * 0.1), new CornerRounding.CornerRounding(0)), + + // top-left + new MaterialShapes.PointNRound(new Offset.Offset(xLeft, yTop + rounding * topCornerYDirection), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft, yTop), new CornerRounding.CornerRounding(topLeftRounding)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft + rounding * leftCornerXDirection, yTop), new CornerRounding.CornerRounding(0)), // top-middle - new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth * 0.1, yTop), new CornerRounding.CornerRounding(0)), - new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth * 1/2, yTop), new CornerRounding.CornerRounding(0)), - new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth * 0.9, yTop), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft + width * 0.1, yTop), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft + width * 1/2, yTop), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft + width * 0.9, yTop), new CornerRounding.CornerRounding(0)), - // top-right -\| - new MaterialShapes.PointNRound(new Offset.Offset(xRight - rounding, yTop), new CornerRounding.CornerRounding(0)), - new MaterialShapes.PointNRound(new Offset.Offset(xRight, yTop), new CornerRounding.CornerRounding(topRounding)), - new MaterialShapes.PointNRound(new Offset.Offset(xRight, yTop + rounding * topCornerDirection), new CornerRounding.CornerRounding(0)), + // top-right + new MaterialShapes.PointNRound(new Offset.Offset(xRight + rounding * rightCornerXDirection, yTop), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xRight, yTop), new CornerRounding.CornerRounding(topRightRounding)), + new MaterialShapes.PointNRound(new Offset.Offset(xRight, yTop + rounding * topCornerYDirection), new CornerRounding.CornerRounding(0)), - // bottom-right ||\ - new MaterialShapes.PointNRound(new Offset.Offset(xRight, yBottom + rounding * bottomCornerDirection), new CornerRounding.CornerRounding(edgeRounding)), - new MaterialShapes.PointNRound(new Offset.Offset(xRight, yBottom), new CornerRounding.CornerRounding(bottomRounding)), - new MaterialShapes.PointNRound(new Offset.Offset(xRight - rounding, yBottom), new CornerRounding.CornerRounding(0)), + // middle-right + new MaterialShapes.PointNRound(new Offset.Offset(xRight, yTop + height * 0.1), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xRight, yTop + height * 1/2), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xRight, yTop + height * 0.9), new CornerRounding.CornerRounding(0)), + + // bottom-right + new MaterialShapes.PointNRound(new Offset.Offset(xRight, yBottom + rounding * bottomCornerYDirection), new CornerRounding.CornerRounding(edgeRounding)), + new MaterialShapes.PointNRound(new Offset.Offset(xRight, yBottom), new CornerRounding.CornerRounding(bottomRightRounding)), + new MaterialShapes.PointNRound(new Offset.Offset(xRight + rounding * rightCornerXDirection, yBottom), new CornerRounding.CornerRounding(0)), // bottom-middle - new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth * 0.9, yBottom), new CornerRounding.CornerRounding(0)), + new MaterialShapes.PointNRound(new Offset.Offset(xLeft + width * 0.9, yBottom), new CornerRounding.CornerRounding(0)), ] return MaterialShapes.customPolygon(points, 1, new Offset.Offset(root.screenWidth / 2, edgeGap + barHeight / 2)) } + backgroundPolygon: getBackgroundPolygon() + Connections { + target: Config + function onReadyChanged() { + if (Config.ready) + root.backgroundPolygon = root.getBackgroundPolygon() + } + function onReloaded() { + root.extraLoadCondition = false + root.backgroundPolygon = root.getBackgroundPolygon() + root.extraLoadCondition = true + } + } // Content - implicitHeight: barHeight + getEdgeGap(Config.options.bar.cornerStyle) * 2 + implicitHeight: vertical ? screenHeight : (barHeight + getEdgeGap(cornerStyle) * 2) + implicitWidth: vertical ? (barVerticalWidth + getEdgeGap(cornerStyle) * 2) : screenWidth + width: implicitWidth + height: implicitHeight anchors { top: parent.top bottom: undefined - left: parent.left - right: parent.right + left: undefined + right: undefined } - states: State { - name: "bottom" - when: Config.options.bar.bottom - AnchorChanges { - target: root - anchors.top: undefined - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right + states: [ + State { + name: "bottom" + when: root.atBottom && !root.vertical + AnchorChanges { + target: root + anchors.top: undefined + anchors.bottom: parent.bottom + anchors.left: undefined + anchors.right: undefined + } + }, + State { + name: "left" + when: !root.atBottom && root.vertical + AnchorChanges { + target: root + anchors.top: undefined + anchors.bottom: undefined + anchors.left: parent.left + anchors.right: undefined + } + }, + State { + name: "right" + when: root.atBottom && root.vertical + AnchorChanges { + target: root + anchors.top: undefined + anchors.bottom: undefined + anchors.left: undefined + anchors.right: parent.right + } } - } + ] transitions: Transition { AnchorAnimation { duration: 500 @@ -135,10 +221,11 @@ HAbstractMorphedPanel { } } + property bool extraLoadCondition: true FadeLazyLoader { id: contentLoader - load: root.load - shown: root.shown + load: root.load && root.extraLoadCondition + shown: root.shown && root.extraLoadCondition anchors.fill: parent component: HBarContent { parent: contentLoader diff --git a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarContent.qml b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarContent.qml index 76bd27696..d090a9221 100644 --- a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarContent.qml +++ b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarContent.qml @@ -1,8 +1,6 @@ import QtQuick import QtQuick.Layouts -import Quickshell -import qs.services -import qs.modules.common.widgets +import qs.modules.common as C Item { id: root @@ -11,13 +9,16 @@ Item { id: leftSide anchors.left: parent.left width: (parent.width - centerSide.width) / 2 + HBarUserFallbackComponentRepeater { + componentNames: C.Config.options.hefty.bar.leftWidgets + } } Side { id: centerSide anchors.horizontalCenter: parent.horizontalCenter HBarUserFallbackComponentRepeater { - componentNames: [["Workspaces"]] + componentNames: C.Config.options.hefty.bar.centerWidgets } } @@ -25,6 +26,9 @@ Item { id: rightSide anchors.right: parent.right width: (parent.width - centerSide.width) / 2 + HBarUserFallbackComponentRepeater { + componentNames: C.Config.options.hefty.bar.rightWidgets + } } component Side: RowLayout { diff --git a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/widgets/Workspaces.qml b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/widgets/Workspaces.qml index 7b0d7d026..c7141bbec 100644 --- a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/widgets/Workspaces.qml +++ b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/widgets/Workspaces.qml @@ -5,7 +5,8 @@ import qs.modules.common as C IIBar.Workspaces { id: root - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - implicitWidth: root.vertical ? C.Appearance.sizes.verticalBarWidth : (root.workspaceButtonWidth * root.workspacesShown - 2) - implicitHeight: root.vertical ? (root.workspaceButtonWidth * root.workspacesShown - 2) : C.Appearance.sizes.barHeight + vertical: C.Config.options.bar.vertical + Layout.alignment: vertical ? Qt.AlignHCenter : Qt.AlignVCenter + Layout.fillWidth: vertical + Layout.fillHeight: !vertical } diff --git a/dots/.config/quickshell/ii/modules/ii/bar/Workspaces.qml b/dots/.config/quickshell/ii/modules/ii/bar/Workspaces.qml index 947fa6d93..7652b8b9f 100644 --- a/dots/.config/quickshell/ii/modules/ii/bar/Workspaces.qml +++ b/dots/.config/quickshell/ii/modules/ii/bar/Workspaces.qml @@ -112,8 +112,8 @@ Item { rowSpacing: 0 columnSpacing: 0 - columns: root.vertical ? 1 : root.workspacesShown - rows: root.vertical ? root.workspacesShown : 1 + columns: root.vertical ? 1 : -1 + rows: root.vertical ? -1 : 1 Repeater { model: root.workspacesShown @@ -185,8 +185,8 @@ Item { id: wsNumbers z: 3 - columns: root.vertical ? 1 : root.workspacesShown - rows: root.vertical ? root.workspacesShown : 1 + columns: root.vertical ? 1 : -1 + rows: root.vertical ? -1 : 1 columnSpacing: 0 rowSpacing: 0