chore: fix bar linter warnings

This commit is contained in:
2 * r + 2 * t 2026-03-21 16:04:57 +11:00
parent 022d509f99
commit 20c7482b2b
17 changed files with 230 additions and 220 deletions

View file

@ -1,8 +1,9 @@
import Quickshell.Io import Quickshell.Io
import qs.config
JsonObject { JsonObject {
property int thickness: Appearance.padding.normal property int thickness: Config.appearance.padding.normal
property int rounding: Appearance.rounding.large property int rounding: Config.appearance.rounding.large
readonly property int minThickness: 2 readonly property int minThickness: 2
readonly property int clampedThickness: Math.max(minThickness, thickness) readonly property int clampedThickness: Math.max(minThickness, thickness)

View file

@ -23,9 +23,9 @@ ColumnLayout {
return; return;
for (let i = 0; i < repeater.count; i++) { for (let i = 0; i < repeater.count; i++) {
const item = repeater.itemAt(i); const loader = repeater.itemAt(i) as WrappedLoader;
if (item?.enabled && item.id === "tray") { if (loader?.enabled && loader.id === "tray") {
item.item.expanded = false; (loader.item as Tray).expanded = false;
} }
} }
} }
@ -43,11 +43,9 @@ ColumnLayout {
const id = ch.id; const id = ch.id;
const top = ch.y; const top = ch.y;
const item = ch.item;
const itemHeight = item.implicitHeight;
if (id === "statusIcons" && Config.bar.popouts.statusIcons) { 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); const icon = items.childAt(items.width / 2, mapToItem(items, 0, y).y);
if (icon) { if (icon) {
popouts.currentName = icon.name; popouts.currentName = icon.name;
@ -55,9 +53,10 @@ ColumnLayout {
popouts.hasCurrent = true; popouts.hasCurrent = true;
} }
} else if (id === "tray" && Config.bar.popouts.tray) { } 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 tray = ch.item as Tray;
const index = Math.floor(((y - top - item.padding * 2 + item.spacing) / item.layout.implicitHeight) * item.items.count); if (!Config.bar.tray.compact || (tray.expanded && !tray.expandIcon.contains(mapToItem(tray.expandIcon, tray.implicitWidth / 2, y)))) {
const trayItem = item.items.itemAt(index); 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) { if (trayItem) {
popouts.currentName = `traymenu${index}`; popouts.currentName = `traymenu${index}`;
popouts.currentCenter = Qt.binding(() => trayItem.mapToItem(root, 0, trayItem.implicitHeight / 2).y); popouts.currentCenter = Qt.binding(() => trayItem.mapToItem(root, 0, trayItem.implicitHeight / 2).y);
@ -67,11 +66,11 @@ ColumnLayout {
} }
} else { } else {
popouts.hasCurrent = false; popouts.hasCurrent = false;
item.expanded = true; tray.expanded = true;
} }
} else if (id === "activeWindow" && Config.bar.popouts.activeWindow && Config.bar.activeWindow.showOnHover) { } else if (id === "activeWindow" && Config.bar.popouts.activeWindow && Config.bar.activeWindow.showOnHover) {
popouts.currentName = id.toLowerCase(); 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; popouts.hasCurrent = true;
} }
} }

View file

