summaryrefslogtreecommitdiff
path: root/modules/controlcenter
diff options
context:
space:
mode:
authorATMDA <atdma2600@gmail.com>2025-11-19 19:51:28 -0500
committerATMDA <atdma2600@gmail.com>2025-11-19 19:51:28 -0500
commitff4e9bbdfd13077f94e1a30ac1dd7e7df2238438 (patch)
treefeb9c4e079a33f7d732f50f263b3428e3bf24182 /modules/controlcenter
parentrefactor: SplitPaneWithDetails integrated (diff)
downloadcaelestia-shell-ff4e9bbdfd13077f94e1a30ac1dd7e7df2238438.tar.gz
caelestia-shell-ff4e9bbdfd13077f94e1a30ac1dd7e7df2238438.tar.bz2
caelestia-shell-ff4e9bbdfd13077f94e1a30ac1dd7e7df2238438.zip
refactor: Updated Bluetooth, Ethernet, and Wireless lists to use DeviceList component and improved layout structure
Diffstat (limited to 'modules/controlcenter')
-rw-r--r--modules/controlcenter/bluetooth/BtPane.qml1
-rw-r--r--modules/controlcenter/bluetooth/DeviceList.qml293
-rw-r--r--modules/controlcenter/components/DeviceDetails.qml108
-rw-r--r--modules/controlcenter/components/DeviceList.qml125
-rw-r--r--modules/controlcenter/network/EthernetList.qml93
-rw-r--r--modules/controlcenter/network/WirelessList.qml152
6 files changed, 446 insertions, 326 deletions
diff --git a/modules/controlcenter/bluetooth/BtPane.qml b/modules/controlcenter/bluetooth/BtPane.qml
index 3cd6ef9..6877801 100644
--- a/modules/controlcenter/bluetooth/BtPane.qml
+++ b/modules/controlcenter/bluetooth/BtPane.qml
@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
import ".."
import "../components"
+import "."
import qs.components
import qs.components.controls
import qs.components.containers
diff --git a/modules/controlcenter/bluetooth/DeviceList.qml b/modules/controlcenter/bluetooth/DeviceList.qml
index 06700e8..b3db236 100644
--- a/modules/controlcenter/bluetooth/DeviceList.qml
+++ b/modules/controlcenter/bluetooth/DeviceList.qml
@@ -1,6 +1,7 @@
pragma ComponentBehavior: Bound
import ".."
+import "../components"
import qs.components
import qs.components.controls
import qs.components.containers
@@ -12,165 +13,144 @@ import Quickshell.Bluetooth
import QtQuick
import QtQuick.Layouts
-ColumnLayout {
+DeviceList {
id: root
required property Session session
readonly property bool smallDiscoverable: width <= 540
readonly property bool smallPairable: width <= 480
- spacing: Appearance.spacing.small
+ title: qsTr("Devices (%1)").arg(Bluetooth.devices.values.length)
+ description: qsTr("All available bluetooth devices")
+ activeItem: session.bt.active
- RowLayout {
- spacing: Appearance.spacing.smaller
+ model: ScriptModel {
+ id: deviceModel
- StyledText {
- text: qsTr("Bluetooth")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- ToggleButton {
- toggled: Bluetooth.defaultAdapter?.enabled ?? false
- icon: "power"
- accent: "Tertiary"
-
- function onClicked(): void {
- const adapter = Bluetooth.defaultAdapter;
- if (adapter)
- adapter.enabled = !adapter.enabled;
- }
- }
-
- ToggleButton {
- toggled: Bluetooth.defaultAdapter?.discoverable ?? false
- icon: root.smallDiscoverable ? "group_search" : ""
- label: root.smallDiscoverable ? "" : qsTr("Discoverable")
-
- function onClicked(): void {
- const adapter = Bluetooth.defaultAdapter;
- if (adapter)
- adapter.discoverable = !adapter.discoverable;
- }
- }
-
- ToggleButton {
- toggled: Bluetooth.defaultAdapter?.pairable ?? false
- icon: "missing_controller"
- label: root.smallPairable ? "" : qsTr("Pairable")
-
- function onClicked(): void {
- const adapter = Bluetooth.defaultAdapter;
- if (adapter)
- adapter.pairable = !adapter.pairable;
- }
- }
-
- ToggleButton {
- toggled: !root.session.bt.active
- icon: "settings"
- accent: "Primary"
-
- function onClicked(): void {
- if (root.session.bt.active)
- root.session.bt.active = null;
- else {
- root.session.bt.active = deviceModel.values[0] ?? null;
- }
- }
- }
+ values: [...Bluetooth.devices.values].sort((a, b) => (b.connected - a.connected) || (b.paired - a.paired))
}
- RowLayout {
- Layout.topMargin: Appearance.spacing.large
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
+ headerComponent: Component {
+ RowLayout {
+ spacing: Appearance.spacing.smaller
StyledText {
- Layout.fillWidth: true
- text: qsTr("Devices (%1)").arg(Bluetooth.devices.values.length)
- font.pointSize: Appearance.font.size.normal
+ text: qsTr("Bluetooth")
+ font.pointSize: Appearance.font.size.large
font.weight: 500
}
- StyledText {
+ Item {
Layout.fillWidth: true
- text: qsTr("All available bluetooth devices")
- color: Colours.palette.m3outline
}
- }
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: scanIcon.implicitHeight + Appearance.padding.normal * 2
+ ToggleButton {
+ toggled: Bluetooth.defaultAdapter?.enabled ?? false
+ icon: "power"
+ accent: "Tertiary"
- radius: Bluetooth.defaultAdapter?.discovering ? Appearance.rounding.normal : implicitHeight / 2 * Math.min(1, Appearance.rounding.scale)
- color: Bluetooth.defaultAdapter?.discovering ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
+ function onClicked(): void {
+ const adapter = Bluetooth.defaultAdapter;
+ if (adapter)
+ adapter.enabled = !adapter.enabled;
+ }
+ }
- StateLayer {
- color: Bluetooth.defaultAdapter?.discovering ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
+ ToggleButton {
+ toggled: Bluetooth.defaultAdapter?.discoverable ?? false
+ icon: root.smallDiscoverable ? "group_search" : ""
+ label: root.smallDiscoverable ? "" : qsTr("Discoverable")
function onClicked(): void {
const adapter = Bluetooth.defaultAdapter;
if (adapter)
- adapter.discovering = !adapter.discovering;
+ adapter.discoverable = !adapter.discoverable;
}
}
- MaterialIcon {
- id: scanIcon
+ ToggleButton {
+ toggled: Bluetooth.defaultAdapter?.pairable ?? false
+ icon: "missing_controller"
+ label: root.smallPairable ? "" : qsTr("Pairable")
- anchors.centerIn: parent
- animate: true
- text: "bluetooth_searching"
- color: Bluetooth.defaultAdapter?.discovering ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
- fill: Bluetooth.defaultAdapter?.discovering ? 1 : 0
+ function onClicked(): void {
+ const adapter = Bluetooth.defaultAdapter;
+ if (adapter)
+ adapter.pairable = !adapter.pairable;
+ }
}
- Behavior on radius {
- Anim {}
+ ToggleButton {
+ toggled: !root.session.bt.active
+ icon: "settings"
+ accent: "Primary"
+
+ function onClicked(): void {
+ if (root.session.bt.active)
+ root.session.bt.active = null;
+ else {
+ root.session.bt.active = root.model.values[0] ?? null;
+ }
+ }
}
}
}
- StyledListView {
- id: view
+ titleSuffix: Component {
+ RowLayout {
+ spacing: Appearance.spacing.normal
- model: ScriptModel {
- id: deviceModel
+ Item {
+ Layout.fillWidth: true
+ }
- values: [...Bluetooth.devices.values].sort((a, b) => (b.connected - a.connected) || (b.paired - a.paired))
- }
+ StyledRect {
+ implicitWidth: implicitHeight
+ implicitHeight: scanIcon.implicitHeight + Appearance.padding.normal * 2
- Layout.fillWidth: true
- Layout.fillHeight: true
- clip: true
- spacing: Appearance.spacing.small / 2
+ radius: Bluetooth.defaultAdapter?.discovering ? Appearance.rounding.normal : implicitHeight / 2 * Math.min(1, Appearance.rounding.scale)
+ color: Bluetooth.defaultAdapter?.discovering ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: view
+ StateLayer {
+ color: Bluetooth.defaultAdapter?.discovering ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
+
+ function onClicked(): void {
+ const adapter = Bluetooth.defaultAdapter;
+ if (adapter)
+ adapter.discovering = !adapter.discovering;
+ }
+ }
+
+ MaterialIcon {
+ id: scanIcon
+
+ anchors.centerIn: parent
+ animate: true
+ text: "bluetooth_searching"
+ color: Bluetooth.defaultAdapter?.discovering ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
+ fill: Bluetooth.defaultAdapter?.discovering ? 1 : 0
+ }
+
+ Behavior on radius {
+ Anim {}
+ }
+ }
}
+ }
- delegate: StyledRect {
+ delegate: Component {
+ StyledRect {
id: device
required property BluetoothDevice modelData
readonly property bool loading: modelData && (modelData.state === BluetoothDeviceState.Connecting || modelData.state === BluetoothDeviceState.Disconnecting)
readonly property bool connected: modelData && modelData.state === BluetoothDeviceState.Connected
- anchors.left: view.contentItem.left
- anchors.right: view.contentItem.right
+ anchors.left: parent.left
+ anchors.right: parent.right
implicitHeight: deviceInner.implicitHeight + Appearance.padding.normal * 2
- color: Qt.alpha(Colours.tPalette.m3surfaceContainer, root.session.bt.active === modelData ? Colours.tPalette.m3surfaceContainer.a : 0)
+ color: Qt.alpha(Colours.tPalette.m3surfaceContainer, root.activeItem === modelData ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Appearance.rounding.normal
StateLayer {
@@ -257,8 +237,18 @@ ColumnLayout {
disabled: device.loading
function onClicked(): void {
- if (device.modelData)
- device.modelData.connected = !device.modelData.connected;
+ if (device.loading)
+ return;
+
+ if (device.connected) {
+ device.modelData.connected = false;
+ } else {
+ if (device.modelData.bonded) {
+ device.modelData.connected = true;
+ } else {
+ device.modelData.pair();
+ }
+ }
}
}
@@ -267,7 +257,7 @@ ColumnLayout {
anchors.centerIn: parent
animate: true
- text: (device.modelData && device.modelData.connected) ? "link_off" : "link"
+ text: device.connected ? "link_off" : "link"
color: device.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
opacity: device.loading ? 0 : 1
@@ -281,78 +271,7 @@ ColumnLayout {
}
}
- component ToggleButton: StyledRect {
- id: toggleBtn
-
- required property bool toggled
- property string icon
- property string label
- property string accent: "Secondary"
-
- function onClicked(): void {
- }
-
- Layout.preferredWidth: implicitWidth + (toggleStateLayer.pressed ? Appearance.padding.normal * 2 : toggled ? Appearance.padding.small * 2 : 0)
- implicitWidth: toggleBtnInner.implicitWidth + Appearance.padding.large * 2
- implicitHeight: toggleBtnIcon.implicitHeight + Appearance.padding.normal * 2
-
- radius: toggled || toggleStateLayer.pressed ? Appearance.rounding.small : Math.min(width, height) / 2 * Math.min(1, Appearance.rounding.scale)
- color: toggled ? Colours.palette[`m3${accent.toLowerCase()}`] : Colours.palette[`m3${accent.toLowerCase()}Container`]
-
- StateLayer {
- id: toggleStateLayer
-
- color: toggleBtn.toggled ? Colours.palette[`m3on${toggleBtn.accent}`] : Colours.palette[`m3on${toggleBtn.accent}Container`]
-
- function onClicked(): void {
- toggleBtn.onClicked();
- }
- }
-
- RowLayout {
- id: toggleBtnInner
-
- anchors.centerIn: parent
- spacing: Appearance.spacing.normal
-
- MaterialIcon {
- id: toggleBtnIcon
-
- visible: !!text
- fill: toggleBtn.toggled ? 1 : 0
- text: toggleBtn.icon
- color: toggleBtn.toggled ? Colours.palette[`m3on${toggleBtn.accent}`] : Colours.palette[`m3on${toggleBtn.accent}Container`]
- font.pointSize: Appearance.font.size.large
-
- Behavior on fill {
- Anim {}
- }
- }
-
- Loader {
- asynchronous: true
- active: !!toggleBtn.label
- visible: active
-
- sourceComponent: StyledText {
- text: toggleBtn.label
- color: toggleBtn.toggled ? Colours.palette[`m3on${toggleBtn.accent}`] : Colours.palette[`m3on${toggleBtn.accent}Container`]
- }
- }
- }
-
- Behavior on radius {
- Anim {
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- }
-
- Behavior on Layout.preferredWidth {
- Anim {
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- }
+ onItemSelected: function(item) {
+ session.bt.active = item;
}
}
diff --git a/modules/controlcenter/components/DeviceDetails.qml b/modules/controlcenter/components/DeviceDetails.qml
new file mode 100644
index 0000000..256e689
--- /dev/null
+++ b/modules/controlcenter/components/DeviceDetails.qml
@@ -0,0 +1,108 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import qs.components
+import qs.components.controls
+import qs.components.effects
+import qs.components.containers
+import qs.config
+import QtQuick
+import QtQuick.Layouts
+
+/**
+ * DeviceDetails
+ *
+ * A reusable base component for displaying device/network details with a standardized
+ * structure. Provides a header, connection status section, and flexible sections for
+ * device-specific information.
+ *
+ * This component eliminates duplication across WirelessDetails, EthernetDetails, and Bluetooth Details
+ * by providing a common structure while allowing full customization of sections.
+ *
+ * Usage:
+ * ```qml
+ * DeviceDetails {
+ * session: root.session
+ * device: session.network.active
+ * headerComponent: Component {
+ * ConnectionHeader {
+ * icon: "wifi"
+ * title: device?.ssid ?? ""
+ * }
+ * }
+ * sections: [
+ * Component {
+ * // Connection status section
+ * },
+ * Component {
+ * // Properties section
+ * }
+ * ]
+ * }
+ * ```
+ */
+Item {
+ id: root
+
+ required property Session session
+ property var device: null
+
+ property Component headerComponent: null
+ property list<Component> sections: []
+
+ // Optional: Custom content to insert after header but before sections
+ property Component topContent: null
+
+ // Optional: Custom content to insert after all sections
+ property Component bottomContent: null
+
+ implicitWidth: layout.implicitWidth
+ implicitHeight: layout.implicitHeight
+
+ ColumnLayout {
+ id: layout
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+ spacing: Appearance.spacing.normal
+
+ // Header component (e.g., ConnectionHeader or SettingsHeader)
+ Loader {
+ id: headerLoader
+
+ Layout.fillWidth: true
+ sourceComponent: root.headerComponent
+ visible: root.headerComponent !== null
+ }
+
+ // Top content (optional)
+ Loader {
+ id: topContentLoader
+
+ Layout.fillWidth: true
+ sourceComponent: root.topContent
+ visible: root.topContent !== null
+ }
+
+ // Sections
+ Repeater {
+ model: root.sections
+
+ Loader {
+ Layout.fillWidth: true
+ sourceComponent: modelData
+ }
+ }
+
+ // Bottom content (optional)
+ Loader {
+ id: bottomContentLoader
+
+ Layout.fillWidth: true
+ sourceComponent: root.bottomContent
+ visible: root.bottomContent !== null
+ }
+ }
+}
+
diff --git a/modules/controlcenter/components/DeviceList.qml b/modules/controlcenter/components/DeviceList.qml
new file mode 100644
index 0000000..f8473ff
--- /dev/null
+++ b/modules/controlcenter/components/DeviceList.qml
@@ -0,0 +1,125 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import qs.components
+import qs.components.controls
+import qs.components.containers
+import qs.services
+import qs.config
+import QtQuick
+import QtQuick.Layouts
+
+/**
+ * DeviceList
+ *
+ * A reusable base component for displaying lists of devices/networks with a standardized
+ * structure. Provides a header with action buttons, title/subtitle, and a scrollable list
+ * with customizable delegates.
+ *
+ * This component eliminates duplication across WirelessList, EthernetList, and Bluetooth DeviceList
+ * by providing a common structure while allowing full customization of headers and delegates.
+ *
+ * Usage:
+ * ```qml
+ * DeviceList {
+ * session: root.session
+ * title: qsTr("Networks (%1)").arg(Nmcli.networks.length)
+ * description: qsTr("All available WiFi networks")
+ * model: ScriptModel {
+ * values: [...Nmcli.networks].sort(...)
+ * }
+ * activeItem: session.network.active
+ * onItemSelected: (item) => {
+ * session.network.active = item;
+ * }
+ * headerComponent: Component {
+ * RowLayout {
+ * // Custom header buttons
+ * }
+ * }
+ * delegate: Component {
+ * // Custom delegate for each item
+ * }
+ * }
+ * ```
+ */
+ColumnLayout {
+ id: root
+
+ property Session session: null
+ property var model: null
+ property Component delegate: null
+
+ property string title: ""
+ property string description: ""
+ property var activeItem: null
+ property Component headerComponent: null
+ property Component titleSuffix: null
+
+ signal itemSelected(var item)
+
+ spacing: Appearance.spacing.small
+
+ // Header with action buttons (optional)
+ Loader {
+ id: headerLoader
+
+ Layout.fillWidth: true
+ sourceComponent: root.headerComponent
+ visible: root.headerComponent !== null
+ }
+
+ // Title and description row
+ RowLayout {
+ Layout.fillWidth: true
+ Layout.topMargin: root.headerComponent ? 0 : 0
+ spacing: Appearance.spacing.small
+ visible: root.title !== "" || root.description !== ""
+
+ StyledText {
+ visible: root.title !== ""
+ text: root.title
+ font.pointSize: Appearance.font.size.large
+ font.weight: 500
+ }
+
+ Loader {
+ sourceComponent: root.titleSuffix
+ visible: root.titleSuffix !== null
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+ }
+
+ // Expose view for access from parent components
+ property alias view: view
+
+ // Description text
+ StyledText {
+ visible: root.description !== ""
+ Layout.fillWidth: true
+ text: root.description
+ color: Colours.palette.m3outline
+ }
+
+ // List view
+ StyledListView {
+ id: view
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ model: root.model
+ delegate: root.delegate
+
+ spacing: Appearance.spacing.small / 2
+ clip: true
+
+ StyledScrollBar.vertical: StyledScrollBar {
+ flickable: view
+ }
+ }
+}
+
diff --git a/modules/controlcenter/network/EthernetList.qml b/modules/controlcenter/network/EthernetList.qml
index 45c9481..03bd37e 100644
--- a/modules/controlcenter/network/EthernetList.qml
+++ b/modules/controlcenter/network/EthernetList.qml
@@ -1,6 +1,7 @@
pragma ComponentBehavior: Bound
import ".."
+import "../components"
import qs.components
import qs.components.controls
import qs.components.containers
@@ -9,81 +10,57 @@ import qs.config
import QtQuick
import QtQuick.Layouts
-ColumnLayout {
+DeviceList {
id: root
required property Session session
- spacing: Appearance.spacing.small
+ title: qsTr("Devices (%1)").arg(Nmcli.ethernetDevices.length)
+ description: qsTr("All available ethernet devices")
+ activeItem: session.ethernet.active
- RowLayout {
- spacing: Appearance.spacing.smaller
+ model: Nmcli.ethernetDevices
- StyledText {
- text: qsTr("Settings")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- Item {
- Layout.fillWidth: true
- }
+ headerComponent: Component {
+ RowLayout {
+ spacing: Appearance.spacing.smaller
- ToggleButton {
- toggled: !root.session.ethernet.active
- icon: "settings"
- accent: "Primary"
+ StyledText {
+ text: qsTr("Settings")
+ font.pointSize: Appearance.font.size.large
+ font.weight: 500
+ }
- onClicked: {
- if (root.session.ethernet.active)
- root.session.ethernet.active = null;
- else {
- root.session.ethernet.active = view.model.get(0)?.modelData ?? null;
- }
+ Item {
+ Layout.fillWidth: true
}
- }
- }
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
+ ToggleButton {
+ toggled: !root.session.ethernet.active
+ icon: "settings"
+ accent: "Primary"
- StyledText {
- text: qsTr("Devices (%1)").arg(Nmcli.ethernetDevices.length)
- font.pointSize: Appearance.font.size.large
- font.weight: 500
+ onClicked: {
+ if (root.session.ethernet.active)
+ root.session.ethernet.active = null;
+ else {
+ root.session.ethernet.active = root.view.model.get(0)?.modelData ?? null;
+ }
+ }
+ }
}
}
- StyledText {
- text: qsTr("All available ethernet devices")
- color: Colours.palette.m3outline
- }
-
- StyledListView {
- id: view
-
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- model: Nmcli.ethernetDevices
-
- spacing: Appearance.spacing.small / 2
- clip: true
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: view
- }
-
- delegate: StyledRect {
+ delegate: Component {
+ StyledRect {
required property var modelData
anchors.left: parent.left
anchors.right: parent.right
- color: Qt.alpha(Colours.tPalette.m3surfaceContainer, root.session.ethernet.active === modelData ? Colours.tPalette.m3surfaceContainer.a : 0)
+ color: Qt.alpha(Colours.tPalette.m3surfaceContainer, root.activeItem === modelData ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Appearance.rounding.normal
- border.width: root.session.ethernet.active === modelData ? 1 : 0
+ border.width: root.activeItem === modelData ? 1 : 0
border.color: Colours.palette.m3primary
StateLayer {
@@ -165,4 +142,8 @@ ColumnLayout {
implicitHeight: rowLayout.implicitHeight + Appearance.padding.normal * 2
}
}
-} \ No newline at end of file
+
+ onItemSelected: function(item) {
+ session.ethernet.active = item;
+ }
+}
diff --git a/modules/controlcenter/network/WirelessList.qml b/modules/controlcenter/network/WirelessList.qml
index 18f728c..2f0288f 100644
--- a/modules/controlcenter/network/WirelessList.qml
+++ b/modules/controlcenter/network/WirelessList.qml
@@ -1,6 +1,7 @@
pragma ComponentBehavior: Bound
import ".."
+import "../components"
import "."
import qs.components
import qs.components.controls
@@ -11,116 +12,94 @@ import qs.utils
import QtQuick
import QtQuick.Layouts
-ColumnLayout {
+DeviceList {
id: root
required property Session session
- spacing: Appearance.spacing.small
-
- RowLayout {
- spacing: Appearance.spacing.smaller
-
+ title: qsTr("Networks (%1)").arg(Nmcli.networks.length)
+ description: qsTr("All available WiFi networks")
+ activeItem: session.network.active
+
+ titleSuffix: Component {
StyledText {
- text: qsTr("Settings")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
+ visible: Nmcli.scanning
+ text: qsTr("Scanning...")
+ color: Colours.palette.m3primary
+ font.pointSize: Appearance.font.size.small
}
+ }
- Item {
- Layout.fillWidth: true
- }
+ model: ScriptModel {
+ values: [...Nmcli.networks].sort((a, b) => {
+ // Put active/connected network first
+ if (a.active !== b.active)
+ return b.active - a.active;
+ // Then sort by signal strength
+ return b.strength - a.strength;
+ })
+ }
- ToggleButton {
- toggled: Nmcli.wifiEnabled
- icon: "wifi"
- accent: "Tertiary"
+ headerComponent: Component {
+ RowLayout {
+ spacing: Appearance.spacing.smaller
- onClicked: {
- Nmcli.toggleWifi(null);
+ StyledText {
+ text: qsTr("Settings")
+ font.pointSize: Appearance.font.size.large
+ font.weight: 500
}
- }
- ToggleButton {
- toggled: Nmcli.scanning
- icon: "wifi_find"
- accent: "Secondary"
-
- onClicked: {
- Nmcli.rescanWifi();
+ Item {
+ Layout.fillWidth: true
}
- }
- ToggleButton {
- toggled: !root.session.network.active
- icon: "settings"
- accent: "Primary"
+ ToggleButton {
+ toggled: Nmcli.wifiEnabled
+ icon: "wifi"
+ accent: "Tertiary"
- onClicked: {
- if (root.session.network.active)
- root.session.network.active = null;
- else {
- root.session.network.active = view.model.get(0)?.modelData ?? null;
+ onClicked: {
+ Nmcli.toggleWifi(null);
}
}
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
- StyledText {
- text: qsTr("Networks (%1)").arg(Nmcli.networks.length)
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
+ ToggleButton {
+ toggled: Nmcli.scanning
+ icon: "wifi_find"
+ accent: "Secondary"
- StyledText {
- visible: Nmcli.scanning
- text: qsTr("Scanning...")
- color: Colours.palette.m3primary
- font.pointSize: Appearance.font.size.small
- }
- }
-
- StyledText {
- text: qsTr("All available WiFi networks")
- color: Colours.palette.m3outline
- }
-
- StyledListView {
- id: view
-
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- model: ScriptModel {
- values: [...Nmcli.networks].sort((a, b) => {
- // Put active/connected network first
- if (a.active !== b.active)
- return b.active - a.active;
- // Then sort by signal strength
- return b.strength - a.strength;
- })
- }
+ onClicked: {
+ Nmcli.rescanWifi();
+ }
+ }
- spacing: Appearance.spacing.small / 2
- clip: true
+ ToggleButton {
+ toggled: !root.session.network.active
+ icon: "settings"
+ accent: "Primary"
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: view
+ onClicked: {
+ if (root.session.network.active)
+ root.session.network.active = null;
+ else {
+ root.session.network.active = root.view.model.get(0)?.modelData ?? null;
+ }
+ }
+ }
}
+ }
- delegate: StyledRect {
+ delegate: Component {
+ StyledRect {
required property var modelData
anchors.left: parent.left
anchors.right: parent.right
- color: Qt.alpha(Colours.tPalette.m3surfaceContainer, root.session.network.active === modelData ? Colours.tPalette.m3surfaceContainer.a : 0)
+ color: Qt.alpha(Colours.tPalette.m3surfaceContainer, root.activeItem === modelData ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Appearance.rounding.normal
- border.width: root.session.network.active === modelData ? 1 : 0
+ border.width: root.activeItem === modelData ? 1 : 0
border.color: Colours.palette.m3primary
StateLayer {
@@ -213,9 +192,16 @@ ColumnLayout {
}
}
+ onItemSelected: function(item) {
+ session.network.active = item;
+ if (item && item.ssid) {
+ checkSavedProfileForNetwork(item.ssid);
+ }
+ }
+
function checkSavedProfileForNetwork(ssid: string): void {
if (ssid && ssid.length > 0) {
Nmcli.loadSavedConnections(() => {});
}
}
-} \ No newline at end of file
+}