From ff4e9bbdfd13077f94e1a30ac1dd7e7df2238438 Mon Sep 17 00:00:00 2001 From: ATMDA Date: Wed, 19 Nov 2025 19:51:28 -0500 Subject: refactor: Updated Bluetooth, Ethernet, and Wireless lists to use DeviceList component and improved layout structure --- modules/controlcenter/components/DeviceList.qml | 125 ++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 modules/controlcenter/components/DeviceList.qml (limited to 'modules/controlcenter/components/DeviceList.qml') 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 + } + } +} + -- cgit v1.2.3-freya