@ -2,7 +2,7 @@ pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.config import qs.config
import "popouts" as BarPopouts import qs.modules.bar.popouts as BarPopouts
import Quickshell import Quickshell
import QtQuick import QtQuick
@ -22,15 +22,15 @@ Item {
property bool isHovered property bool isHovered
function closeTray(): void { function closeTray(): void {
content.item?.closeTray(); (content.item as Bar)?.closeTray();
} }
function checkPopout(y: real): void { function checkPopout(y: real): void {
content.item?.checkPopout(y); (content.item as Bar)?.checkPopout(y);
} }
function handleWheel(y: real, angleDelta: point): void { function handleWheel(y: real, angleDelta: point): void {
content.item?.handleWheel(y, angleDelta); (content.item as Bar)?.handleWheel(y, angleDelta);
} }
visible: width > Config.border.thickness visible: width > Config.border.thickness

View file

@ -20,13 +20,12 @@ StyledRect {
property real leading: workspaces.count > 0 ? workspaces.itemAt(currentWsIdx)?.y ?? 0 : 0 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 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 offset: Math.min(leading, trailing)
property real size: { property real size: {
const s = Math.abs(leading - trailing) + currentSize; const s = Math.abs(leading - trailing) + currentSize;
if (Config.bar.workspaces.activeTrail && lastWs > currentWsIdx) { if (Config.bar.workspaces.activeTrail && lastWs > currentWsIdx) {
const ws = workspaces.itemAt(lastWs); const ws = workspaces.itemAt(lastWs) as Workspace;
// console.log(ws, lastWs);
return ws ? Math.min(ws.y + ws.size - offset, s) : 0; return ws ? Math.min(ws.y + ws.size - offset, s) : 0;
} }
return s; return s;

View file

@ -15,7 +15,7 @@ Item {
required property ShellScreen screen required property ShellScreen screen
readonly property HyprlandMonitor monitor: Hypr.monitorFor(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.enabled: true
layer.effect: OpacityMask { layer.effect: OpacityMask {
@ -105,151 +105,14 @@ Item {
highlightFollowsCurrentItem: false highlightFollowsCurrentItem: false
highlight: Item { highlight: Item {
y: view.currentItem?.y ?? 0 y: view.currentItem?.y ?? 0
implicitHeight: view.currentItem?.size ?? 0 implicitHeight: (view.currentItem as SpecialWsDelegate)?.size ?? 0
Behavior on y { Behavior on y {
Anim {} Anim {}
} }
} }
delegate: ColumnLayout { delegate: SpecialWsDelegate {}
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 {}
}
}
}
add: Transition { add: Transition {
Anim { 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 { Loader {
asynchronous: true asynchronous: true
active: Config.bar.workspaces.activeIndicator active: Config.bar.workspaces.activeIndicator
@ -309,7 +311,7 @@ Item {
anchors.right: parent.right anchors.right: parent.right
y: (view.currentItem?.y ?? 0) - view.contentY y: (view.currentItem?.y ?? 0) - view.contentY
implicitHeight: view.currentItem?.size ?? 0 implicitHeight: (view.currentItem as SpecialWsDelegate)?.size ?? 0
color: Colours.palette.m3tertiary color: Colours.palette.m3tertiary
radius: Appearance.rounding.full radius: Appearance.rounding.full
@ -358,7 +360,7 @@ Item {
if (Math.abs(event.y - startY) > drag.threshold) if (Math.abs(event.y - startY) > drag.threshold)
return; return;
const ws = view.itemAt(event.x, event.y); const ws = view.itemAt(event.x, event.y) as SpecialWsDelegate;
if (ws?.modelData) if (ws?.modelData)
Hypr.dispatch(`togglespecialworkspace ${ws.modelData.name.slice(8)}`); Hypr.dispatch(`togglespecialworkspace ${ws.modelData.name.slice(8)}`);
else else

View file

@ -13,7 +13,7 @@ StyledClippingRect {
required property ShellScreen screen 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 int activeWsId: Config.bar.workspaces.perMonitorWorkspaces ? (Hypr.monitorFor(screen).activeWorkspace?.id ?? 1) : Hypr.activeWsId
readonly property var occupied: { readonly property var occupied: {
@ -92,7 +92,7 @@ StyledClippingRect {
MouseArea { MouseArea {
anchors.fill: layout anchors.fill: layout
onClicked: event => { 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) if (Hypr.activeWsId !== ws)
Hypr.dispatch(`workspace ${ws}`); Hypr.dispatch(`workspace ${ws}`);
else else

View file

@ -10,7 +10,7 @@ import QtQuick.Layouts
Item { Item {
id: root id: root
required property Item wrapper required property PopoutState popouts
implicitWidth: Hypr.activeToplevel ? child.implicitWidth : -Appearance.padding.large * 2 implicitWidth: Hypr.activeToplevel ? child.implicitWidth : -Appearance.padding.large * 2
implicitHeight: child.implicitHeight implicitHeight: child.implicitHeight
@ -66,7 +66,7 @@ Item {
StateLayer { StateLayer {
function onClicked(): void { function onClicked(): void {
root.wrapper.detach("winfo"); root.popouts.detachRequested("winfo");
} }
radius: Appearance.rounding.normal radius: Appearance.rounding.normal

View file

@ -12,7 +12,7 @@ import QtQuick.Controls
Item { Item {
id: root id: root
required property var wrapper required property PopoutState popouts
implicitWidth: layout.implicitWidth + Appearance.padding.normal * 2 implicitWidth: layout.implicitWidth + Appearance.padding.normal * 2
implicitHeight: layout.implicitHeight + Appearance.padding.normal * 2 implicitHeight: layout.implicitHeight + Appearance.padding.normal * 2
@ -112,7 +112,7 @@ Item {
text: qsTr("Open settings") text: qsTr("Open settings")
icon: "settings" icon: "settings"
onClicked: root.wrapper.detach("audio") onClicked: root.popouts.detachRequested("audio")
} }
} }
} }

View file

@ -42,7 +42,7 @@ Column {
active: PowerProfiles.degradationReason !== PerformanceDegradationReason.None active: PowerProfiles.degradationReason !== PerformanceDegradationReason.None
height: active ? (item?.implicitHeight ?? 0) : 0 height: active ? ((item as Item)?.implicitHeight ?? 0) : 0
sourceComponent: StyledRect { sourceComponent: StyledRect {
implicitWidth: child.implicitWidth + Appearance.padding.normal * 2 implicitWidth: child.implicitWidth + Appearance.padding.normal * 2

View file

@ -13,7 +13,7 @@ import QtQuick.Layouts
ColumnLayout { ColumnLayout {
id: root id: root
required property Item wrapper required property PopoutState popouts
spacing: Appearance.spacing.small spacing: Appearance.spacing.small
@ -173,7 +173,7 @@ ColumnLayout {
text: qsTr("Open settings") text: qsTr("Open settings")
icon: "settings" icon: "settings"
onClicked: root.wrapper.detach("bluetooth") onClicked: root.popouts.detachRequested("bluetooth")
} }
component Toggle: RowLayout { component Toggle: RowLayout {

View file

@ -11,7 +11,7 @@ import "./kblayout"
Item { Item {
id: root id: root
required property Item wrapper required property PopoutState popouts
readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null
readonly property Item current: currentPopout?.item ?? null readonly property Item current: currentPopout?.item ?? null
@ -29,7 +29,7 @@ Item {
Popout { Popout {
name: "activewindow" name: "activewindow"
sourceComponent: ActiveWindow { sourceComponent: ActiveWindow {
wrapper: root.wrapper popouts: root.popouts
} }
} }
@ -38,7 +38,7 @@ Item {
name: "network" name: "network"
sourceComponent: Network { sourceComponent: Network {
wrapper: root.wrapper popouts: root.popouts
view: "wireless" view: "wireless"
} }
} }
@ -46,7 +46,7 @@ Item {
Popout { Popout {
name: "ethernet" name: "ethernet"
sourceComponent: Network { sourceComponent: Network {
wrapper: root.wrapper popouts: root.popouts
view: "ethernet" view: "ethernet"
} }
} }
@ -58,39 +58,39 @@ Item {
sourceComponent: WirelessPassword { sourceComponent: WirelessPassword {
id: passwordComponent id: passwordComponent
wrapper: root.wrapper popouts: root.popouts
network: networkPopout.item?.passwordNetwork ?? null network: (networkPopout.item as Network)?.passwordNetwork ?? null
} }
Connections { Connections {
function onCurrentNameChanged() { function onCurrentNameChanged() {
// Update network immediately when password popout becomes active // Update network immediately when password popout becomes active
if (root.wrapper.currentName === "wirelesspassword") { if (root.popouts.currentName === "wirelesspassword") {
// Set network immediately if available // Set network immediately if available
if (networkPopout.item && networkPopout.item.passwordNetwork) { if ((networkPopout.item as Network)?.passwordNetwork) {
if (passwordPopout.item) { 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 // Also try after a short delay in case networkPopout.item wasn't ready
Qt.callLater(() => { Qt.callLater(() => {
if (passwordPopout.item && networkPopout.item && networkPopout.item.passwordNetwork) { if (passwordPopout.item && (networkPopout.item as Network)?.passwordNetwork) {
passwordPopout.item.network = networkPopout.item.passwordNetwork; (passwordPopout.item as WirelessPassword).network = (networkPopout.item as Network).passwordNetwork;
} }
}, 100); }, 100);
} }
} }
target: root.wrapper target: root.popouts
} }
Connections { Connections {
function onItemChanged() { function onItemChanged() {
// When network popout loads, update password popout if it's active // 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(() => { Qt.callLater(() => {
if (networkPopout.item && networkPopout.item.passwordNetwork) { if ((networkPopout.item as Network)?.passwordNetwork) {
passwordPopout.item.network = networkPopout.item.passwordNetwork; (passwordPopout.item as WirelessPassword).network = (networkPopout.item as Network).passwordNetwork;
} }
}); });
} }
@ -103,7 +103,7 @@ Item {
Popout { Popout {
name: "bluetooth" name: "bluetooth"
sourceComponent: Bluetooth { sourceComponent: Bluetooth {
wrapper: root.wrapper popouts: root.popouts
} }
} }
@ -115,15 +115,13 @@ Item {
Popout { Popout {
name: "audio" name: "audio"
sourceComponent: Audio { sourceComponent: Audio {
wrapper: root.wrapper popouts: root.popouts
} }
} }
Popout { Popout {
name: "kblayout" name: "kblayout"
sourceComponent: KbLayout { sourceComponent: KbLayout {}
wrapper: root.wrapper
}
} }
Popout { Popout {
@ -147,21 +145,21 @@ Item {
Connections { Connections {
function onHasCurrentChanged(): void { function onHasCurrentChanged(): void {
if (root.wrapper.hasCurrent && trayMenu.shouldBeActive) { if (root.popouts.hasCurrent && trayMenu.shouldBeActive) {
trayMenu.sourceComponent = null; trayMenu.sourceComponent = null;
trayMenu.sourceComponent = trayMenuComp; trayMenu.sourceComponent = trayMenuComp;
} }
} }
target: root.wrapper target: root.popouts
} }
Component { Component {
id: trayMenuComp id: trayMenuComp
TrayMenu { TrayMenu {
popouts: root.wrapper popouts: root.popouts
trayItem: trayMenu.modelData.menu trayItem: trayMenu.modelData.menu // qmllint disable unresolved-type
} }
} }
} }
@ -172,7 +170,7 @@ Item {
id: popout id: popout
required property string name 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.verticalCenter: parent.verticalCenter
anchors.right: parent.right anchors.right: parent.right

View file

@ -12,7 +12,7 @@ import QtQuick.Layouts
ColumnLayout { ColumnLayout {
id: root id: root
required property Item wrapper required property PopoutState popouts
property string connectingToSsid: "" property string connectingToSsid: ""
property string view: "wireless" // "wireless" or "ethernet" property string view: "wireless" // "wireless" or "ethernet"
@ -132,7 +132,7 @@ ColumnLayout {
// Password is required - show password dialog // Password is required - show password dialog
root.passwordNetwork = network; root.passwordNetwork = network;
root.showPasswordDialog = true; root.showPasswordDialog = true;
root.wrapper.currentName = "wirelesspassword"; root.popouts.currentName = "wirelesspassword";
}); });
// Clear connecting state if connection succeeds immediately (saved profile) // 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) { if (root.showPasswordDialog && root.passwordNetwork && Nmcli.active.ssid === root.passwordNetwork.ssid) {
root.showPasswordDialog = false; root.showPasswordDialog = false;
root.passwordNetwork = null; root.passwordNetwork = null;
if (root.wrapper.currentName === "wirelesspassword") { if (root.popouts.currentName === "wirelesspassword") {
root.wrapper.currentName = "network"; root.popouts.currentName = "network";
} }
} }
} }
@ -359,13 +359,13 @@ ColumnLayout {
Connections { Connections {
function onCurrentNameChanged(): void { function onCurrentNameChanged(): void {
// Clear password network when leaving password dialog // 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.showPasswordDialog = false;
root.passwordNetwork = null; root.passwordNetwork = null;
} }
} }
target: root.wrapper target: root.popouts
} }
component Toggle: RowLayout { component Toggle: RowLayout {

View file

@ -0,0 +1,8 @@
import QtQuick
QtObject {
property string currentName
property bool hasCurrent
signal detachRequested(mode: string)
}

View file

@ -11,7 +11,7 @@ import QtQuick.Controls
StackView { StackView {
id: root id: root
required property Item popouts required property PopoutState popouts
required property QsMenuHandle trayItem required property QsMenuHandle trayItem
implicitWidth: currentItem?.implicitWidth ?? 0 implicitWidth: currentItem?.implicitWidth ?? 0

View file

@ -12,11 +12,11 @@ import QtQuick.Layouts
ColumnLayout { ColumnLayout {
id: root id: root
required property Item wrapper required property PopoutState popouts
property var network: null property var network: null
property bool isClosing: false property bool isClosing: false
readonly property bool shouldBeVisible: root.wrapper.currentName === "wirelesspassword" readonly property bool shouldBeVisible: root.popouts.currentName === "wirelesspassword"
function checkConnectionStatus(): void { function checkConnectionStatus(): void {
if (!root.shouldBeVisible || !connectButton.connecting) { if (!root.shouldBeVisible || !connectButton.connecting) {
@ -64,8 +64,8 @@ ColumnLayout {
connectionMonitor.stop(); connectionMonitor.stop();
// Return to network popout // Return to network popout
if (root.wrapper.currentName === "wirelesspassword") { if (root.popouts.currentName === "wirelesspassword") {
root.wrapper.currentName = "network"; root.popouts.currentName = "network";
} }
} }
@ -94,7 +94,7 @@ ColumnLayout {
Connections { Connections {
function onCurrentNameChanged() { function onCurrentNameChanged() {
if (root.wrapper.currentName === "wirelesspassword") { if (root.popouts.currentName === "wirelesspassword") {
// Update network when popout becomes active // Update network when popout becomes active
Qt.callLater(() => { Qt.callLater(() => {
// Try to get network from parent Content's networkPopout // Try to get network from parent Content's networkPopout
@ -112,7 +112,7 @@ ColumnLayout {
} }
} }
target: root.wrapper target: root.popouts
} }
Timer { Timer {
@ -578,8 +578,8 @@ ColumnLayout {
connectButton.connecting = false; connectButton.connecting = false;
connectButton.text = qsTr("Connect"); connectButton.text = qsTr("Connect");
// Return to network popout on successful connection // Return to network popout on successful connection
if (root.wrapper.currentName === "wirelesspassword") { if (root.popouts.currentName === "wirelesspassword") {
root.wrapper.currentName = "network"; root.popouts.currentName = "network";
} }
closeDialog(); closeDialog();
} }

View file

@ -17,11 +17,12 @@ Item {
readonly property real nonAnimWidth: x > 0 || hasCurrent ? children.find(c => c.shouldBeActive)?.implicitWidth ?? content.implicitWidth : 0 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 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 real currentCenter
property bool hasCurrent property alias hasCurrent: popoutState.hasCurrent
readonly property PopoutState state: popoutState
property string detachedMode property string detachedMode
property string queuedMode property string queuedMode
@ -59,7 +60,7 @@ Item {
Keys.onEscapePressed: { Keys.onEscapePressed: {
// Forward escape to password popout if active, otherwise close // Forward escape to password popout if active, otherwise close
if (currentName === "wirelesspassword" && content.item) { 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) { if (passwordPopout && passwordPopout.item) {
passwordPopout.item.closeDialog(); passwordPopout.item.closeDialog();
return; return;
@ -75,6 +76,12 @@ Item {
} }
} }
PopoutState {
id: popoutState
onDetachRequested: mode => root.detach(mode)
}
HyprlandFocusGrab { HyprlandFocusGrab {
active: root.isDetached active: root.isDetached
windows: [QsWindow.window] windows: [QsWindow.window]
@ -105,7 +112,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
sourceComponent: Content { sourceComponent: Content {
wrapper: root popouts: popoutState
} }
} }

View file

@ -7,13 +7,9 @@ import qs.components
import qs.services import qs.services
import qs.config import qs.config
import "."
ColumnLayout { ColumnLayout {
id: root id: root
required property Item wrapper
function refresh() { function refresh() {
kb.refresh(); kb.refresh();
} }