From 25515fd32b84ab7320bac305a7c050933747c8c3 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sun, 22 Mar 2026 16:08:57 +1100 Subject: [PATCH] chore: fix rest of formatting issues --- components/controls/StyledInputField.qml | 14 +- config/LauncherConfig.qml | 30 +- config/UtilitiesConfig.qml | 50 +- .../bar/components/workspaces/OccupiedBg.qml | 10 +- .../workspaces/SpecialWorkspaces.qml | 140 ++--- modules/bar/popouts/TrayMenu.qml | 12 +- modules/bar/popouts/WirelessPassword.qml | 14 +- .../bar/popouts/kblayout/KbLayoutModel.qml | 20 +- .../sections/ColorSchemeSection.qml | 3 +- .../sections/ColorVariantSection.qml | 3 +- .../appearance/sections/FontsSection.qml | 9 +- modules/controlcenter/audio/AudioPane.qml | 66 +-- .../controlcenter/components/DeviceList.qml | 3 +- .../controlcenter/components/SliderInput.qml | 16 +- .../components/SplitPaneWithDetails.qml | 10 +- .../components/WallpaperGrid.qml | 16 +- .../controlcenter/launcher/LauncherPane.qml | 8 +- modules/controlcenter/network/VpnList.qml | 3 +- modules/controlcenter/network/VpnSettings.qml | 3 +- .../controlcenter/network/WirelessList.qml | 3 +- .../network/WirelessPasswordDialog.qml | 3 +- services/LyricsService.qml | 181 +++--- services/Network.qml | 12 +- services/Nmcli.qml | 550 +++++++++--------- 24 files changed, 582 insertions(+), 597 deletions(-) diff --git a/components/controls/StyledInputField.qml b/components/controls/StyledInputField.qml index 9c3390fe..f56f79fb 100644 --- a/components/controls/StyledInputField.qml +++ b/components/controls/StyledInputField.qml @@ -61,13 +61,6 @@ Item { readOnly: root.readOnly enabled: root.enabled - Binding { - target: inputField - property: "text" - value: root.text - when: !inputField.activeFocus - } - onTextChanged: { root.text = text; root.textEdited(text); @@ -76,6 +69,13 @@ Item { onEditingFinished: { root.editingFinished(); } + + Binding { + target: inputField + property: "text" + value: root.text + when: !inputField.activeFocus + } } } } diff --git a/config/LauncherConfig.qml b/config/LauncherConfig.qml index d9e3a738..05088af0 100644 --- a/config/LauncherConfig.qml +++ b/config/LauncherConfig.qml @@ -15,21 +15,6 @@ JsonObject { property UseFuzzy useFuzzy: UseFuzzy {} property Sizes sizes: Sizes {} - component UseFuzzy: JsonObject { - property bool apps: false - property bool actions: false - property bool schemes: false - property bool variants: false - property bool wallpapers: false - } - - component Sizes: JsonObject { - property int itemWidth: 600 - property int itemHeight: 57 - property int wallpaperWidth: 280 - property int wallpaperHeight: 200 - } - property list actions: [ { name: "Calculator", @@ -144,4 +129,19 @@ JsonObject { dangerous: false } ] + + component UseFuzzy: JsonObject { + property bool apps: false + property bool actions: false + property bool schemes: false + property bool variants: false + property bool wallpapers: false + } + + component Sizes: JsonObject { + property int itemWidth: 600 + property int itemHeight: 57 + property int wallpaperWidth: 280 + property int wallpaperHeight: 200 + } } diff --git a/config/UtilitiesConfig.qml b/config/UtilitiesConfig.qml index 4d1dd6e8..017ab4ad 100644 --- a/config/UtilitiesConfig.qml +++ b/config/UtilitiesConfig.qml @@ -8,31 +8,6 @@ JsonObject { property Toasts toasts: Toasts {} property Vpn vpn: Vpn {} - component Sizes: JsonObject { - property int width: 430 - property int toastWidth: 430 - } - - component Toasts: JsonObject { - property bool configLoaded: true - property bool chargingChanged: true - property bool gameModeChanged: true - property bool dndChanged: true - property bool audioOutputChanged: true - property bool audioInputChanged: true - property bool capsLockChanged: true - property bool numLockChanged: true - property bool kbLayoutChanged: true - property bool kbLimit: true - property bool vpnChanged: true - property bool nowPlaying: false - } - - component Vpn: JsonObject { - property bool enabled: false - property list provider: ["netbird"] - } - property list quickToggles: [ { id: "wifi", @@ -63,4 +38,29 @@ JsonObject { enabled: false } ] + + component Sizes: JsonObject { + property int width: 430 + property int toastWidth: 430 + } + + component Toasts: JsonObject { + property bool configLoaded: true + property bool chargingChanged: true + property bool gameModeChanged: true + property bool dndChanged: true + property bool audioOutputChanged: true + property bool audioInputChanged: true + property bool capsLockChanged: true + property bool numLockChanged: true + property bool kbLayoutChanged: true + property bool kbLimit: true + property bool vpnChanged: true + property bool nowPlaying: false + } + + component Vpn: JsonObject { + property bool enabled: false + property list provider: ["netbird"] + } } diff --git a/modules/bar/components/workspaces/OccupiedBg.qml b/modules/bar/components/workspaces/OccupiedBg.qml index 0ed1831f..3f087160 100644 --- a/modules/bar/components/workspaces/OccupiedBg.qml +++ b/modules/bar/components/workspaces/OccupiedBg.qml @@ -90,14 +90,14 @@ Item { } } - component Pill: QtObject { - property int start - property int end - } - Component { id: pillComp Pill {} } + + component Pill: QtObject { + property int start + property int end + } } diff --git a/modules/bar/components/workspaces/SpecialWorkspaces.qml b/modules/bar/components/workspaces/SpecialWorkspaces.qml index e62ed719..cef8a990 100644 --- a/modules/bar/components/workspaces/SpecialWorkspaces.qml +++ b/modules/bar/components/workspaces/SpecialWorkspaces.qml @@ -159,6 +159,76 @@ Item { } } + Loader { + asynchronous: true + active: Config.bar.workspaces.activeIndicator + anchors.fill: parent + + sourceComponent: Item { + StyledClippingRect { + id: indicator + + anchors.left: parent.left + anchors.right: parent.right + + y: (view.currentItem?.y ?? 0) - view.contentY + implicitHeight: (view.currentItem as SpecialWsDelegate)?.size ?? 0 + + color: Colours.palette.m3tertiary + radius: Appearance.rounding.full + + Colouriser { + source: view + sourceColor: Colours.palette.m3onSurface + colorizationColor: Colours.palette.m3onTertiary + + anchors.horizontalCenter: parent.horizontalCenter + + x: 0 + y: -indicator.y + implicitWidth: view.width + implicitHeight: view.height + } + + Behavior on y { + Anim { + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } + + Behavior on implicitHeight { + Anim { + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } + } + } + } + + MouseArea { + property real startY + + anchors.fill: view + + drag.target: view.contentItem + drag.axis: Drag.YAxis + drag.maximumY: 0 + drag.minimumY: Math.min(0, view.height - view.contentHeight - Appearance.padding.small) + + onPressed: event => startY = event.y + + onClicked: event => { + if (Math.abs(event.y - startY) > drag.threshold) + return; + + const ws = view.itemAt(event.x, event.y) as SpecialWsDelegate; + if (ws?.modelData) + Hypr.dispatch(`togglespecialworkspace ${ws.modelData.name.slice(8)}`); + else + Hypr.dispatch("togglespecialworkspace special"); + } + } + component SpecialWsDelegate: ColumnLayout { id: ws @@ -297,74 +367,4 @@ Item { } } } - - Loader { - asynchronous: true - active: Config.bar.workspaces.activeIndicator - anchors.fill: parent - - sourceComponent: Item { - StyledClippingRect { - id: indicator - - anchors.left: parent.left - anchors.right: parent.right - - y: (view.currentItem?.y ?? 0) - view.contentY - implicitHeight: (view.currentItem as SpecialWsDelegate)?.size ?? 0 - - color: Colours.palette.m3tertiary - radius: Appearance.rounding.full - - Colouriser { - source: view - sourceColor: Colours.palette.m3onSurface - colorizationColor: Colours.palette.m3onTertiary - - anchors.horizontalCenter: parent.horizontalCenter - - x: 0 - y: -indicator.y - implicitWidth: view.width - implicitHeight: view.height - } - - Behavior on y { - Anim { - easing.bezierCurve: Appearance.anim.curves.emphasized - } - } - - Behavior on implicitHeight { - Anim { - easing.bezierCurve: Appearance.anim.curves.emphasized - } - } - } - } - } - - MouseArea { - property real startY - - anchors.fill: view - - drag.target: view.contentItem - drag.axis: Drag.YAxis - drag.maximumY: 0 - drag.minimumY: Math.min(0, view.height - view.contentHeight - Appearance.padding.small) - - onPressed: event => startY = event.y - - onClicked: event => { - if (Math.abs(event.y - startY) > drag.threshold) - return; - - const ws = view.itemAt(event.x, event.y) as SpecialWsDelegate; - if (ws?.modelData) - Hypr.dispatch(`togglespecialworkspace ${ws.modelData.name.slice(8)}`); - else - Hypr.dispatch("togglespecialworkspace special"); - } - } } diff --git a/modules/bar/popouts/TrayMenu.qml b/modules/bar/popouts/TrayMenu.qml index 50bd60a5..4347e39e 100644 --- a/modules/bar/popouts/TrayMenu.qml +++ b/modules/bar/popouts/TrayMenu.qml @@ -26,6 +26,12 @@ StackView { popEnter: NoAnim {} popExit: NoAnim {} + Component { + id: subMenuComp + + SubMenu {} + } + component NoAnim: Transition { NumberAnimation { duration: 0 @@ -221,10 +227,4 @@ StackView { } } } - - Component { - id: subMenuComp - - SubMenu {} - } } diff --git a/modules/bar/popouts/WirelessPassword.qml b/modules/bar/popouts/WirelessPassword.qml index 4d439cc5..e80e9148 100644 --- a/modules/bar/popouts/WirelessPassword.qml +++ b/modules/bar/popouts/WirelessPassword.qml @@ -267,6 +267,13 @@ ColumnLayout { focus: true activeFocusOnTab: true + Component.onCompleted: { + if (root.shouldBeVisible) { + // Use Timer for actual delay to ensure focus works correctly + passwordFocusTimer.start(); + } + } + Keys.onPressed: event => { // Ensure we have focus when receiving keyboard input if (!activeFocus) { @@ -318,13 +325,6 @@ ColumnLayout { } } - Component.onCompleted: { - if (root.shouldBeVisible) { - // Use Timer for actual delay to ensure focus works correctly - passwordFocusTimer.start(); - } - } - StyledRect { anchors.fill: parent radius: Appearance.rounding.normal diff --git a/modules/bar/popouts/kblayout/KbLayoutModel.qml b/modules/bar/popouts/kblayout/KbLayoutModel.qml index 65c809b3..4caebbd2 100644 --- a/modules/bar/popouts/kblayout/KbLayoutModel.qml +++ b/modules/bar/popouts/kblayout/KbLayoutModel.qml @@ -10,17 +10,11 @@ import qs.config Item { id: model - visible: false - - ListModel { - id: _visibleModel - } - property alias visibleModel: _visibleModel - property string activeLabel: "" - property int activeIndex: -1 + property var _xkbMap: ({}) + property bool _notifiedLimit: false function start() { _xkbXmlBase.running = true; @@ -127,14 +121,16 @@ Item { return code.toUpperCase() + " - " + code; } + visible: false + + ListModel { + id: _visibleModel + } + ListModel { id: _layoutsModel } - property var _xkbMap: ({}) - - property bool _notifiedLimit: false - Process { id: _xkbXmlBase diff --git a/modules/controlcenter/appearance/sections/ColorSchemeSection.qml b/modules/controlcenter/appearance/sections/ColorSchemeSection.qml index 0e96de70..b954cd45 100644 --- a/modules/controlcenter/appearance/sections/ColorSchemeSection.qml +++ b/modules/controlcenter/appearance/sections/ColorSchemeSection.qml @@ -35,6 +35,7 @@ CollapsibleSection { radius: Appearance.rounding.normal border.width: isCurrent ? 1 : 0 border.color: Colours.palette.m3primary + implicitHeight: schemeRow.implicitHeight + Appearance.padding.normal * 2 StateLayer { function onClicked(): void { @@ -140,8 +141,6 @@ CollapsibleSection { } } } - - implicitHeight: schemeRow.implicitHeight + Appearance.padding.normal * 2 } } } diff --git a/modules/controlcenter/appearance/sections/ColorVariantSection.qml b/modules/controlcenter/appearance/sections/ColorVariantSection.qml index 0977c2bb..b3cc4cfb 100644 --- a/modules/controlcenter/appearance/sections/ColorVariantSection.qml +++ b/modules/controlcenter/appearance/sections/ColorVariantSection.qml @@ -32,6 +32,7 @@ CollapsibleSection { radius: Appearance.rounding.normal border.width: modelData.variant === Schemes.currentVariant ? 1 : 0 border.color: Colours.palette.m3primary + implicitHeight: variantRow.implicitHeight + Appearance.padding.normal * 2 StateLayer { function onClicked(): void { @@ -84,8 +85,6 @@ CollapsibleSection { font.pointSize: Appearance.font.size.large } } - - implicitHeight: variantRow.implicitHeight + Appearance.padding.normal * 2 } } } diff --git a/modules/controlcenter/appearance/sections/FontsSection.qml b/modules/controlcenter/appearance/sections/FontsSection.qml index dc42f3b9..47b738f1 100644 --- a/modules/controlcenter/appearance/sections/FontsSection.qml +++ b/modules/controlcenter/appearance/sections/FontsSection.qml @@ -55,6 +55,7 @@ CollapsibleSection { radius: Appearance.rounding.normal border.width: isCurrent ? 1 : 0 border.color: Colours.palette.m3primary + implicitHeight: fontFamilySansRow.implicitHeight + Appearance.padding.normal * 2 StateLayer { function onClicked(): void { @@ -93,8 +94,6 @@ CollapsibleSection { } } } - - implicitHeight: fontFamilySansRow.implicitHeight + Appearance.padding.normal * 2 } } } @@ -137,6 +136,7 @@ CollapsibleSection { radius: Appearance.rounding.normal border.width: isCurrent ? 1 : 0 border.color: Colours.palette.m3primary + implicitHeight: fontFamilyMonoRow.implicitHeight + Appearance.padding.normal * 2 StateLayer { function onClicked(): void { @@ -175,8 +175,6 @@ CollapsibleSection { } } } - - implicitHeight: fontFamilyMonoRow.implicitHeight + Appearance.padding.normal * 2 } } } @@ -221,6 +219,7 @@ CollapsibleSection { radius: Appearance.rounding.normal border.width: isCurrent ? 1 : 0 border.color: Colours.palette.m3primary + implicitHeight: fontFamilyMaterialRow.implicitHeight + Appearance.padding.normal * 2 StateLayer { function onClicked(): void { @@ -259,8 +258,6 @@ CollapsibleSection { } } } - - implicitHeight: fontFamilyMaterialRow.implicitHeight + Appearance.padding.normal * 2 } } } diff --git a/modules/controlcenter/audio/AudioPane.qml b/modules/controlcenter/audio/AudioPane.qml index fe03d8b3..172132f6 100644 --- a/modules/controlcenter/audio/AudioPane.qml +++ b/modules/controlcenter/audio/AudioPane.qml @@ -94,6 +94,7 @@ Item { color: Audio.sink?.id === modelData.id ? Colours.layer(Colours.palette.m3surfaceContainer, 2) : "transparent" radius: Appearance.rounding.normal + implicitHeight: outputRowLayout.implicitHeight + Appearance.padding.normal * 2 StateLayer { function onClicked(): void { @@ -126,8 +127,6 @@ Item { font.weight: Audio.sink?.id === modelData.id ? 500 : 400 } } - - implicitHeight: outputRowLayout.implicitHeight + Appearance.padding.normal * 2 } } } @@ -172,6 +171,7 @@ Item { color: Audio.source?.id === modelData.id ? Colours.layer(Colours.palette.m3surfaceContainer, 2) : "transparent" radius: Appearance.rounding.normal + implicitHeight: inputRowLayout.implicitHeight + Appearance.padding.normal * 2 StateLayer { function onClicked(): void { @@ -204,8 +204,6 @@ Item { font.weight: Audio.source?.id === modelData.id ? 500 : 400 } } - - implicitHeight: inputRowLayout.implicitHeight + Appearance.padding.normal * 2 } } } @@ -278,16 +276,6 @@ Item { text = Math.round(Audio.volume * 100).toString(); } - Connections { - function onVolumeChanged() { - if (!outputVolumeInput.hasFocus) { - outputVolumeInput.text = Math.round(Audio.volume * 100).toString(); - } - } - - target: Audio - } - onTextEdited: text => { if (hasFocus) { const val = parseInt(text); @@ -303,6 +291,16 @@ Item { text = Math.round(Audio.volume * 100).toString(); } } + + Connections { + function onVolumeChanged() { + if (!outputVolumeInput.hasFocus) { + outputVolumeInput.text = Math.round(Audio.volume * 100).toString(); + } + } + + target: Audio + } } StyledText { @@ -396,16 +394,6 @@ Item { text = Math.round(Audio.sourceVolume * 100).toString(); } - Connections { - function onSourceVolumeChanged() { - if (!inputVolumeInput.hasFocus) { - inputVolumeInput.text = Math.round(Audio.sourceVolume * 100).toString(); - } - } - - target: Audio - } - onTextEdited: text => { if (hasFocus) { const val = parseInt(text); @@ -421,6 +409,16 @@ Item { text = Math.round(Audio.sourceVolume * 100).toString(); } } + + Connections { + function onSourceVolumeChanged() { + if (!inputVolumeInput.hasFocus) { + inputVolumeInput.text = Math.round(Audio.sourceVolume * 100).toString(); + } + } + + target: Audio + } } StyledText { @@ -530,16 +528,6 @@ Item { text = Math.round(Audio.getStreamVolume(modelData) * 100).toString(); } - Connections { - function onAudioChanged() { - if (!streamVolumeInput.hasFocus && modelData?.audio) { - streamVolumeInput.text = Math.round(modelData.audio.volume * 100).toString(); - } - } - - target: modelData - } - onTextEdited: text => { if (hasFocus) { const val = parseInt(text); @@ -555,6 +543,16 @@ Item { text = Math.round(Audio.getStreamVolume(modelData) * 100).toString(); } } + + Connections { + function onAudioChanged() { + if (!streamVolumeInput.hasFocus && modelData?.audio) { + streamVolumeInput.text = Math.round(modelData.audio.volume * 100).toString(); + } + } + + target: modelData + } } StyledText { diff --git a/modules/controlcenter/components/DeviceList.qml b/modules/controlcenter/components/DeviceList.qml index f121eefe..2134d8cf 100644 --- a/modules/controlcenter/components/DeviceList.qml +++ b/modules/controlcenter/components/DeviceList.qml @@ -23,6 +23,7 @@ ColumnLayout { property Component headerComponent: null property Component titleSuffix: null property bool showHeader: true + property alias view: view signal itemSelected(var item) @@ -61,8 +62,6 @@ ColumnLayout { } } - property alias view: view - StyledText { visible: root.description !== "" Layout.fillWidth: true diff --git a/modules/controlcenter/components/SliderInput.qml b/modules/controlcenter/components/SliderInput.qml index d677fc30..df3acf41 100644 --- a/modules/controlcenter/components/SliderInput.qml +++ b/modules/controlcenter/components/SliderInput.qml @@ -152,14 +152,6 @@ ColumnLayout { to: root.to stepSize: root.stepSize - // Use Binding to allow slider to move freely during dragging - Binding { - target: slider - property: "value" - value: root.value - when: !slider.pressed - } - onValueChanged: { // Update input field text in real-time as slider moves during dragging // Always update when slider value changes (during dragging or external updates) @@ -176,5 +168,13 @@ ColumnLayout { inputField.text = root.formatValue(newValue); } } + + // Use Binding to allow slider to move freely during dragging + Binding { + target: slider + property: "value" + value: root.value + when: !slider.pressed + } } } diff --git a/modules/controlcenter/components/SplitPaneWithDetails.qml b/modules/controlcenter/components/SplitPaneWithDetails.qml index 92d9c2c8..e8dcb269 100644 --- a/modules/controlcenter/components/SplitPaneWithDetails.qml +++ b/modules/controlcenter/components/SplitPaneWithDetails.qml @@ -48,6 +48,11 @@ Item { nextComponent = targetComponent; } + onPaneChanged: { + nextComponent = getComponentForPane(); + paneId = root.paneIdGenerator(pane); + } + Loader { id: rightLoader @@ -74,11 +79,6 @@ Item { ] } } - - onPaneChanged: { - nextComponent = getComponentForPane(); - paneId = root.paneIdGenerator(pane); - } } } } diff --git a/modules/controlcenter/components/WallpaperGrid.qml b/modules/controlcenter/components/WallpaperGrid.qml index 674886a7..6a65c8e1 100644 --- a/modules/controlcenter/components/WallpaperGrid.qml +++ b/modules/controlcenter/components/WallpaperGrid.qml @@ -154,16 +154,16 @@ GridView { opacity: 0 + Component.onCompleted: { + opacity = 1; + } + Behavior on opacity { NumberAnimation { duration: 1000 easing.type: Easing.OutCubic } } - - Component.onCompleted: { - opacity = 1; - } } } @@ -219,16 +219,16 @@ GridView { opacity: 0 + Component.onCompleted: { + opacity = 1; + } + Behavior on opacity { NumberAnimation { duration: 1000 easing.type: Easing.OutCubic } } - - Component.onCompleted: { - opacity = 1; - } } } } diff --git a/modules/controlcenter/launcher/LauncherPane.qml b/modules/controlcenter/launcher/LauncherPane.qml index 4703cace..677cf418 100644 --- a/modules/controlcenter/launcher/LauncherPane.qml +++ b/modules/controlcenter/launcher/LauncherPane.qml @@ -317,6 +317,10 @@ Item { opacity: 0 + Component.onCompleted: { + opacity = 1; + } + Behavior on opacity { NumberAnimation { duration: 1000 @@ -324,10 +328,6 @@ Item { } } - Component.onCompleted: { - opacity = 1; - } - StateLayer { function onClicked(): void { root.session.launcher.active = modelData; diff --git a/modules/controlcenter/network/VpnList.qml b/modules/controlcenter/network/VpnList.qml index 7f0bf3b1..3646841c 100644 --- a/modules/controlcenter/network/VpnList.qml +++ b/modules/controlcenter/network/VpnList.qml @@ -98,6 +98,7 @@ ColumnLayout { required property int index width: ListView.view ? ListView.view.width : undefined + implicitHeight: rowLayout.implicitHeight + Appearance.padding.normal * 2 color: Qt.alpha(Colours.tPalette.m3surfaceContainer, (root.session && root.session.vpn && root.session.vpn.active === modelData) ? Colours.tPalette.m3surfaceContainer.a : 0) radius: Appearance.rounding.normal @@ -258,8 +259,6 @@ ColumnLayout { } } } - - implicitHeight: rowLayout.implicitHeight + Appearance.padding.normal * 2 } } } diff --git a/modules/controlcenter/network/VpnSettings.qml b/modules/controlcenter/network/VpnSettings.qml index d335b658..ae689050 100644 --- a/modules/controlcenter/network/VpnSettings.qml +++ b/modules/controlcenter/network/VpnSettings.qml @@ -82,6 +82,7 @@ ColumnLayout { required property int index width: ListView.view ? ListView.view.width : undefined + implicitHeight: 60 color: Colours.tPalette.m3surfaceContainerHigh radius: Appearance.rounding.normal @@ -147,8 +148,6 @@ ColumnLayout { } } } - - implicitHeight: 60 } } } diff --git a/modules/controlcenter/network/WirelessList.qml b/modules/controlcenter/network/WirelessList.qml index b1738f76..bff142d3 100644 --- a/modules/controlcenter/network/WirelessList.qml +++ b/modules/controlcenter/network/WirelessList.qml @@ -110,6 +110,7 @@ DeviceList { required property var modelData width: ListView.view ? ListView.view.width : undefined + implicitHeight: rowLayout.implicitHeight + Appearance.padding.normal * 2 color: Qt.alpha(Colours.tPalette.m3surfaceContainer, root.activeItem === modelData ? Colours.tPalette.m3surfaceContainer.a : 0) radius: Appearance.rounding.normal @@ -214,8 +215,6 @@ DeviceList { } } } - - implicitHeight: rowLayout.implicitHeight + Appearance.padding.normal * 2 } } diff --git a/modules/controlcenter/network/WirelessPasswordDialog.qml b/modules/controlcenter/network/WirelessPasswordDialog.qml index 0c2cb714..40711730 100644 --- a/modules/controlcenter/network/WirelessPasswordDialog.qml +++ b/modules/controlcenter/network/WirelessPasswordDialog.qml @@ -105,6 +105,7 @@ Item { color: Colours.tPalette.m3surface opacity: root.session.network.showPasswordDialog && !root.isClosing ? 1 : 0 scale: root.session.network.showPasswordDialog && !root.isClosing ? 1 : 0.7 + Keys.onEscapePressed: closeDialog() Behavior on opacity { Anim {} @@ -135,8 +136,6 @@ Item { } } - Keys.onEscapePressed: closeDialog() - ColumnLayout { id: content diff --git a/services/LyricsService.qml b/services/LyricsService.qml index f96dde91..53be9f90 100644 --- a/services/LyricsService.qml +++ b/services/LyricsService.qml @@ -38,96 +38,6 @@ Singleton { "Referer": "https://music.163.com/" }) - ListModel { - id: lyricsModel - } - ListModel { - id: fetchedCandidatesModel - } - - Timer { - id: seekTimer - - interval: 500 - onTriggered: root.isManualSeeking = false - } - - // If no local lyrics were loaded within the interval, fall back to NetEase - Timer { - id: fallbackTimer - - interval: 200 - onTriggered: { - if (lyricsModel.count === 0) { - root.backend = "NetEase"; - fallbackToOnline(); - } - } - } - - Timer { - id: loadDebounce - - interval: 50 - onTriggered: root._doLoadLyrics() - } - - FileView { - id: lyricsMapFileView - - path: root.lyricsMapFile - printErrors: false - onLoaded: { - try { - root.lyricsMap = JSON.parse(text()); - } catch (e) { - root.lyricsMap = {}; - } - } - } - - FileView { - id: lrcFile - - printErrors: false - onLoaded: { - fallbackTimer.stop(); - let parsed = Lrc.parseLrc(text()); - if (parsed.length > 0) { - root.backend = "Local"; - updateModel(parsed); - loading = false; - } else { - root.backend = "NetEase"; - fallbackToOnline(); - } - } - } - - Connections { - function onActiveChanged() { - root.player = Players.active; - loadLyrics(); - } - - target: Players - } - - Connections { - function onMetadataChanged() { - loadLyrics(); - } - - target: root.player - ignoreUnknownSignals: true - } - - Process { - id: saveLyricsMap - - command: ["sh", "-c", `mkdir -p "${root.lyricsDir}" && echo '${JSON.stringify(root.lyricsMap)}' > "${root.lyricsMapFile}"`] - } - function getMetadata() { if (!player || !player.metadata) return null; @@ -345,4 +255,95 @@ Singleton { seekTimer.restart(); } + + ListModel { + id: lyricsModel + } + + ListModel { + id: fetchedCandidatesModel + } + + Timer { + id: seekTimer + + interval: 500 + onTriggered: root.isManualSeeking = false + } + + // If no local lyrics were loaded within the interval, fall back to NetEase + Timer { + id: fallbackTimer + + interval: 200 + onTriggered: { + if (lyricsModel.count === 0) { + root.backend = "NetEase"; + fallbackToOnline(); + } + } + } + + Timer { + id: loadDebounce + + interval: 50 + onTriggered: root._doLoadLyrics() + } + + FileView { + id: lyricsMapFileView + + path: root.lyricsMapFile + printErrors: false + onLoaded: { + try { + root.lyricsMap = JSON.parse(text()); + } catch (e) { + root.lyricsMap = {}; + } + } + } + + FileView { + id: lrcFile + + printErrors: false + onLoaded: { + fallbackTimer.stop(); + let parsed = Lrc.parseLrc(text()); + if (parsed.length > 0) { + root.backend = "Local"; + updateModel(parsed); + loading = false; + } else { + root.backend = "NetEase"; + fallbackToOnline(); + } + } + } + + Connections { + function onActiveChanged() { + root.player = Players.active; + loadLyrics(); + } + + target: Players + } + + Connections { + function onMetadataChanged() { + loadLyrics(); + } + + target: root.player + ignoreUnknownSignals: true + } + + Process { + id: saveLyricsMap + + command: ["sh", "-c", `mkdir -p "${root.lyricsDir}" && echo '${JSON.stringify(root.lyricsMap)}' > "${root.lyricsMapFile}"`] + } } diff --git a/services/Network.qml b/services/Network.qml index cef0def8..4e0b809c 100644 --- a/services/Network.qml +++ b/services/Network.qml @@ -313,6 +313,12 @@ Singleton { } } + Component { + id: apComp + + AccessPoint {} + } + component AccessPoint: QtObject { required property var lastIpcObject readonly property string ssid: lastIpcObject.ssid @@ -323,10 +329,4 @@ Singleton { readonly property string security: lastIpcObject.security readonly property bool isSecure: security.length > 0 } - - Component { - id: apComp - - AccessPoint {} - } } diff --git a/services/Nmcli.qml b/services/Nmcli.qml index c3c05360..7af9513b 100644 --- a/services/Nmcli.qml +++ b/services/Nmcli.qml @@ -872,78 +872,222 @@ Singleton { return false; } - component CommandProcess: Process { - id: proc + function checkPendingConnection(): void { + if (root.pendingConnection) { + Qt.callLater(() => { + const connected = root.active && root.active.ssid === root.pendingConnection.ssid; + if (connected) { + connectionCheckTimer.stop(); + immediateCheckTimer.stop(); + immediateCheckTimer.checkCount = 0; + if (root.pendingConnection.callback) { + root.pendingConnection.callback({ + success: true, + output: "Connected", + error: "", + exitCode: 0 + }); + } + root.pendingConnection = null; + } else { + if (!immediateCheckTimer.running) { + immediateCheckTimer.start(); + } + } + }); + } + } - property var callback: null - property list command: [] - property bool callbackCalled: false - property int exitCode: 0 - - signal processFinished - - environment: ({ - LANG: "C.UTF-8", - LC_ALL: "C.UTF-8" - }) - - stdout: StdioCollector { - id: stdoutCollector + function cidrToSubnetMask(cidr: string): string { + const cidrNum = parseInt(cidr, 10); + if (isNaN(cidrNum) || cidrNum < 0 || cidrNum > 32) { + return ""; } - stderr: StdioCollector { - id: stderrCollector + const mask = (0xffffffff << (32 - cidrNum)) >>> 0; + const octet1 = (mask >>> 24) & 0xff; + const octet2 = (mask >>> 16) & 0xff; + const octet3 = (mask >>> 8) & 0xff; + const octet4 = mask & 0xff; - onStreamFinished: { - const error = text.trim(); - if (error && error.length > 0) { - const output = (stdoutCollector && stdoutCollector.text) ? stdoutCollector.text : ""; - root.handlePasswordRequired(proc, error, output, -1); + return `${octet1}.${octet2}.${octet3}.${octet4}`; + } + + function getWirelessDeviceDetails(interfaceName: string, callback: var): void { + if (!interfaceName || interfaceName.length === 0) { + const activeInterface = root.wirelessInterfaces.find(iface => { + return isConnectedState(iface.state); + }); + if (activeInterface && activeInterface.device) { + interfaceName = activeInterface.device; + } else { + if (callback) + callback(null); + return; + } + } + + executeCommand(["device", "show", interfaceName], result => { + if (!result.success || !result.output) { + root.wirelessDeviceDetails = null; + if (callback) + callback(null); + return; + } + + const details = parseDeviceDetails(result.output, false); + root.wirelessDeviceDetails = details; + if (callback) + callback(details); + }); + } + + function getEthernetDeviceDetails(interfaceName: string, callback: var): void { + if (!interfaceName || interfaceName.length === 0) { + const activeInterface = root.ethernetInterfaces.find(iface => { + return isConnectedState(iface.state); + }); + if (activeInterface && activeInterface.device) { + interfaceName = activeInterface.device; + } else { + if (callback) + callback(null); + return; + } + } + + executeCommand(["device", "show", interfaceName], result => { + if (!result.success || !result.output) { + root.ethernetDeviceDetails = null; + if (callback) + callback(null); + return; + } + + const details = parseDeviceDetails(result.output, true); + root.ethernetDeviceDetails = details; + if (callback) + callback(details); + }); + } + + function parseDeviceDetails(output: string, isEthernet: bool): var { + const details = { + ipAddress: "", + gateway: "", + dns: [], + subnet: "", + macAddress: "", + speed: "" + }; + + if (!output || output.length === 0) { + return details; + } + + const lines = output.trim().split("\n"); + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + const parts = line.split(":"); + if (parts.length >= 2) { + const key = parts[0].trim(); + const value = parts.slice(1).join(":").trim(); + + if (key.startsWith("IP4.ADDRESS")) { + const ipParts = value.split("/"); + details.ipAddress = ipParts[0] || ""; + if (ipParts[1]) { + details.subnet = cidrToSubnetMask(ipParts[1]); + } else { + details.subnet = ""; + } + } else if (key === "IP4.GATEWAY") { + if (value !== "--") { + details.gateway = value; + } + } else if (key.startsWith("IP4.DNS")) { + if (value !== "--" && value.length > 0) { + details.dns.push(value); + } + } else if (isEthernet && key === "WIRED-PROPERTIES.MAC") { + details.macAddress = value; + } else if (isEthernet && key === "WIRED-PROPERTIES.SPEED") { + details.speed = value; + } else if (!isEthernet && key === "GENERAL.HWADDR") { + details.macAddress = value; } } } - onExited: code => { // qmllint disable signal-handler-parameters - exitCode = code; + return details; + } - Qt.callLater(() => { - if (callbackCalled) { - processFinished(); - return; - } + function refreshOnConnectionChange(): void { + getNetworks(networks => { + const newActive = root.active; - if (proc.callback) { - const output = (stdoutCollector && stdoutCollector.text) ? stdoutCollector.text : ""; - const error = (stderrCollector && stderrCollector.text) ? stderrCollector.text : ""; - const success = exitCode === 0; - const cmdIsConnection = isConnectionCommand(proc.command); - - if (root.handlePasswordRequired(proc, error, output, exitCode)) { - processFinished(); - return; + if (newActive && newActive.active) { + Qt.callLater(() => { + if (root.wirelessInterfaces.length > 0) { + const activeWireless = root.wirelessInterfaces.find(iface => { + return isConnectedState(iface.state); + }); + if (activeWireless && activeWireless.device) { + getWirelessDeviceDetails(activeWireless.device, () => {}); + } } - const needsPassword = cmdIsConnection && root.detectPasswordRequired(error); - - if (!success && cmdIsConnection && root.pendingConnection) { - const failedSsid = root.pendingConnection.ssid; - root.connectionFailed(failedSsid); + if (root.ethernetInterfaces.length > 0) { + const activeEthernet = root.ethernetInterfaces.find(iface => { + return isConnectedState(iface.state); + }); + if (activeEthernet && activeEthernet.device) { + getEthernetDeviceDetails(activeEthernet.device, () => {}); + } } + }, 500); + } else { + root.wirelessDeviceDetails = null; + root.ethernetDeviceDetails = null; + } - callbackCalled = true; - callback({ - success: success, - output: output, - error: error, - exitCode: proc.exitCode, - needsPassword: needsPassword || false - }); - processFinished(); - } else { - processFinished(); + getWirelessInterfaces(() => {}); + getEthernetInterfaces(() => { + if (root.activeEthernet && root.activeEthernet.connected) { + Qt.callLater(() => { + getEthernetDeviceDetails(root.activeEthernet.interface, () => {}); + }, 500); } }); - } + }); + } + + Component.onCompleted: { + getWifiStatus(() => {}); + getNetworks(() => {}); + loadSavedConnections(() => {}); + getEthernetInterfaces(() => {}); + + Qt.callLater(() => { + if (root.wirelessInterfaces.length > 0) { + const activeWireless = root.wirelessInterfaces.find(iface => { + return isConnectedState(iface.state); + }); + if (activeWireless && activeWireless.device) { + getWirelessDeviceDetails(activeWireless.device, () => {}); + } + } + + if (root.ethernetInterfaces.length > 0) { + const activeEthernet = root.ethernetInterfaces.find(iface => { + return isConnectedState(iface.state); + }); + if (activeEthernet && activeEthernet.device) { + getEthernetDeviceDetails(activeEthernet.device, () => {}); + } + } + }, 2000); } Component { @@ -952,17 +1096,6 @@ Singleton { CommandProcess {} } - component AccessPoint: QtObject { - required property var lastIpcObject - readonly property string ssid: lastIpcObject.ssid - readonly property string bssid: lastIpcObject.bssid - readonly property int strength: lastIpcObject.strength - readonly property int frequency: lastIpcObject.frequency - readonly property bool active: lastIpcObject.active - readonly property string security: lastIpcObject.security - readonly property bool isSecure: security.length > 0 - } - Component { id: apComp @@ -1113,157 +1246,6 @@ Singleton { } } - function checkPendingConnection(): void { - if (root.pendingConnection) { - Qt.callLater(() => { - const connected = root.active && root.active.ssid === root.pendingConnection.ssid; - if (connected) { - connectionCheckTimer.stop(); - immediateCheckTimer.stop(); - immediateCheckTimer.checkCount = 0; - if (root.pendingConnection.callback) { - root.pendingConnection.callback({ - success: true, - output: "Connected", - error: "", - exitCode: 0 - }); - } - root.pendingConnection = null; - } else { - if (!immediateCheckTimer.running) { - immediateCheckTimer.start(); - } - } - }); - } - } - - function cidrToSubnetMask(cidr: string): string { - const cidrNum = parseInt(cidr, 10); - if (isNaN(cidrNum) || cidrNum < 0 || cidrNum > 32) { - return ""; - } - - const mask = (0xffffffff << (32 - cidrNum)) >>> 0; - const octet1 = (mask >>> 24) & 0xff; - const octet2 = (mask >>> 16) & 0xff; - const octet3 = (mask >>> 8) & 0xff; - const octet4 = mask & 0xff; - - return `${octet1}.${octet2}.${octet3}.${octet4}`; - } - - function getWirelessDeviceDetails(interfaceName: string, callback: var): void { - if (!interfaceName || interfaceName.length === 0) { - const activeInterface = root.wirelessInterfaces.find(iface => { - return isConnectedState(iface.state); - }); - if (activeInterface && activeInterface.device) { - interfaceName = activeInterface.device; - } else { - if (callback) - callback(null); - return; - } - } - - executeCommand(["device", "show", interfaceName], result => { - if (!result.success || !result.output) { - root.wirelessDeviceDetails = null; - if (callback) - callback(null); - return; - } - - const details = parseDeviceDetails(result.output, false); - root.wirelessDeviceDetails = details; - if (callback) - callback(details); - }); - } - - function getEthernetDeviceDetails(interfaceName: string, callback: var): void { - if (!interfaceName || interfaceName.length === 0) { - const activeInterface = root.ethernetInterfaces.find(iface => { - return isConnectedState(iface.state); - }); - if (activeInterface && activeInterface.device) { - interfaceName = activeInterface.device; - } else { - if (callback) - callback(null); - return; - } - } - - executeCommand(["device", "show", interfaceName], result => { - if (!result.success || !result.output) { - root.ethernetDeviceDetails = null; - if (callback) - callback(null); - return; - } - - const details = parseDeviceDetails(result.output, true); - root.ethernetDeviceDetails = details; - if (callback) - callback(details); - }); - } - - function parseDeviceDetails(output: string, isEthernet: bool): var { - const details = { - ipAddress: "", - gateway: "", - dns: [], - subnet: "", - macAddress: "", - speed: "" - }; - - if (!output || output.length === 0) { - return details; - } - - const lines = output.trim().split("\n"); - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - const parts = line.split(":"); - if (parts.length >= 2) { - const key = parts[0].trim(); - const value = parts.slice(1).join(":").trim(); - - if (key.startsWith("IP4.ADDRESS")) { - const ipParts = value.split("/"); - details.ipAddress = ipParts[0] || ""; - if (ipParts[1]) { - details.subnet = cidrToSubnetMask(ipParts[1]); - } else { - details.subnet = ""; - } - } else if (key === "IP4.GATEWAY") { - if (value !== "--") { - details.gateway = value; - } - } else if (key.startsWith("IP4.DNS")) { - if (value !== "--" && value.length > 0) { - details.dns.push(value); - } - } else if (isEthernet && key === "WIRED-PROPERTIES.MAC") { - details.macAddress = value; - } else if (isEthernet && key === "WIRED-PROPERTIES.SPEED") { - details.speed = value; - } else if (!isEthernet && key === "GENERAL.HWADDR") { - details.macAddress = value; - } - } - } - - return details; - } - Process { id: rescanProc @@ -1295,70 +1277,88 @@ Singleton { } } - function refreshOnConnectionChange(): void { - getNetworks(networks => { - const newActive = root.active; + component CommandProcess: Process { + id: proc - if (newActive && newActive.active) { - Qt.callLater(() => { - if (root.wirelessInterfaces.length > 0) { - const activeWireless = root.wirelessInterfaces.find(iface => { - return isConnectedState(iface.state); - }); - if (activeWireless && activeWireless.device) { - getWirelessDeviceDetails(activeWireless.device, () => {}); - } - } + property var callback: null + property list command: [] + property bool callbackCalled: false + property int exitCode: 0 - if (root.ethernetInterfaces.length > 0) { - const activeEthernet = root.ethernetInterfaces.find(iface => { - return isConnectedState(iface.state); - }); - if (activeEthernet && activeEthernet.device) { - getEthernetDeviceDetails(activeEthernet.device, () => {}); - } - } - }, 500); - } else { - root.wirelessDeviceDetails = null; - root.ethernetDeviceDetails = null; + signal processFinished + + environment: ({ + LANG: "C.UTF-8", + LC_ALL: "C.UTF-8" + }) + + stdout: StdioCollector { + id: stdoutCollector + } + + stderr: StdioCollector { + id: stderrCollector + + onStreamFinished: { + const error = text.trim(); + if (error && error.length > 0) { + const output = (stdoutCollector && stdoutCollector.text) ? stdoutCollector.text : ""; + root.handlePasswordRequired(proc, error, output, -1); + } } + } - getWirelessInterfaces(() => {}); - getEthernetInterfaces(() => { - if (root.activeEthernet && root.activeEthernet.connected) { - Qt.callLater(() => { - getEthernetDeviceDetails(root.activeEthernet.interface, () => {}); - }, 500); + onExited: code => { // qmllint disable signal-handler-parameters + exitCode = code; + + Qt.callLater(() => { + if (callbackCalled) { + processFinished(); + return; + } + + if (proc.callback) { + const output = (stdoutCollector && stdoutCollector.text) ? stdoutCollector.text : ""; + const error = (stderrCollector && stderrCollector.text) ? stderrCollector.text : ""; + const success = exitCode === 0; + const cmdIsConnection = isConnectionCommand(proc.command); + + if (root.handlePasswordRequired(proc, error, output, exitCode)) { + processFinished(); + return; + } + + const needsPassword = cmdIsConnection && root.detectPasswordRequired(error); + + if (!success && cmdIsConnection && root.pendingConnection) { + const failedSsid = root.pendingConnection.ssid; + root.connectionFailed(failedSsid); + } + + callbackCalled = true; + callback({ + success: success, + output: output, + error: error, + exitCode: proc.exitCode, + needsPassword: needsPassword || false + }); + processFinished(); + } else { + processFinished(); } }); - }); + } } - Component.onCompleted: { - getWifiStatus(() => {}); - getNetworks(() => {}); - loadSavedConnections(() => {}); - getEthernetInterfaces(() => {}); - - Qt.callLater(() => { - if (root.wirelessInterfaces.length > 0) { - const activeWireless = root.wirelessInterfaces.find(iface => { - return isConnectedState(iface.state); - }); - if (activeWireless && activeWireless.device) { - getWirelessDeviceDetails(activeWireless.device, () => {}); - } - } - - if (root.ethernetInterfaces.length > 0) { - const activeEthernet = root.ethernetInterfaces.find(iface => { - return isConnectedState(iface.state); - }); - if (activeEthernet && activeEthernet.device) { - getEthernetDeviceDetails(activeEthernet.device, () => {}); - } - } - }, 2000); + component AccessPoint: QtObject { + required property var lastIpcObject + readonly property string ssid: lastIpcObject.ssid + readonly property string bssid: lastIpcObject.bssid + readonly property int strength: lastIpcObject.strength + readonly property int frequency: lastIpcObject.frequency + readonly property bool active: lastIpcObject.active + readonly property string security: lastIpcObject.security + readonly property bool isSecure: security.length > 0 } }