diff options
Diffstat (limited to 'modules/controlcenter/components/DeviceList.qml')
| -rw-r--r-- | modules/controlcenter/components/DeviceList.qml | 125 |
1 files changed, 125 insertions, 0 deletions
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 + } + } +} + |