From 20c7482b2b72f7bec3191927e87c2f2cfd7f6230 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sat, 21 Mar 2026 16:04:57 +1100 Subject: [PATCH] chore: fix bar linter warnings --- config/BorderConfig.qml | 5 +- modules/bar/Bar.qml | 21 +- modules/bar/BarWrapper.qml | 8 +- .../components/workspaces/ActiveIndicator.qml | 5 +- .../workspaces/SpecialWorkspaces.qml | 286 +++++++++--------- .../bar/components/workspaces/Workspaces.qml | 4 +- modules/bar/popouts/ActiveWindow.qml | 4 +- modules/bar/popouts/Audio.qml | 4 +- modules/bar/popouts/Battery.qml | 2 +- modules/bar/popouts/Bluetooth.qml | 4 +- modules/bar/popouts/Content.qml | 48 ++- modules/bar/popouts/Network.qml | 12 +- modules/bar/popouts/PopoutState.qml | 8 + modules/bar/popouts/TrayMenu.qml | 2 +- modules/bar/popouts/WirelessPassword.qml | 16 +- modules/bar/popouts/Wrapper.qml | 17 +- modules/bar/popouts/kblayout/KbLayout.qml | 4 - 17 files changed, 230 insertions(+), 220 deletions(-) create mode 100644 modules/bar/popouts/PopoutState.qml diff --git a/config/BorderConfig.qml b/config/BorderConfig.qml index b203925d..662320d9 100644 --- a/config/BorderConfig.qml +++ b/config/BorderConfig.qml @@ -1,8 +1,9 @@ import Quickshell.Io +import qs.config JsonObject { - property int thickness: Appearance.padding.normal - property int rounding: Appearance.rounding.large + property int thickness: Config.appearance.padding.normal + property int rounding: Config.appearance.rounding.large readonly property int minThickness: 2 readonly property int clampedThickness: Math.max(minThickness, thickness) diff --git a/modules/bar/Bar.qml b/modules/bar/Bar.qml index 83815d1f..d4e8e977 100644 --- a/modules/bar/Bar.qml +++ b/modules/bar/Bar.qml @@ -23,9 +23,9 @@ ColumnLayout { return; for (let i = 0; i < repeater.count; i++) { - const item = repeater.itemAt(i); - if (item?.enabled && item.id === "tray") { - item.item.expanded = false; + const loader = repeater.itemAt(i) as WrappedLoader; + if (loader?.enabled && loader.id === "tray") { + (loader.item as Tray).expanded = false; } } } @@ -43,11 +43,9 @@ ColumnLayout { const id = ch.id; const top = ch.y; - const item = ch.item; - const itemHeight = item.implicitHeight; if (id === "statusIcons" && Config.bar.popouts.statusIcons) { - const items = item.items; + const items = (ch.item as StatusIcons).items; const icon = items.childAt(items.width / 2, mapToItem(items, 0, y).y); if (icon) { popouts.currentName = icon.name; @@ -55,9 +53,10 @@ ColumnLayout { popouts.hasCurrent = true; } } else if (id === "tray" && Config.bar.popouts.tray) { - if (!Config.bar.tray.compact || (item.expanded && !item.expandIcon.contains(mapToItem(item.expandIcon, item.implicitWidth / 2, y)))) { - const index = Math.floor(((y - top - item.padding * 2 + item.spacing) / item.layout.implicitHeight) * item.items.count); - const trayItem = item.items.itemAt(index); + const tray = ch.item as Tray; + if (!Config.bar.tray.compact || (tray.expanded && !tray.expandIcon.contains(mapToItem(tray.expandIcon, tray.implicitWidth / 2, y)))) { + const index = Math.floor(((y - top - tray.padding * 2 + tray.spacing) / tray.layout.implicitHeight) * tray.items.count); + const trayItem = tray.items.itemAt(index); if (trayItem) { popouts.currentName = `traymenu${index}`; popouts.currentCenter = Qt.binding(() => trayItem.mapToItem(root, 0, trayItem.implicitHeight / 2).y); @@ -67,11 +66,11 @@ ColumnLayout { } } else { popouts.hasCurrent = false; - item.expanded = true; + tray.expanded = true; } } else if (id === "activeWindow" && Config.bar.popouts.activeWindow && Config.bar.activeWindow.showOnHover) { popouts.currentName = id.toLowerCase(); - popouts.currentCenter = item.mapToItem(root, 0, itemHeight / 2).y; + popouts.currentCenter = (ch.item as Item).mapToItem(root, 0, (ch.item as Item).implicitHeight / 2).y ?? 0; popouts.hasCurrent = true; } } diff --git a/modules/bar/BarWrapper.qml b/modules/bar/BarWrapper.qml index 450e6a52..3a6bdfee 100644 --- a/modules/bar/BarWrapper.qml +++ b/modules/bar/BarWrapper.qml @@ -2,7 +2,7 @@ pragma ComponentBehavior: Bound import qs.components import qs.config -import "popouts" as BarPopouts +import qs.modules.bar.popouts as BarPopouts import Quickshell import QtQuick @@ -22,15 +22,15 @@ Item { property bool isHovered function closeTray(): void { - content.item?.closeTray(); + (content.item as Bar)?.closeTray(); } function checkPopout(y: real): void { - content.item?.checkPopout(y); + (content.item as Bar)?.checkPopout(y); } function handleWheel(y: real, angleDelta: point): void { - content.item?.handleWheel(y, angleDelta); + (content.item as Bar)?.handleWheel(y, angleDelta); } visible: width > Config.border.thickness diff --git a/modules/bar/components/workspaces/ActiveIndicator.qml b/modules/bar/components/workspaces/ActiveIndicator.qml index dae54b37..bad146eb 100644 --- a/modules/bar/components/workspaces/ActiveIndicator.qml +++ b/modules/bar/components/workspaces/ActiveIndicator.qml @@ -20,13 +20,12 @@ StyledRect { property real leading: workspaces.count > 0 ? workspaces.itemAt(currentWsIdx)?.y ?? 0 : 0 property real trailing: workspaces.count > 0 ? workspaces.itemAt(currentWsIdx)?.y ?? 0 : 0 - property real currentSize: workspaces.count > 0 ? workspaces.itemAt(currentWsIdx)?.size ?? 0 : 0 + property real currentSize: workspaces.count > 0 ? (workspaces.itemAt(currentWsIdx) as Workspace)?.size ?? 0 : 0 property real offset: Math.min(leading, trailing) property real size: { const s = Math.abs(leading - trailing) + currentSize; if (Config.bar.workspaces.activeTrail && lastWs > currentWsIdx) { - const ws = workspaces.itemAt(lastWs); - // console.log(ws, lastWs); + const ws = workspaces.itemAt(lastWs) as Workspace; return ws ? Math.min(ws.y + ws.size - offset, s) : 0; } return s; diff --git a/modules/bar/components/workspaces/SpecialWorkspaces.qml b/modules/bar/components/workspaces/SpecialWorkspaces.qml index 03394463..058a6a5f 100644 --- a/modules/bar/components/workspaces/SpecialWorkspaces.qml +++ b/modules/bar/components/workspaces/SpecialWorkspaces.qml @@ -15,7 +15,7 @@ Item { required property ShellScreen screen readonly property HyprlandMonitor monitor: Hypr.monitorFor(screen) - readonly property string activeSpecial: (Config.bar.workspaces.perMonitorWorkspaces ? monitor : Hypr.focusedMonitor)?.lastIpcObject?.specialWorkspace?.name ?? "" + readonly property string activeSpecial: (Config.bar.workspaces.perMonitorWorkspaces ? monitor : Hypr.focusedMonitor)?.lastIpcObject.specialWorkspace?.name ?? "" layer.enabled: true layer.effect: OpacityMask { @@ -105,151 +105,14 @@ Item { highlightFollowsCurrentItem: false highlight: Item { y: view.currentItem?.y ?? 0 - implicitHeight: view.currentItem?.size ?? 0 + implicitHeight: (view.currentItem as SpecialWsDelegate)?.size ?? 0 Behavior on y { Anim {} } } - delegate: ColumnLayout { - id: ws - - required property HyprlandWorkspace modelData - readonly property int size: label.Layout.preferredHeight + (hasWindows ? windows.implicitHeight + Appearance.padding.small : 0) - property int wsId - property string icon - property bool hasWindows - - anchors.left: view.contentItem.left - anchors.right: view.contentItem.right - - spacing: 0 - - Component.onCompleted: { - wsId = modelData.id; - icon = Icons.getSpecialWsIcon(modelData.name); - hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && modelData.lastIpcObject.windows > 0; - } - - // Hacky thing cause modelData gets destroyed before the remove anim finishes - Connections { - function onIdChanged(): void { - if (ws.modelData) - ws.wsId = ws.modelData.id; - } - - function onNameChanged(): void { - if (ws.modelData) - ws.icon = Icons.getSpecialWsIcon(ws.modelData.name); - } - - function onLastIpcObjectChanged(): void { - if (ws.modelData) - ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0; - } - - target: ws.modelData - } - - Connections { - function onShowWindowsOnSpecialWorkspacesChanged(): void { - if (ws.modelData) - ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0; - } - - target: Config.bar.workspaces - } - - Loader { - id: label - - asynchronous: true - - Layout.alignment: Qt.AlignHCenter | Qt.AlignTop - Layout.preferredHeight: Config.bar.sizes.innerWidth - Appearance.padding.small * 2 - - sourceComponent: ws.icon.length === 1 ? letterComp : iconComp - - Component { - id: iconComp - - MaterialIcon { - fill: 1 - text: ws.icon - verticalAlignment: Qt.AlignVCenter - } - } - - Component { - id: letterComp - - StyledText { - text: ws.icon - verticalAlignment: Qt.AlignVCenter - } - } - } - - Loader { - id: windows - - asynchronous: true - - Layout.alignment: Qt.AlignHCenter - Layout.fillHeight: true - Layout.preferredHeight: implicitHeight - - visible: active - active: ws.hasWindows - - sourceComponent: Column { - spacing: 0 - - add: Transition { - Anim { - properties: "scale" - from: 0 - to: 1 - easing.bezierCurve: Appearance.anim.curves.standardDecel - } - } - - move: Transition { - Anim { - properties: "scale" - to: 1 - easing.bezierCurve: Appearance.anim.curves.standardDecel - } - Anim { - properties: "x,y" - } - } - - Repeater { - model: ScriptModel { - values: { - const windows = Hypr.toplevels.values.filter(c => c.workspace?.id === ws.wsId); - const maxIcons = Config.bar.workspaces.maxWindowIcons; - return maxIcons > 0 ? windows.slice(0, maxIcons) : windows; - } - } - - MaterialIcon { - required property var modelData - - grade: 0 - text: Icons.getAppCategoryIcon(modelData.lastIpcObject.class, "terminal") - color: Colours.palette.m3onSurfaceVariant - } - } - } - - Behavior on Layout.preferredHeight { - Anim {} - } - } - } + delegate: SpecialWsDelegate {} add: Transition { Anim { @@ -296,6 +159,145 @@ Item { } } + component SpecialWsDelegate: ColumnLayout { + id: ws + + required property HyprlandWorkspace modelData + readonly property int size: label.Layout.preferredHeight + (hasWindows ? windows.implicitHeight + Appearance.padding.small : 0) + property int wsId + property string icon + property bool hasWindows + + anchors.left: view.contentItem.left + anchors.right: view.contentItem.right + + spacing: 0 + + Component.onCompleted: { + wsId = modelData.id; + icon = Icons.getSpecialWsIcon(modelData.name); + hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && modelData.lastIpcObject.windows > 0; + } + + // Hacky thing cause modelData gets destroyed before the remove anim finishes + Connections { + function onIdChanged(): void { + if (ws.modelData) + ws.wsId = ws.modelData.id; + } + + function onNameChanged(): void { + if (ws.modelData) + ws.icon = Icons.getSpecialWsIcon(ws.modelData.name); + } + + function onLastIpcObjectChanged(): void { + if (ws.modelData) + ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0; + } + + target: ws.modelData + } + + Connections { + function onShowWindowsOnSpecialWorkspacesChanged(): void { + if (ws.modelData) + ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0; + } + + target: Config.bar.workspaces + } + + Loader { + id: label + + asynchronous: true + + Layout.alignment: Qt.AlignHCenter | Qt.AlignTop + Layout.preferredHeight: Config.bar.sizes.innerWidth - Appearance.padding.small * 2 + + sourceComponent: ws.icon.length === 1 ? letterComp : iconComp + + Component { + id: iconComp + + MaterialIcon { + fill: 1 + text: ws.icon + verticalAlignment: Qt.AlignVCenter + } + } + + Component { + id: letterComp + + StyledText { + text: ws.icon + verticalAlignment: Qt.AlignVCenter + } + } + } + + Loader { + id: windows + + asynchronous: true + + Layout.alignment: Qt.AlignHCenter + Layout.fillHeight: true + Layout.preferredHeight: implicitHeight + + visible: active + active: ws.hasWindows + + sourceComponent: Column { + spacing: 0 + + add: Transition { + Anim { + properties: "scale" + from: 0 + to: 1 + easing.bezierCurve: Appearance.anim.curves.standardDecel + } + } + + move: Transition { + Anim { + properties: "scale" + to: 1 + easing.bezierCurve: Appearance.anim.curves.standardDecel + } + Anim { + properties: "x,y" + } + } + + Repeater { + model: ScriptModel { + values: { + const windows = Hypr.toplevels.values.filter(c => c.workspace?.id === ws.wsId); + const maxIcons = Config.bar.workspaces.maxWindowIcons; + return maxIcons > 0 ? windows.slice(0, maxIcons) : windows; + } + } + + MaterialIcon { + required property var modelData + + grade: 0 + text: Icons.getAppCategoryIcon(modelData.lastIpcObject.class, "terminal") + color: Colours.palette.m3onSurfaceVariant + } + } + } + + Behavior on Layout.preferredHeight { + Anim {} + } + } + } + Loader { asynchronous: true active: Config.bar.workspaces.activeIndicator @@ -309,7 +311,7 @@ Item { anchors.right: parent.right y: (view.currentItem?.y ?? 0) - view.contentY - implicitHeight: view.currentItem?.size ?? 0 + implicitHeight: (view.currentItem as SpecialWsDelegate)?.size ?? 0 color: Colours.palette.m3tertiary radius: Appearance.rounding.full @@ -358,7 +360,7 @@ Item { if (Math.abs(event.y - startY) > drag.threshold) return; - const ws = view.itemAt(event.x, event.y); + const ws = view.itemAt(event.x, event.y) as SpecialWsDelegate; if (ws?.modelData) Hypr.dispatch(`togglespecialworkspace ${ws.modelData.name.slice(8)}`); else diff --git a/modules/bar/components/workspaces/Workspaces.qml b/modules/bar/components/workspaces/Workspaces.qml index a2231b74..43f8fba6 100644 --- a/modules/bar/components/workspaces/Workspaces.qml +++ b/modules/bar/components/workspaces/Workspaces.qml @@ -13,7 +13,7 @@ StyledClippingRect { required property ShellScreen screen - readonly property bool onSpecial: (Config.bar.workspaces.perMonitorWorkspaces ? Hypr.monitorFor(screen) : Hypr.focusedMonitor)?.lastIpcObject?.specialWorkspace?.name !== "" + readonly property bool onSpecial: (Config.bar.workspaces.perMonitorWorkspaces ? Hypr.monitorFor(screen) : Hypr.focusedMonitor)?.lastIpcObject.specialWorkspace?.name !== "" readonly property int activeWsId: Config.bar.workspaces.perMonitorWorkspaces ? (Hypr.monitorFor(screen).activeWorkspace?.id ?? 1) : Hypr.activeWsId readonly property var occupied: { @@ -92,7 +92,7 @@ StyledClippingRect { MouseArea { anchors.fill: layout onClicked: event => { - const ws = layout.childAt(event.x, event.y).ws; + const ws = (layout.childAt(event.x, event.y) as Workspace)?.ws; if (Hypr.activeWsId !== ws) Hypr.dispatch(`workspace ${ws}`); else diff --git a/modules/bar/popouts/ActiveWindow.qml b/modules/bar/popouts/ActiveWindow.qml index 9f0162d3..9a1582a3 100644 --- a/modules/bar/popouts/ActiveWindow.qml +++ b/modules/bar/popouts/ActiveWindow.qml @@ -10,7 +10,7 @@ import QtQuick.Layouts Item { id: root - required property Item wrapper + required property PopoutState popouts implicitWidth: Hypr.activeToplevel ? child.implicitWidth : -Appearance.padding.large * 2 implicitHeight: child.implicitHeight @@ -66,7 +66,7 @@ Item { StateLayer { function onClicked(): void { - root.wrapper.detach("winfo"); + root.popouts.detachRequested("winfo"); } radius: Appearance.rounding.normal diff --git a/modules/bar/popouts/Audio.qml b/modules/bar/popouts/Audio.qml index fbc62a58..20cf826e 100644 --- a/modules/bar/popouts/Audio.qml +++ b/modules/bar/popouts/Audio.qml @@ -12,7 +12,7 @@ import QtQuick.Controls Item { id: root - required property var wrapper + required property PopoutState popouts implicitWidth: layout.implicitWidth + Appearance.padding.normal * 2 implicitHeight: layout.implicitHeight + Appearance.padding.normal * 2 @@ -112,7 +112,7 @@ Item { text: qsTr("Open settings") icon: "settings" - onClicked: root.wrapper.detach("audio") + onClicked: root.popouts.detachRequested("audio") } } } diff --git a/modules/bar/popouts/Battery.qml b/modules/bar/popouts/Battery.qml index 7c68f4d3..50cea105 100644 --- a/modules/bar/popouts/Battery.qml +++ b/modules/bar/popouts/Battery.qml @@ -42,7 +42,7 @@ Column { active: PowerProfiles.degradationReason !== PerformanceDegradationReason.None - height: active ? (item?.implicitHeight ?? 0) : 0 + height: active ? ((item as Item)?.implicitHeight ?? 0) : 0 sourceComponent: StyledRect { implicitWidth: child.implicitWidth + Appearance.padding.normal * 2 diff --git a/modules/bar/popouts/Bluetooth.qml b/modules/bar/popouts/Bluetooth.qml index 4ac4a667..3acace1c 100644 --- a/modules/bar/popouts/Bluetooth.qml +++ b/modules/bar/popouts/Bluetooth.qml @@ -13,7 +13,7 @@ import QtQuick.Layouts ColumnLayout { id: root - required property Item wrapper + required property PopoutState popouts spacing: Appearance.spacing.small @@ -173,7 +173,7 @@ ColumnLayout { text: qsTr("Open settings") icon: "settings" - onClicked: root.wrapper.detach("bluetooth") + onClicked: root.popouts.detachRequested("bluetooth") } component Toggle: RowLayout { diff --git a/modules/bar/popouts/Content.qml b/modules/bar/popouts/Content.qml index f866b45c..5ba8b3c0 100644 --- a/modules/bar/popouts/Content.qml +++ b/modules/bar/popouts/Content.qml @@ -11,7 +11,7 @@ import "./kblayout" Item { id: root - required property Item wrapper + required property PopoutState popouts readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null readonly property Item current: currentPopout?.item ?? null @@ -29,7 +29,7 @@ Item { Popout { name: "activewindow" sourceComponent: ActiveWindow { - wrapper: root.wrapper + popouts: root.popouts } } @@ -38,7 +38,7 @@ Item { name: "network" sourceComponent: Network { - wrapper: root.wrapper + popouts: root.popouts view: "wireless" } } @@ -46,7 +46,7 @@ Item { Popout { name: "ethernet" sourceComponent: Network { - wrapper: root.wrapper + popouts: root.popouts view: "ethernet" } } @@ -58,39 +58,39 @@ Item { sourceComponent: WirelessPassword { id: passwordComponent - wrapper: root.wrapper - network: networkPopout.item?.passwordNetwork ?? null + popouts: root.popouts + network: (networkPopout.item as Network)?.passwordNetwork ?? null } Connections { function onCurrentNameChanged() { // Update network immediately when password popout becomes active - if (root.wrapper.currentName === "wirelesspassword") { + if (root.popouts.currentName === "wirelesspassword") { // Set network immediately if available - if (networkPopout.item && networkPopout.item.passwordNetwork) { + if ((networkPopout.item as Network)?.passwordNetwork) { if (passwordPopout.item) { - passwordPopout.item.network = networkPopout.item.passwordNetwork; + (passwordPopout.item as WirelessPassword).network = (networkPopout.item as Network).passwordNetwork; } } // Also try after a short delay in case networkPopout.item wasn't ready Qt.callLater(() => { - if (passwordPopout.item && networkPopout.item && networkPopout.item.passwordNetwork) { - passwordPopout.item.network = networkPopout.item.passwordNetwork; + if (passwordPopout.item && (networkPopout.item as Network)?.passwordNetwork) { + (passwordPopout.item as WirelessPassword).network = (networkPopout.item as Network).passwordNetwork; } }, 100); } } - target: root.wrapper + target: root.popouts } Connections { function onItemChanged() { // When network popout loads, update password popout if it's active - if (root.wrapper.currentName === "wirelesspassword" && passwordPopout.item) { + if (root.popouts.currentName === "wirelesspassword" && passwordPopout.item) { Qt.callLater(() => { - if (networkPopout.item && networkPopout.item.passwordNetwork) { - passwordPopout.item.network = networkPopout.item.passwordNetwork; + if ((networkPopout.item as Network)?.passwordNetwork) { + (passwordPopout.item as WirelessPassword).network = (networkPopout.item as Network).passwordNetwork; } }); } @@ -103,7 +103,7 @@ Item { Popout { name: "bluetooth" sourceComponent: Bluetooth { - wrapper: root.wrapper + popouts: root.popouts } } @@ -115,15 +115,13 @@ Item { Popout { name: "audio" sourceComponent: Audio { - wrapper: root.wrapper + popouts: root.popouts } } Popout { name: "kblayout" - sourceComponent: KbLayout { - wrapper: root.wrapper - } + sourceComponent: KbLayout {} } Popout { @@ -147,21 +145,21 @@ Item { Connections { function onHasCurrentChanged(): void { - if (root.wrapper.hasCurrent && trayMenu.shouldBeActive) { + if (root.popouts.hasCurrent && trayMenu.shouldBeActive) { trayMenu.sourceComponent = null; trayMenu.sourceComponent = trayMenuComp; } } - target: root.wrapper + target: root.popouts } Component { id: trayMenuComp TrayMenu { - popouts: root.wrapper - trayItem: trayMenu.modelData.menu + popouts: root.popouts + trayItem: trayMenu.modelData.menu // qmllint disable unresolved-type } } } @@ -172,7 +170,7 @@ Item { id: popout required property string name - readonly property bool shouldBeActive: root.wrapper.currentName === name + readonly property bool shouldBeActive: root.popouts.currentName === name anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right diff --git a/modules/bar/popouts/Network.qml b/modules/bar/popouts/Network.qml index 91991fcb..fc2f1d40 100644 --- a/modules/bar/popouts/Network.qml +++ b/modules/bar/popouts/Network.qml @@ -12,7 +12,7 @@ import QtQuick.Layouts ColumnLayout { id: root - required property Item wrapper + required property PopoutState popouts property string connectingToSsid: "" property string view: "wireless" // "wireless" or "ethernet" @@ -132,7 +132,7 @@ ColumnLayout { // Password is required - show password dialog root.passwordNetwork = network; root.showPasswordDialog = true; - root.wrapper.currentName = "wirelesspassword"; + root.popouts.currentName = "wirelesspassword"; }); // Clear connecting state if connection succeeds immediately (saved profile) @@ -341,8 +341,8 @@ ColumnLayout { if (root.showPasswordDialog && root.passwordNetwork && Nmcli.active.ssid === root.passwordNetwork.ssid) { root.showPasswordDialog = false; root.passwordNetwork = null; - if (root.wrapper.currentName === "wirelesspassword") { - root.wrapper.currentName = "network"; + if (root.popouts.currentName === "wirelesspassword") { + root.popouts.currentName = "network"; } } } @@ -359,13 +359,13 @@ ColumnLayout { Connections { function onCurrentNameChanged(): void { // Clear password network when leaving password dialog - if (root.wrapper.currentName !== "wirelesspassword" && root.showPasswordDialog) { + if (root.popouts.currentName !== "wirelesspassword" && root.showPasswordDialog) { root.showPasswordDialog = false; root.passwordNetwork = null; } } - target: root.wrapper + target: root.popouts } component Toggle: RowLayout { diff --git a/modules/bar/popouts/PopoutState.qml b/modules/bar/popouts/PopoutState.qml new file mode 100644 index 00000000..6be8169b --- /dev/null +++ b/modules/bar/popouts/PopoutState.qml @@ -0,0 +1,8 @@ +import QtQuick + +QtObject { + property string currentName + property bool hasCurrent + + signal detachRequested(mode: string) +} diff --git a/modules/bar/popouts/TrayMenu.qml b/modules/bar/popouts/TrayMenu.qml index eac73eeb..09194d97 100644 --- a/modules/bar/popouts/TrayMenu.qml +++ b/modules/bar/popouts/TrayMenu.qml @@ -11,7 +11,7 @@ import QtQuick.Controls StackView { id: root - required property Item popouts + required property PopoutState popouts required property QsMenuHandle trayItem implicitWidth: currentItem?.implicitWidth ?? 0 diff --git a/modules/bar/popouts/WirelessPassword.qml b/modules/bar/popouts/WirelessPassword.qml index 0c0f301f..4d0b7aed 100644 --- a/modules/bar/popouts/WirelessPassword.qml +++ b/modules/bar/popouts/WirelessPassword.qml @@ -12,11 +12,11 @@ import QtQuick.Layouts ColumnLayout { id: root - required property Item wrapper + required property PopoutState popouts property var network: null property bool isClosing: false - readonly property bool shouldBeVisible: root.wrapper.currentName === "wirelesspassword" + readonly property bool shouldBeVisible: root.popouts.currentName === "wirelesspassword" function checkConnectionStatus(): void { if (!root.shouldBeVisible || !connectButton.connecting) { @@ -64,8 +64,8 @@ ColumnLayout { connectionMonitor.stop(); // Return to network popout - if (root.wrapper.currentName === "wirelesspassword") { - root.wrapper.currentName = "network"; + if (root.popouts.currentName === "wirelesspassword") { + root.popouts.currentName = "network"; } } @@ -94,7 +94,7 @@ ColumnLayout { Connections { function onCurrentNameChanged() { - if (root.wrapper.currentName === "wirelesspassword") { + if (root.popouts.currentName === "wirelesspassword") { // Update network when popout becomes active Qt.callLater(() => { // Try to get network from parent Content's networkPopout @@ -112,7 +112,7 @@ ColumnLayout { } } - target: root.wrapper + target: root.popouts } Timer { @@ -578,8 +578,8 @@ ColumnLayout { connectButton.connecting = false; connectButton.text = qsTr("Connect"); // Return to network popout on successful connection - if (root.wrapper.currentName === "wirelesspassword") { - root.wrapper.currentName = "network"; + if (root.popouts.currentName === "wirelesspassword") { + root.popouts.currentName = "network"; } closeDialog(); } diff --git a/modules/bar/popouts/Wrapper.qml b/modules/bar/popouts/Wrapper.qml index 40479f9a..88861166 100644 --- a/modules/bar/popouts/Wrapper.qml +++ b/modules/bar/popouts/Wrapper.qml @@ -17,11 +17,12 @@ Item { readonly property real nonAnimWidth: x > 0 || hasCurrent ? children.find(c => c.shouldBeActive)?.implicitWidth ?? content.implicitWidth : 0 readonly property real nonAnimHeight: children.find(c => c.shouldBeActive)?.implicitHeight ?? content.implicitHeight - readonly property Item current: content.item?.current ?? null + readonly property Item current: (content.item as Content)?.current ?? null - property string currentName + property alias currentName: popoutState.currentName property real currentCenter - property bool hasCurrent + property alias hasCurrent: popoutState.hasCurrent + readonly property PopoutState state: popoutState property string detachedMode property string queuedMode @@ -59,7 +60,7 @@ Item { Keys.onEscapePressed: { // Forward escape to password popout if active, otherwise close if (currentName === "wirelesspassword" && content.item) { - const passwordPopout = content.item.children.find(c => c.name === "wirelesspassword"); + const passwordPopout = (content.item as Content)?.children.find(c => c.name === "wirelesspassword"); if (passwordPopout && passwordPopout.item) { passwordPopout.item.closeDialog(); return; @@ -75,6 +76,12 @@ Item { } } + PopoutState { + id: popoutState + + onDetachRequested: mode => root.detach(mode) + } + HyprlandFocusGrab { active: root.isDetached windows: [QsWindow.window] @@ -105,7 +112,7 @@ Item { anchors.verticalCenter: parent.verticalCenter sourceComponent: Content { - wrapper: root + popouts: popoutState } } diff --git a/modules/bar/popouts/kblayout/KbLayout.qml b/modules/bar/popouts/kblayout/KbLayout.qml index 74ee67e1..68a7a794 100644 --- a/modules/bar/popouts/kblayout/KbLayout.qml +++ b/modules/bar/popouts/kblayout/KbLayout.qml @@ -7,13 +7,9 @@ import qs.components import qs.services import qs.config -import "." - ColumnLayout { id: root - required property Item wrapper - function refresh() { kb.refresh(); }