controlcenter: ethernet panel (debug)
This commit is contained in:
parent
47dfcf4baf
commit
1debf488ee
8 changed files with 983 additions and 7 deletions
|
|
@ -158,8 +158,13 @@ Item {
|
|||
|
||||
NavItem {
|
||||
Layout.topMargin: Appearance.spacing.large * 2
|
||||
icon: "network_manage"
|
||||
label: "network"
|
||||
icon: "cable"
|
||||
label: "ethernet"
|
||||
}
|
||||
|
||||
NavItem {
|
||||
icon: "wifi"
|
||||
label: "wireless"
|
||||
}
|
||||
|
||||
NavItem {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import "ethernet"
|
||||
import "bluetooth"
|
||||
import "network"
|
||||
import "audio"
|
||||
|
|
@ -26,27 +27,34 @@ ClippingRectangle {
|
|||
|
||||
Pane {
|
||||
index: 0
|
||||
sourceComponent: NetworkPane {
|
||||
sourceComponent: EthernetPane {
|
||||
session: root.session
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
index: 1
|
||||
sourceComponent: BtPane {
|
||||
sourceComponent: NetworkPane {
|
||||
session: root.session
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
index: 2
|
||||
sourceComponent: AudioPane {
|
||||
sourceComponent: BtPane {
|
||||
session: root.session
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
index: 3
|
||||
sourceComponent: AudioPane {
|
||||
session: root.session
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
index: 4
|
||||
sourceComponent: AppearancePane {
|
||||
session: root.session
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import Quickshell.Bluetooth
|
|||
import QtQuick
|
||||
|
||||
QtObject {
|
||||
readonly property list<string> panes: ["network", "bluetooth", "audio", "appearance"]
|
||||
readonly property list<string> panes: ["ethernet", "wireless", "bluetooth", "audio", "appearance"]
|
||||
|
||||
required property var root
|
||||
property bool floating: false
|
||||
|
|
@ -12,6 +12,7 @@ QtObject {
|
|||
|
||||
readonly property Bt bt: Bt {}
|
||||
readonly property Network network: Network {}
|
||||
readonly property Ethernet ethernet: Ethernet {}
|
||||
|
||||
onActiveChanged: activeIndex = panes.indexOf(active)
|
||||
onActiveIndexChanged: active = panes[activeIndex]
|
||||
|
|
@ -29,4 +30,8 @@ QtObject {
|
|||
property bool showPasswordDialog: false
|
||||
property var pendingNetwork
|
||||
}
|
||||
|
||||
component Ethernet: QtObject {
|
||||
property var active
|
||||
}
|
||||
}
|
||||
|
|
|
|||
204
modules/controlcenter/ethernet/EthernetDetails.qml
Normal file
204
modules/controlcenter/ethernet/EthernetDetails.qml
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import ".."
|
||||
import qs.components
|
||||
import qs.components.controls
|
||||
import qs.components.effects
|
||||
import qs.components.containers
|
||||
import qs.services
|
||||
import qs.config
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property Session session
|
||||
readonly property var device: session.ethernet.active
|
||||
|
||||
StyledFlickable {
|
||||
anchors.fill: parent
|
||||
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
contentHeight: layout.height
|
||||
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
spacing: Appearance.spacing.normal
|
||||
|
||||
MaterialIcon {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
animate: true
|
||||
text: "cable"
|
||||
font.pointSize: Appearance.font.size.extraLarge * 3
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
animate: true
|
||||
text: root.device?.interface ?? qsTr("Unknown")
|
||||
font.pointSize: Appearance.font.size.large
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.topMargin: Appearance.spacing.large
|
||||
text: qsTr("Connection status")
|
||||
font.pointSize: Appearance.font.size.larger
|
||||
font.weight: 500
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: qsTr("Connection settings for this device")
|
||||
color: Colours.palette.m3outline
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: deviceStatus.implicitHeight + Appearance.padding.large * 2
|
||||
|
||||
radius: Appearance.rounding.normal
|
||||
color: Colours.tPalette.m3surfaceContainer
|
||||
|
||||
ColumnLayout {
|
||||
id: deviceStatus
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: Appearance.padding.large
|
||||
|
||||
spacing: Appearance.spacing.larger
|
||||
|
||||
Toggle {
|
||||
label: qsTr("Connected")
|
||||
checked: root.device?.connected ?? false
|
||||
toggle.onToggled: {
|
||||
if (checked) {
|
||||
if (root.device?.connection) {
|
||||
Network.connectEthernet(root.device.connection);
|
||||
}
|
||||
} else {
|
||||
if (root.device?.connection) {
|
||||
Network.disconnectEthernet(root.device.connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.topMargin: Appearance.spacing.large
|
||||
text: qsTr("Device properties")
|
||||
font.pointSize: Appearance.font.size.larger
|
||||
font.weight: 500
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: qsTr("Additional information")
|
||||
color: Colours.palette.m3outline
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: deviceProps.implicitHeight + Appearance.padding.large * 2
|
||||
|
||||
radius: Appearance.rounding.normal
|
||||
color: Colours.tPalette.m3surfaceContainer
|
||||
|
||||
ColumnLayout {
|
||||
id: deviceProps
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: Appearance.padding.large
|
||||
|
||||
spacing: Appearance.spacing.small / 2
|
||||
|
||||
StyledText {
|
||||
text: qsTr("Interface")
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: root.device?.interface ?? qsTr("Unknown")
|
||||
color: Colours.palette.m3outline
|
||||
font.pointSize: Appearance.font.size.small
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.topMargin: Appearance.spacing.normal
|
||||
text: qsTr("Connection")
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: root.device?.connection || qsTr("Not connected")
|
||||
color: Colours.palette.m3outline
|
||||
font.pointSize: Appearance.font.size.small
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.topMargin: Appearance.spacing.normal
|
||||
text: qsTr("State")
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: root.device?.state ?? qsTr("Unknown")
|
||||
color: Colours.palette.m3outline
|
||||
font.pointSize: Appearance.font.size.small
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
component Toggle: RowLayout {
|
||||
required property string label
|
||||
property alias checked: toggle.checked
|
||||
property alias toggle: toggle
|
||||
|
||||
Layout.fillWidth: true
|
||||
spacing: Appearance.spacing.normal
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
text: parent.label
|
||||
}
|
||||
|
||||
StyledSwitch {
|
||||
id: toggle
|
||||
|
||||
cLayer: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
262
modules/controlcenter/ethernet/EthernetList.qml
Normal file
262
modules/controlcenter/ethernet/EthernetList.qml
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
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 if (modelData.connection) {
|
||||
Network.connectEthernet(modelData.connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
156
modules/controlcenter/ethernet/EthernetPane.qml
Normal file
156
modules/controlcenter/ethernet/EthernetPane.qml
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import ".."
|
||||
import qs.components
|
||||
import qs.components.effects
|
||||
import qs.components.containers
|
||||
import qs.config
|
||||
import Quickshell.Widgets
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
required property Session session
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
spacing: 0
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: Math.floor(parent.width * 0.4)
|
||||
Layout.minimumWidth: 420
|
||||
Layout.fillHeight: true
|
||||
|
||||
EthernetList {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Appearance.padding.large + Appearance.padding.normal
|
||||
anchors.leftMargin: Appearance.padding.large
|
||||
anchors.rightMargin: Appearance.padding.large + Appearance.padding.normal / 2
|
||||
|
||||
session: root.session
|
||||
}
|
||||
|
||||
InnerBorder {
|
||||
leftThickness: 0
|
||||
rightThickness: Appearance.padding.normal / 2
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
ClippingRectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Appearance.padding.normal
|
||||
anchors.leftMargin: 0
|
||||
anchors.rightMargin: Appearance.padding.normal / 2
|
||||
|
||||
radius: rightBorder.innerRadius
|
||||
color: "transparent"
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
|
||||
property var pane: root.session.ethernet.active
|
||||
property string paneId: pane ? (pane.interface || "") : ""
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Appearance.padding.large * 2
|
||||
|
||||
opacity: 1
|
||||
scale: 1
|
||||
transformOrigin: Item.Center
|
||||
|
||||
clip: false
|
||||
asynchronous: true
|
||||
sourceComponent: pane ? details : settings
|
||||
|
||||
Behavior on paneId {
|
||||
SequentialAnimation {
|
||||
ParallelAnimation {
|
||||
Anim {
|
||||
target: loader
|
||||
property: "opacity"
|
||||
to: 0
|
||||
easing.bezierCurve: Appearance.anim.curves.standardAccel
|
||||
}
|
||||
Anim {
|
||||
target: loader
|
||||
property: "scale"
|
||||
to: 0.8
|
||||
easing.bezierCurve: Appearance.anim.curves.standardAccel
|
||||
}
|
||||
}
|
||||
PropertyAction {}
|
||||
ParallelAnimation {
|
||||
Anim {
|
||||
target: loader
|
||||
property: "opacity"
|
||||
to: 1
|
||||
easing.bezierCurve: Appearance.anim.curves.standardDecel
|
||||
}
|
||||
Anim {
|
||||
target: loader
|
||||
property: "scale"
|
||||
to: 1
|
||||
easing.bezierCurve: Appearance.anim.curves.standardDecel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPaneChanged: {
|
||||
paneId = pane ? (pane.interface || "") : "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InnerBorder {
|
||||
id: rightBorder
|
||||
|
||||
leftThickness: Appearance.padding.normal / 2
|
||||
}
|
||||
|
||||
Component {
|
||||
id: settings
|
||||
|
||||
StyledFlickable {
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
contentHeight: settingsInner.height
|
||||
|
||||
EthernetSettings {
|
||||
id: settingsInner
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
session: root.session
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: details
|
||||
|
||||
EthernetDetails {
|
||||
session: root.session
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component Anim: NumberAnimation {
|
||||
target: loader
|
||||
duration: Appearance.anim.durations.normal / 2
|
||||
easing.type: Easing.BezierSpline
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
155
modules/controlcenter/ethernet/EthernetSettings.qml
Normal file
155
modules/controlcenter/ethernet/EthernetSettings.qml
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import ".."
|
||||
import qs.components
|
||||
import qs.components.controls
|
||||
import qs.components.effects
|
||||
import qs.services
|
||||
import qs.config
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
required property Session session
|
||||
|
||||
spacing: Appearance.spacing.normal
|
||||
|
||||
MaterialIcon {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: "cable"
|
||||
font.pointSize: Appearance.font.size.extraLarge * 3
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: qsTr("Ethernet settings")
|
||||
font.pointSize: Appearance.font.size.large
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.topMargin: Appearance.spacing.large
|
||||
text: qsTr("Ethernet devices")
|
||||
font.pointSize: Appearance.font.size.larger
|
||||
font.weight: 500
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: qsTr("Available ethernet devices")
|
||||
color: Colours.palette.m3outline
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: ethernetInfo.implicitHeight + Appearance.padding.large * 2
|
||||
|
||||
radius: Appearance.rounding.normal
|
||||
color: Colours.tPalette.m3surfaceContainer
|
||||
|
||||
ColumnLayout {
|
||||
id: ethernetInfo
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: Appearance.padding.large
|
||||
|
||||
spacing: Appearance.spacing.small / 2
|
||||
|
||||
StyledText {
|
||||
text: qsTr("Total devices")
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: qsTr("%1").arg(Network.ethernetDeviceCount || Network.ethernetDevices.length)
|
||||
color: Colours.palette.m3outline
|
||||
font.pointSize: Appearance.font.size.small
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.topMargin: Appearance.spacing.normal
|
||||
text: qsTr("Connected devices")
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: qsTr("%1").arg(Network.ethernetDevices.filter(d => d.connected).length)
|
||||
color: Colours.palette.m3outline
|
||||
font.pointSize: Appearance.font.size.small
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.topMargin: Appearance.spacing.large
|
||||
text: qsTr("Debug Info")
|
||||
font.pointSize: Appearance.font.size.larger
|
||||
font.weight: 500
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: debugInfo.implicitHeight + Appearance.padding.large * 2
|
||||
|
||||
radius: Appearance.rounding.normal
|
||||
color: Colours.tPalette.m3surfaceContainer
|
||||
|
||||
ColumnLayout {
|
||||
id: debugInfo
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: Appearance.padding.large
|
||||
|
||||
spacing: Appearance.spacing.small / 2
|
||||
|
||||
StyledText {
|
||||
text: qsTr("Process running: %1").arg(Network.ethernetProcessRunning ? "Yes" : "No")
|
||||
font.pointSize: Appearance.font.size.small
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: qsTr("List length: %1").arg(Network.ethernetDevices.length)
|
||||
font.pointSize: Appearance.font.size.small
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: qsTr("Device count: %1").arg(Network.ethernetDeviceCount)
|
||||
font.pointSize: Appearance.font.size.small
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.topMargin: Appearance.spacing.normal
|
||||
text: qsTr("Debug: %1").arg(Network.ethernetDebugInfo || "No info")
|
||||
font.pointSize: Appearance.font.size.small
|
||||
color: Colours.palette.m3outline
|
||||
wrapMode: Text.Wrap
|
||||
Layout.maximumWidth: parent.width
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -7,11 +7,24 @@ import QtQuick
|
|||
Singleton {
|
||||
id: root
|
||||
|
||||
Component.onCompleted: {
|
||||
// Trigger ethernet device detection after initialization
|
||||
Qt.callLater(() => {
|
||||
getEthernetDevices();
|
||||
});
|
||||
}
|
||||
|
||||
readonly property list<AccessPoint> networks: []
|
||||
readonly property AccessPoint active: networks.find(n => n.active) ?? null
|
||||
property bool wifiEnabled: true
|
||||
readonly property bool scanning: rescanProc.running
|
||||
|
||||
property list<var> ethernetDevices: []
|
||||
readonly property var activeEthernet: ethernetDevices.find(d => d.connected) ?? null
|
||||
property int ethernetDeviceCount: 0
|
||||
property string ethernetDebugInfo: ""
|
||||
property bool ethernetProcessRunning: false
|
||||
|
||||
function enableWifi(enabled: bool): void {
|
||||
const cmd = enabled ? "on" : "off";
|
||||
enableWifiProc.exec(["nmcli", "radio", "wifi", cmd]);
|
||||
|
|
@ -70,11 +83,27 @@ Singleton {
|
|||
wifiStatusProc.running = true;
|
||||
}
|
||||
|
||||
function getEthernetDevices(): void {
|
||||
getEthernetDevicesProc.running = true;
|
||||
}
|
||||
|
||||
|
||||
function connectEthernet(connectionName: string): void {
|
||||
connectEthernetProc.exec(["nmcli", "connection", "up", connectionName]);
|
||||
}
|
||||
|
||||
function disconnectEthernet(connectionName: string): void {
|
||||
disconnectEthernetProc.exec(["nmcli", "connection", "down", connectionName]);
|
||||
}
|
||||
|
||||
Process {
|
||||
running: true
|
||||
command: ["nmcli", "m"]
|
||||
stdout: SplitParser {
|
||||
onRead: getNetworks.running = true
|
||||
onRead: {
|
||||
getNetworks.running = true;
|
||||
getEthernetDevices();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -336,6 +365,158 @@ Singleton {
|
|||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: getEthernetDevicesProc
|
||||
|
||||
running: false
|
||||
command: ["nmcli", "-g", "DEVICE,TYPE,STATE,CONNECTION", "device", "status"]
|
||||
environment: ({
|
||||
LANG: "C.UTF-8",
|
||||
LC_ALL: "C.UTF-8"
|
||||
})
|
||||
onRunningChanged: {
|
||||
root.ethernetProcessRunning = running;
|
||||
if (!running) {
|
||||
// Process finished, update debug info
|
||||
Qt.callLater(() => {
|
||||
if (root.ethernetDebugInfo === "" || root.ethernetDebugInfo.includes("Process exited")) {
|
||||
root.ethernetDebugInfo = "Process finished, waiting for output...";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
Qt.callLater(() => {
|
||||
const outputLength = ethernetStdout.text ? ethernetStdout.text.length : 0;
|
||||
root.ethernetDebugInfo = "Process exited with code: " + exitCode + ", output length: " + outputLength;
|
||||
if (outputLength > 0) {
|
||||
// Output was captured, process it
|
||||
const output = ethernetStdout.text.trim();
|
||||
root.ethernetDebugInfo = "Processing output from onExited, length: " + output.length + "\nOutput: " + output.substring(0, 200);
|
||||
root.processEthernetOutput(output);
|
||||
} else {
|
||||
root.ethernetDebugInfo = "No output captured in onExited";
|
||||
}
|
||||
});
|
||||
}
|
||||
stdout: StdioCollector {
|
||||
id: ethernetStdout
|
||||
onStreamFinished: {
|
||||
const output = text.trim();
|
||||
root.ethernetDebugInfo = "Output received in onStreamFinished! Length: " + output.length + ", First 100 chars: " + output.substring(0, 100);
|
||||
|
||||
if (!output || output.length === 0) {
|
||||
root.ethernetDebugInfo = "No output received (empty)";
|
||||
return;
|
||||
}
|
||||
|
||||
root.processEthernetOutput(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processEthernetOutput(output: string): void {
|
||||
const PLACEHOLDER = "STRINGWHICHHOPEFULLYWONTBEUSED";
|
||||
const rep = new RegExp("\\\\:", "g");
|
||||
const rep2 = new RegExp(PLACEHOLDER, "g");
|
||||
|
||||
const lines = output.split("\n");
|
||||
root.ethernetDebugInfo = "Processing " + lines.length + " lines";
|
||||
|
||||
const allDevices = lines.map(d => {
|
||||
const dev = d.replace(rep, PLACEHOLDER).split(":");
|
||||
return {
|
||||
interface: dev[0]?.replace(rep2, ":") ?? "",
|
||||
type: dev[1]?.replace(rep2, ":") ?? "",
|
||||
state: dev[2]?.replace(rep2, ":") ?? "",
|
||||
connection: dev[3]?.replace(rep2, ":") ?? ""
|
||||
};
|
||||
});
|
||||
|
||||
root.ethernetDebugInfo = "All devices: " + allDevices.length + ", Types: " + allDevices.map(d => d.type).join(", ");
|
||||
|
||||
const ethernetOnly = allDevices.filter(d => d.type === "ethernet");
|
||||
root.ethernetDebugInfo = "Ethernet devices found: " + ethernetOnly.length;
|
||||
|
||||
const ethernetDevices = ethernetOnly.map(d => {
|
||||
const state = d.state || "";
|
||||
const connected = state === "100 (connected)" || state === "connected" || state.startsWith("connected");
|
||||
return {
|
||||
interface: d.interface,
|
||||
type: d.type,
|
||||
state: state,
|
||||
connection: d.connection,
|
||||
connected: connected,
|
||||
ipAddress: "",
|
||||
gateway: "",
|
||||
dns: [],
|
||||
subnet: "",
|
||||
macAddress: "",
|
||||
speed: ""
|
||||
};
|
||||
});
|
||||
|
||||
root.ethernetDebugInfo = "Ethernet devices processed: " + ethernetDevices.length + ", First device: " + (ethernetDevices[0]?.interface || "none");
|
||||
|
||||
// Update the list - replace the entire array to ensure QML detects the change
|
||||
// Create a new array and assign it to the property
|
||||
const newDevices = [];
|
||||
for (let i = 0; i < ethernetDevices.length; i++) {
|
||||
newDevices.push(ethernetDevices[i]);
|
||||
}
|
||||
|
||||
// Replace the entire list
|
||||
root.ethernetDevices = newDevices;
|
||||
|
||||
// Force QML to detect the change by updating a property
|
||||
root.ethernetDeviceCount = ethernetDevices.length;
|
||||
|
||||
// Force QML to re-evaluate the list by accessing it
|
||||
Qt.callLater(() => {
|
||||
const count = root.ethernetDevices.length;
|
||||
root.ethernetDebugInfo = "Final: Found " + ethernetDevices.length + " devices, List length: " + count + ", Parsed all: " + allDevices.length + ", Output length: " + output.length;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Process {
|
||||
id: connectEthernetProc
|
||||
|
||||
onExited: {
|
||||
getEthernetDevices();
|
||||
}
|
||||
stdout: SplitParser {
|
||||
onRead: getEthernetDevices()
|
||||
}
|
||||
stderr: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const error = text.trim();
|
||||
if (error && error.length > 0 && !error.includes("successfully") && !error.includes("Connection activated")) {
|
||||
console.warn("Ethernet connection error:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: disconnectEthernetProc
|
||||
|
||||
onExited: {
|
||||
getEthernetDevices();
|
||||
}
|
||||
stdout: SplitParser {
|
||||
onRead: getEthernetDevices()
|
||||
}
|
||||
stderr: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const error = text.trim();
|
||||
if (error && error.length > 0 && !error.includes("successfully") && !error.includes("disconnected")) {
|
||||
console.warn("Ethernet disconnection error:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component AccessPoint: QtObject {
|
||||
required property var lastIpcObject
|
||||
readonly property string ssid: lastIpcObject.ssid
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue