diff options
Diffstat (limited to '')
| -rw-r--r-- | modules/controlcenter/ControlCenter.qml | 1 | ||||
| -rw-r--r-- | modules/controlcenter/NavRail.qml | 1 | ||||
| -rw-r--r-- | modules/controlcenter/Panes.qml | 3 | ||||
| -rw-r--r-- | modules/controlcenter/Session.qml | 4 | ||||
| -rw-r--r-- | modules/controlcenter/audio/AudioPane.qml | 145 | ||||
| -rw-r--r-- | modules/controlcenter/components/SplitPaneLayout.qml | 2 | ||||
| -rw-r--r-- | modules/controlcenter/components/SplitPaneWithDetails.qml | 1 | ||||
| -rw-r--r-- | modules/controlcenter/network/NetworkSettings.qml | 2 | ||||
| -rw-r--r-- | modules/controlcenter/network/NetworkingPane.qml | 30 |
9 files changed, 165 insertions, 24 deletions
diff --git a/modules/controlcenter/ControlCenter.qml b/modules/controlcenter/ControlCenter.qml index fdb824e..043e7e1 100644 --- a/modules/controlcenter/ControlCenter.qml +++ b/modules/controlcenter/ControlCenter.qml @@ -42,7 +42,6 @@ Item { Layout.fillWidth: true Layout.columnSpan: 2 - asynchronous: true active: root.floating visible: active diff --git a/modules/controlcenter/NavRail.qml b/modules/controlcenter/NavRail.qml index ef338b2..e61a741 100644 --- a/modules/controlcenter/NavRail.qml +++ b/modules/controlcenter/NavRail.qml @@ -43,7 +43,6 @@ Item { Loader { Layout.topMargin: Appearance.spacing.large - asynchronous: true active: !root.session.floating visible: active diff --git a/modules/controlcenter/Panes.qml b/modules/controlcenter/Panes.qml index 32ee708..03f74be 100644 --- a/modules/controlcenter/Panes.qml +++ b/modules/controlcenter/Panes.qml @@ -126,11 +126,10 @@ ClippingRectangle { anchors.fill: parent clip: false - asynchronous: true active: false Component.onCompleted: { - pane.updateActive(); + Qt.callLater(pane.updateActive); } onActiveChanged: { diff --git a/modules/controlcenter/Session.qml b/modules/controlcenter/Session.qml index 090ae9b..164e6cd 100644 --- a/modules/controlcenter/Session.qml +++ b/modules/controlcenter/Session.qml @@ -15,6 +15,6 @@ QtObject { readonly property NetworkState network: NetworkState {} readonly property EthernetState ethernet: EthernetState {} - onActiveChanged: activeIndex = panes.indexOf(active) - onActiveIndexChanged: active = panes[activeIndex] + onActiveChanged: activeIndex = Math.max(0, panes.indexOf(active)) + onActiveIndexChanged: if (panes[activeIndex]) active = panes[activeIndex] } diff --git a/modules/controlcenter/audio/AudioPane.qml b/modules/controlcenter/audio/AudioPane.qml index 76122f9..e4a1a64 100644 --- a/modules/controlcenter/audio/AudioPane.qml +++ b/modules/controlcenter/audio/AudioPane.qml @@ -460,6 +460,151 @@ Item { } } } + + SectionHeader { + title: qsTr("Applications") + description: qsTr("Control volume for individual applications") + } + + SectionContainer { + contentSpacing: Appearance.spacing.normal + + ColumnLayout { + Layout.fillWidth: true + spacing: Appearance.spacing.small + + Repeater { + model: Audio.streams + Layout.fillWidth: true + + delegate: ColumnLayout { + required property var modelData + required property int index + + Layout.fillWidth: true + spacing: Appearance.spacing.smaller + + RowLayout { + Layout.fillWidth: true + spacing: Appearance.spacing.normal + + MaterialIcon { + text: "apps" + font.pointSize: Appearance.font.size.normal + fill: 0 + } + + StyledText { + Layout.fillWidth: true + elide: Text.ElideRight + maximumLineCount: 1 + text: Audio.getStreamName(modelData) + font.pointSize: Appearance.font.size.normal + font.weight: 500 + } + + StyledInputField { + id: streamVolumeInput + Layout.preferredWidth: 70 + validator: IntValidator { bottom: 0; top: 100 } + enabled: !Audio.getStreamMuted(modelData) + + Component.onCompleted: { + text = Math.round(Audio.getStreamVolume(modelData) * 100).toString(); + } + + Connections { + target: modelData + function onAudioChanged() { + if (!streamVolumeInput.hasFocus && modelData?.audio) { + streamVolumeInput.text = Math.round(modelData.audio.volume * 100).toString(); + } + } + } + + onTextEdited: (text) => { + if (hasFocus) { + const val = parseInt(text); + if (!isNaN(val) && val >= 0 && val <= 100) { + Audio.setStreamVolume(modelData, val / 100); + } + } + } + + onEditingFinished: { + const val = parseInt(text); + if (isNaN(val) || val < 0 || val > 100) { + text = Math.round(Audio.getStreamVolume(modelData) * 100).toString(); + } + } + } + + StyledText { + text: "%" + color: Colours.palette.m3outline + font.pointSize: Appearance.font.size.normal + opacity: Audio.getStreamMuted(modelData) ? 0.5 : 1 + } + + StyledRect { + implicitWidth: implicitHeight + implicitHeight: streamMuteIcon.implicitHeight + Appearance.padding.normal * 2 + + radius: Appearance.rounding.normal + color: Audio.getStreamMuted(modelData) ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer + + StateLayer { + function onClicked(): void { + Audio.setStreamMuted(modelData, !Audio.getStreamMuted(modelData)); + } + } + + MaterialIcon { + id: streamMuteIcon + + anchors.centerIn: parent + text: Audio.getStreamMuted(modelData) ? "volume_off" : "volume_up" + color: Audio.getStreamMuted(modelData) ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer + } + } + } + + StyledSlider { + Layout.fillWidth: true + implicitHeight: Appearance.padding.normal * 3 + + value: Audio.getStreamVolume(modelData) + enabled: !Audio.getStreamMuted(modelData) + opacity: enabled ? 1 : 0.5 + onMoved: { + Audio.setStreamVolume(modelData, value); + if (!streamVolumeInput.hasFocus) { + streamVolumeInput.text = Math.round(value * 100).toString(); + } + } + + Connections { + target: modelData + function onAudioChanged() { + if (modelData?.audio) { + value = modelData.audio.volume; + } + } + } + } + } + } + + StyledText { + Layout.fillWidth: true + visible: Audio.streams.length === 0 + text: qsTr("No applications currently playing audio") + color: Colours.palette.m3outline + font.pointSize: Appearance.font.size.small + horizontalAlignment: Text.AlignHCenter + } + } + } } } } diff --git a/modules/controlcenter/components/SplitPaneLayout.qml b/modules/controlcenter/components/SplitPaneLayout.qml index 8b4f0d9..3609a74 100644 --- a/modules/controlcenter/components/SplitPaneLayout.qml +++ b/modules/controlcenter/components/SplitPaneLayout.qml @@ -49,7 +49,6 @@ RowLayout { anchors.leftMargin: Appearance.padding.large anchors.rightMargin: Appearance.padding.large + Appearance.padding.normal / 2 - asynchronous: true sourceComponent: root.leftContent Component.onCompleted: { @@ -91,7 +90,6 @@ RowLayout { anchors.fill: parent anchors.margins: Appearance.padding.large * 2 - asynchronous: true sourceComponent: root.rightContent Component.onCompleted: { diff --git a/modules/controlcenter/components/SplitPaneWithDetails.qml b/modules/controlcenter/components/SplitPaneWithDetails.qml index e873923..5db5bdb 100644 --- a/modules/controlcenter/components/SplitPaneWithDetails.qml +++ b/modules/controlcenter/components/SplitPaneWithDetails.qml @@ -56,7 +56,6 @@ Item { transformOrigin: Item.Center clip: false - asynchronous: true sourceComponent: rightPaneItem.targetComponent } diff --git a/modules/controlcenter/network/NetworkSettings.qml b/modules/controlcenter/network/NetworkSettings.qml index 22e07cb..81175fb 100644 --- a/modules/controlcenter/network/NetworkSettings.qml +++ b/modules/controlcenter/network/NetworkSettings.qml @@ -4,10 +4,12 @@ import ".." import "../components" import qs.components import qs.components.controls +import qs.components.containers import qs.components.effects import qs.services import qs.config import QtQuick +import QtQuick.Controls import QtQuick.Layouts ColumnLayout { diff --git a/modules/controlcenter/network/NetworkingPane.qml b/modules/controlcenter/network/NetworkingPane.qml index b430cce..9047174 100644 --- a/modules/controlcenter/network/NetworkingPane.qml +++ b/modules/controlcenter/network/NetworkingPane.qml @@ -153,9 +153,9 @@ Item { rightContent: Component { Item { id: rightPaneItem - - property var ethernetPane: root.session.ethernet.active - property var wirelessPane: root.session.network.active + + property var ethernetPane: root.session && root.session.ethernet ? root.session.ethernet.active : null + property var wirelessPane: root.session && root.session.network ? root.session.network.active : null property var pane: ethernetPane || wirelessPane property string paneId: ethernetPane ? ("eth:" + (ethernetPane.interface || "")) : (wirelessPane ? ("wifi:" + (wirelessPane.ssid || wirelessPane.bssid || "")) : "settings") property Component targetComponent: settingsComponent @@ -173,28 +173,28 @@ Item { } Connections { - target: root.session.ethernet + target: root.session && root.session.ethernet ? root.session.ethernet : null + enabled: target !== null + function onActiveChanged() { - // Clear wireless when ethernet is selected - if (root.session.ethernet.active && root.session.network.active) { - root.session.network.active = null; - return; // Let the network.onActiveChanged handle the update + // Clear others when ethernet is selected + if (root.session && root.session.ethernet && root.session.ethernet.active) { + if (root.session.network && root.session.network.active) root.session.network.active = null; } rightPaneItem.nextComponent = rightPaneItem.getComponentForPane(); - // paneId will automatically update via property binding } } Connections { - target: root.session.network + target: root.session && root.session.network ? root.session.network : null + enabled: target !== null + function onActiveChanged() { - // Clear ethernet when wireless is selected - if (root.session.network.active && root.session.ethernet.active) { - root.session.ethernet.active = null; - return; // Let the ethernet.onActiveChanged handle the update + // Clear others when wireless is selected + if (root.session && root.session.network && root.session.network.active) { + if (root.session.ethernet && root.session.ethernet.active) root.session.ethernet.active = null; } rightPaneItem.nextComponent = rightPaneItem.getComponentForPane(); - // paneId will automatically update via property binding } } |