Commit cbcda4ac authored by Oliver Beard's avatar Oliver Beard Committed by Nate Graham
Browse files

KCM: Make list items shorter with changed layout

Port and profile dropdowns are moved to the level of the device name, and
the test and balance buttons are moved to the level of the volume slider.
This makes each list item shorter and more streamlined-looking.
parent 30e3b58d
Pipeline #221226 passed with stage
in 51 seconds
......@@ -17,11 +17,12 @@ ColumnLayout {
RowLayout {
Layout.fillWidth: true
spacing: Kirigami.Units.largeSpacing
Kirigami.Icon {
Layout.alignment: Qt.AlignHCenter
width: height
height: nameLabel.contentHeight
height: Kirigami.Units.iconSizes.medium
source: IconName || "audio-card"
}
......@@ -30,6 +31,17 @@ ColumnLayout {
Layout.fillWidth: true
text: Properties["device.description"] || Name
elide: Text.ElideRight
// Show tooltip on hover when text elided
ToolTip {
text: parent.text
visible: parent.truncated && inputTextMouseArea.containsMouse
}
MouseArea {
id: inputTextMouseArea
anchors.fill: parent
hoverEnabled: true
}
}
Label {
......@@ -38,6 +50,7 @@ ColumnLayout {
}
ComboBox {
Layout.preferredWidth: Kirigami.Units.gridUnit * 12
model: Profiles.filter(function (profile) {
return profile.availability === Profile.Available;
})
......@@ -52,6 +65,7 @@ ColumnLayout {
Kirigami.Separator {
visible: (delegate.ListView.view.count != 0) && (delegate.ListView.view.count != (index + 1))
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.fillWidth: true
}
}
......@@ -14,7 +14,7 @@ import org.kde.plasma.private.volume 0.1
ColumnLayout {
id: delegate
spacing: Kirigami.Units.smallSpacing * 2
spacing: Kirigami.Units.smallSpacing
width: parent.width
property bool isPlayback: type.substring(0, 4) == "sink"
......@@ -28,6 +28,9 @@ ColumnLayout {
RowLayout {
spacing: Kirigami.Units.smallSpacing
Layout.fillWidth: true
// To keep the top row the same height as the row below, and stop things moving too much
// as the KCM loads (and the port/profile ComboBoxes may appear)
Layout.minimumHeight: balanceButton.implicitHeight
RadioButton {
id: defaultButton
......@@ -39,59 +42,40 @@ ColumnLayout {
visible: delegate.ListView.view.count > 1
onClicked: Default = true
text: !currentPort ? Description : i18ndc("kcm_pulseaudio", "label of device items", "%1 (%2)", currentPort.description, Description)
ToolTip {
text: parent.text
visible: parent.visible && parent.contentItem.truncated && labelMouseArea.containsMouse
}
MouseArea {
id: labelMouseArea
anchors.fill: parent.contentItem
hoverEnabled: true
acceptedButtons: Qt.NoButton
z: defaultButton.z + 1
}
}
Label {
id: soloLabel
Layout.fillWidth: true
text: defaultButton.text
visible: delegate.ListView.view.count <= 1
text: currentPort.description
visible: delegate.ListView.view.count === 1
elide: Text.ElideRight
}
Button {
id: testButton
text: i18ndc("kcm_pulseaudio", "Perform an audio test of the device", "Test")
icon.name: "audio-speakers-symbolic"
visible: isPlayback
onClicked: testOverlay.testSink(index);
}
Button {
id: balanceButton
text: i18ndc("kcm_pulseaudio", "Audio balance (e.g. control left/right volume individually", "Balance")
icon.name: "view-media-equalizer"
checkable: true
onClicked: {
if (checked) {
return;
}
// When unifying channels again, set all of them to the same value
// as to not keep an odd difference when adjusting them in unison
let volumes = ChannelVolumes;
for (let i = 0, count = RawChannels.length; i < count; ++i) {
volumes[i] = Volume;
}
// NOTE "ChannelVolumes = volumes" does not work as the
// AbstractModel does not have the magic JS Array to Qt List
// conversion stuff and only sees our Array as a QJSValue
delegate.pulseObject.channelVolumes = volumes;
ToolTip {
text: defaultButton.text
visible: parent.visible && soloLabelMouseArea.containsMouse
}
// Default to individual mode when a channel has a different volume
Component.onCompleted: {
checked = ChannelVolumes.some((volume) => {
return volume !== ChannelVolumes[0];
});
MouseArea {
id: soloLabelMouseArea
anchors.fill: parent
hoverEnabled: true
}
}
}
RowLayout {
Item {
Layout.leftMargin: Kirigami.Units.largeSpacing * 3
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
}
......@@ -99,13 +83,17 @@ ColumnLayout {
id: portLabel
visible: portBox.visible
text: i18nd("kcm_pulseaudio", "Port:")
Layout.leftMargin: Kirigami.Units.largeSpacing * 2
Layout.leftMargin: Kirigami.Units.largeSpacing
}
ComboBox {
id: portBox
readonly property var ports: Ports
Layout.preferredWidth: Kirigami.Units.gridUnit * 10
visible: portBox.count > 1
onModelChanged: currentIndex = ActivePortIndex
currentIndex: ActivePortIndex
onActivated: ActivePortIndex = index
......@@ -134,7 +122,7 @@ ColumnLayout {
id: profileLabel
visible: profileBox.visible
text: i18ndc("kcm_pulseaudio", "@label", "Profile:")
Layout.leftMargin: Kirigami.Units.largeSpacing * 2
Layout.leftMargin: Kirigami.Units.largeSpacing
}
ComboBox {
......@@ -142,6 +130,7 @@ ColumnLayout {
readonly property var card: paCardModel.data(paCardModel.indexOfCardNumber(CardIndex), paCardModel.role("PulseObject"))
Layout.preferredWidth: Kirigami.Units.gridUnit * 12
visible: profileBox.count > 1
textRole: "description"
......@@ -157,12 +146,7 @@ ColumnLayout {
MuteButton {
id: muteButton
Layout.alignment: Qt.AlignTop
Layout.topMargin: {
// Center the mute button around the main slider, or the first channel slider
const sliderHeight = channelSliderRepeater.count > 0 ? channelSliderRepeater.itemAt(0).height : volumeSlider.height;
return -Math.round((height - sliderHeight) / 2);
}
Layout.alignment: Qt.AlignTop | Qt.AlignVCenter
muted: Muted
onCheckedChanged: Muted = checked
toolTipText: !currentPort ? Description : currentPort.description
......@@ -175,7 +159,7 @@ ColumnLayout {
VolumeSlider {
id: volumeSlider
Layout.columnSpan: 2
Layout.alignment: Qt.AlignTop
Layout.alignment: Qt.AlignVCenter
visible: !balanceButton.checked
value: Volume
......@@ -200,7 +184,6 @@ ColumnLayout {
VolumeSlider {
Layout.fillWidth: true
hundredPercentLabelVisible: index === channelSliderRepeater.count -1
value: ChannelVolumes[index]
onMoved: {
......@@ -216,11 +199,56 @@ ColumnLayout {
}
}
}
Item {
Layout.leftMargin: Kirigami.Units.smallSpacing
}
Button {
Layout.alignment: Qt.AlignTop
id: testButton
text: i18ndc("kcm_pulseaudio", "Perform an audio test of the device", "Test")
icon.name: "audio-speakers-symbolic"
visible: isPlayback
onClicked: testOverlay.testSink(index);
}
Button {
Layout.alignment: Qt.AlignTop
id: balanceButton
text: i18ndc("kcm_pulseaudio", "Audio balance (e.g. control left/right volume individually", "Balance")
icon.name: "view-media-equalizer"
checkable: true
onClicked: {
if (checked) {
return;
}
// When unifying channels again, set all of them to the same value
// as to not keep an odd difference when adjusting them in unison
let volumes = ChannelVolumes;
for (let i = 0, count = RawChannels.length; i < count; ++i) {
volumes[i] = Volume;
}
// NOTE "ChannelVolumes = volumes" does not work as the
// AbstractModel does not have the magic JS Array to Qt List
// conversion stuff and only sees our Array as a QJSValue
delegate.pulseObject.channelVolumes = volumes;
}
// Default to individual mode when a channel has a different volume
Component.onCompleted: {
checked = ChannelVolumes.some((volume) => {
return volume !== ChannelVolumes[0];
});
}
}
}
Kirigami.Separator {
visible: (delegate.ListView.view.count != 0) && (delegate.ListView.view.count != (index + 1))
Layout.topMargin: delegate.ListView.view.spacing - delegate.spacing
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.fillWidth: true
}
}
......@@ -23,33 +23,35 @@ ColumnLayout {
RowLayout {
Layout.fillWidth: true
spacing: Kirigami.Units.smallSpacing * 2
Kirigami.Icon {
Layout.alignment: Qt.AlignHCenter
implicitHeight: Kirigami.Units.iconSizes.large
implicitWidth: implicitHeight
source: {
if (IconName.length !== 0) {
return IconName
}
if (delegate.isPlayback) {
return "audio-speakers-symbolic"
} else {
return "audio-input-microphone-symbolic"
}
}
}
ColumnLayout {
id: delegateColumn
Layout.fillWidth: true
spacing: Kirigami.Units.smallSpacing
RowLayout {
spacing: Kirigami.Units.largeSpacing
Kirigami.Icon {
Layout.alignment: Qt.AlignHCenter
width: height
height: Kirigami.Units.iconSizes.medium
source: {
if (IconName.length !== 0) {
return IconName
}
if (delegate.isPlayback) {
return "audio-speakers-symbolic"
} else {
return "audio-input-microphone-symbolic"
}
}
}
Label {
id: inputText
Layout.fillWidth: true
Layout.preferredHeight: deviceComboBox.implicitHeight
text: {
if (isEventStream) {
return i18nd("kcm_pulseaudio", "Notification Sounds");
......@@ -64,11 +66,22 @@ ColumnLayout {
}
}
elide: Text.ElideRight
// Show tooltip on hover when text elided
ToolTip {
text: parent.text
visible: parent.truncated && inputTextMouseArea.containsMouse
}
MouseArea {
id: inputTextMouseArea
anchors.fill: parent
hoverEnabled: true
}
}
DeviceComboBox {
id: deviceComboBox
Layout.preferredWidth: delegate.width / 3
Layout.preferredWidth: Kirigami.Units.gridUnit * 12
visible: !isEventStream && count > 1
}
}
......@@ -76,7 +89,6 @@ ColumnLayout {
RowLayout {
MuteButton {
Layout.alignment: Qt.AlignTop
Layout.topMargin: -Math.round((height - volumeSlider.height) / 2)
muted: Muted
onCheckedChanged: Muted = checked
toolTipText: inputText.text
......@@ -84,7 +96,7 @@ ColumnLayout {
VolumeSlider {
id: volumeSlider
Layout.alignment: Qt.AlignTop
Layout.alignment: Qt.AlignVCenter
value: Volume
onMoved: {
......@@ -98,6 +110,7 @@ ColumnLayout {
Kirigami.Separator {
visible: (delegate.ListView.view.count != 0) && (delegate.ListView.view.count != (index + 1))
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.fillWidth: true
Component.onCompleted: {
......
......@@ -15,14 +15,10 @@ import org.kde.plasma.private.volume 0.1
RowLayout {
id: sliderRow
Layout.bottomMargin: hundredPercentLabelVisible ? hundredPercentLabel.height : 0
signal moved()
property alias value: slider.value
property bool hundredPercentLabelVisible: true
QQC2.Slider {
id: slider
......@@ -31,24 +27,18 @@ RowLayout {
value: Volume
from: PulseAudio.MinimalVolume
to: PulseAudio.MaximalVolume
// TODO: implement a way to hide tickmarks
// stepSize: to / (PulseAudio.MaximalVolume / PulseAudio.NormalVolume * 100.0)
// TODO: implement a way to hide tickmarks (stepSize is also required to scroll)
// stepSize: to / (PulseAudio.MaximalVolume / PulseAudio.NormalVolume * 100.0)
visible: HasVolume
enabled: VolumeWritable
opacity: Muted ? 0.5 : 1
onMoved: sliderRow.moved()
QQC2.Label {
id: hundredPercentLabel
readonly property real hundredPos: (slider.width / slider.to) * PulseAudio.NormalVolume
z: slider.z - 1
x: (Qt.application.layoutDirection == Qt.RightToLeft ? slider.width - hundredPos : hundredPos) - width / 2
y: slider.height
visible: sliderRow.hundredPercentLabelVisible
opacity: 0.5
font.pixelSize: slider.height / 2.2
text: i18nd("kcm_pulseaudio", "100%")
onMoved: {
// Since it is not possible to use stepSize without tickmarks being displayed, force 1% steps
// Unfortunately without stepSize, it cannot snap visually whilst scrolling by changing value instead of Volume as it breaks the binding
Volume = Math.round(value * 100 / PulseAudio.NormalVolume) * PulseAudio.NormalVolume / 100
sliderRow.moved()
}
}
QQC2.Label {
......
......@@ -82,15 +82,18 @@ ScrollViewKCM {
Kirigami.ListSectionHeader {
Layout.fillWidth: true
visible: sinks.count > 0
visible: sinks.visible
text: i18nd("kcm_pulseaudio", "Playback Devices")
}
ListView {
id: sinks
visible: count > 0
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.bottomMargin: Kirigami.Units.smallSpacing
Layout.preferredHeight: contentHeight
interactive: false
spacing: Kirigami.Units.largeSpacing
......@@ -102,15 +105,18 @@ ScrollViewKCM {
Kirigami.ListSectionHeader {
Layout.fillWidth: true
visible: sources.count > 0
visible: sources.visible
text: i18nd("kcm_pulseaudio", "Recording Devices")
}
ListView {
id: sources
visible: count > 0
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.bottomMargin: Kirigami.Units.smallSpacing
Layout.preferredHeight: contentHeight
interactive: false
spacing: Kirigami.Units.largeSpacing
......@@ -122,18 +128,21 @@ ScrollViewKCM {
Kirigami.ListSectionHeader {
Layout.fillWidth: true
visible: inactiveCards.count > 0
visible: inactiveCards.visible
text: i18nd("kcm_pulseaudio", "Inactive Cards")
}
ListView {
id: inactiveCards
visible: count > 0
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.bottomMargin: Kirigami.Units.smallSpacing
Layout.preferredHeight: contentHeight
Layout.margins: Kirigami.Units.gridUnit / 2
interactive: false
spacing: Kirigami.Units.smallSpacing * 2
spacing: Kirigami.Units.largeSpacing
model: PlasmaCore.SortFilterModel {
sourceModel: paCardModel
function role(name) {
......@@ -151,15 +160,19 @@ ScrollViewKCM {
Kirigami.ListSectionHeader {
Layout.fillWidth: true
visible: eventStreamView.count || sinkInputView.count
visible: eventStreamView.visible || sinkInputView.visible
text: i18nd("kcm_pulseaudio", "Playback Streams")
}
ListView {
id: eventStreamView
visible: count > 0
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing
Layout.topMargin: Kirigami.Units.smallSpacing
// Only have a bottom margin if the ListView beneath is empty and not visible
Layout.bottomMargin: sinkInputView.visible ? 0 : Kirigami.Units.smallSpacing
Layout.preferredHeight: contentHeight
interactive: false
spacing: Kirigami.Units.largeSpacing
......@@ -175,9 +188,12 @@ ScrollViewKCM {
ListView {
id: sinkInputView
visible: count > 0
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.bottomMargin: Kirigami.Units.smallSpacing
Layout.preferredHeight: contentHeight
interactive: false
spacing: Kirigami.Units.largeSpacing
......@@ -193,15 +209,18 @@ ScrollViewKCM {
Kirigami.ListSectionHeader {
Layout.fillWidth: true
visible: sourceOutputView.count > 0
visible: sourceOutputView.visible
text: i18nd("kcm_pulseaudio", "Recording Streams")
}
ListView {
id: sourceOutputView
visible: count > 0
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.bottomMargin: Kirigami.Units.smallSpacing
Layout.preferredHeight: contentHeight
interactive: false
spacing: Kirigami.Units.largeSpacing
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment