nosignal-shell/modules/controlcenter/ethernet/EthernetList.qml
2025-11-10 11:51:43 -05:00

263 lines
7.9 KiB
QML

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
ColumnLayout {
id: root
required property Session session
spacing: Appearance.spacing.small
RowLayout {
spacing: Appearance.spacing.smaller
StyledText {
text: qsTr("Settings")
font.pointSize: Appearance.font.size.large
font.weight: 500
}
Item {
Layout.fillWidth: true
}
ToggleButton {
toggled: !root.session.ethernet.active
icon: "settings"
accent: "Primary"
function onClicked(): void {
if (root.session.ethernet.active)
root.session.ethernet.active = null;
else {
root.session.ethernet.active = view.model.get(0)?.modelData ?? null;
}
}
}
}
RowLayout {
Layout.fillWidth: true
spacing: Appearance.spacing.small
StyledText {
text: qsTr("Devices (%1)").arg(Network.ethernetDeviceCount || Network.ethernetDevices.length)
font.pointSize: Appearance.font.size.large
font.weight: 500
}
}
StyledText {
text: qsTr("All available ethernet devices")
color: Colours.palette.m3outline
}
StyledListView {
id: view
Layout.fillWidth: true
Layout.fillHeight: true
model: Network.ethernetDevices
spacing: Appearance.spacing.small / 2
clip: true
StyledScrollBar.vertical: StyledScrollBar {
flickable: view
}
delegate: 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)
radius: Appearance.rounding.normal
border.width: root.session.ethernet.active === modelData ? 1 : 0
border.color: Colours.palette.m3primary
StateLayer {
function onClicked(): void {
root.session.ethernet.active = modelData;
}
}
RowLayout {
id: rowLayout
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Appearance.padding.normal
spacing: Appearance.spacing.normal
StyledRect {
implicitWidth: implicitHeight
implicitHeight: icon.implicitHeight + Appearance.padding.normal * 2
radius: Appearance.rounding.normal
color: modelData.connected ? Colours.palette.m3primaryContainer : Colours.tPalette.m3surfaceContainerHigh
MaterialIcon {
id: icon
anchors.centerIn: parent
text: "cable"
font.pointSize: Appearance.font.size.large
fill: modelData.connected ? 1 : 0
color: modelData.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
}
}
StyledText {
Layout.fillWidth: true
text: modelData.interface || qsTr("Unknown")
}
StyledText {
text: modelData.connected ? qsTr("Connected") : qsTr("Disconnected")
color: modelData.connected ? Colours.palette.m3primary : Colours.palette.m3outline
font.pointSize: Appearance.font.size.small
font.weight: modelData.connected ? 500 : 400
}
StyledRect {
implicitWidth: implicitHeight
implicitHeight: connectIcon.implicitHeight + Appearance.padding.smaller * 2
radius: Appearance.rounding.full
color: Qt.alpha(Colours.palette.m3primaryContainer, modelData.connected ? 1 : 0)
StateLayer {
function onClicked(): void {
if (modelData.connected && modelData.connection) {
Network.disconnectEthernet(modelData.connection);
} else {
// Use connection name if available, otherwise use interface
Network.connectEthernet(modelData.connection || "", modelData.interface || "");
}
}
}
MaterialIcon {
id: connectIcon
anchors.centerIn: parent
text: modelData.connected ? "link_off" : "link"
color: modelData.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
}
}
}
implicitHeight: rowLayout.implicitHeight + Appearance.padding.normal * 2
}
}
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
}
}
}
}