summaryrefslogtreecommitdiff
path: root/modules/controlcenter
diff options
context:
space:
mode:
Diffstat (limited to 'modules/controlcenter')
-rw-r--r--modules/controlcenter/ControlCenter.qml1
-rw-r--r--modules/controlcenter/NavRail.qml1
-rw-r--r--modules/controlcenter/Panes.qml3
-rw-r--r--modules/controlcenter/Session.qml4
-rw-r--r--modules/controlcenter/audio/AudioPane.qml145
-rw-r--r--modules/controlcenter/components/SplitPaneLayout.qml2
-rw-r--r--modules/controlcenter/components/SplitPaneWithDetails.qml1
-rw-r--r--modules/controlcenter/network/NetworkSettings.qml2
-rw-r--r--modules/controlcenter/network/NetworkingPane.qml30
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
}
}