Warning, /plasma/plasma-pa/src/kcm/ui/DeviceListItem.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2014-2015 Harald Sitter <sitter@kde.org> 0003 SPDX-FileCopyrightText: 2019 Sefa Eyeoglu <contact@scrumplex.net> 0004 0005 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 0008 import QtQuick 0009 import QtQuick.Controls 0010 import QtQuick.Layouts 0011 0012 import org.kde.kirigami as Kirigami 0013 import org.kde.kitemmodels as KItemModels 0014 import org.kde.plasma.private.volume 0015 0016 ColumnLayout { 0017 id: delegate 0018 spacing: Kirigami.Units.smallSpacing 0019 width: parent.width 0020 0021 property bool isPlayback: type.substring(0, 4) == "sink" 0022 0023 readonly property var currentPort: Ports[ActivePortIndex] 0024 0025 opacity: (Ports.length === 1 && Ports[0].availability == Port.Unavailable) ? 0.5 : 1 0026 0027 property var pulseObject: model.PulseObject 0028 0029 property alias portVisible: portBox.visible 0030 property bool comboBoxLabelsVisible: false 0031 0032 RowLayout { 0033 spacing: Kirigami.Units.smallSpacing 0034 Layout.fillWidth: true 0035 // To keep the top row the same height as the row below, and stop things moving too much 0036 // as the KCM loads (and the port/profile ComboBoxes may appear) 0037 Layout.minimumHeight: balanceButton.implicitHeight 0038 0039 RadioButton { 0040 id: defaultButton 0041 Layout.fillWidth: true 0042 Layout.leftMargin: LayoutMirroring.enabled ? 0 : Math.round((muteButton.width - defaultButton.indicator.width) / 2) 0043 Layout.rightMargin: LayoutMirroring.enabled ? Math.round((muteButton.width - defaultButton.indicator.width) / 2) : 0 0044 spacing: Kirigami.Units.smallSpacing + Math.round((muteButton.width - defaultButton.indicator.width) / 2) 0045 checked: Default 0046 visible: delegate.ListView.view.count > 1 0047 onClicked: Default = true 0048 text: !currentPort ? Description : i18ndc("kcm_pulseaudio", "label of device items", "%1 (%2)", currentPort.description, Description) 0049 0050 ToolTip { 0051 text: parent.text 0052 visible: parent.visible && parent.contentItem.truncated && labelMouseArea.containsMouse 0053 } 0054 MouseArea { 0055 id: labelMouseArea 0056 anchors.fill: parent.contentItem 0057 hoverEnabled: true 0058 acceptedButtons: Qt.NoButton 0059 z: defaultButton.z + 1 0060 } 0061 } 0062 0063 Label { 0064 id: soloLabel 0065 Layout.fillWidth: true 0066 text: currentPort.description 0067 visible: delegate.ListView.view.count === 1 0068 elide: Text.ElideRight 0069 0070 ToolTip { 0071 text: defaultButton.text 0072 visible: parent.visible && soloLabelMouseArea.containsMouse 0073 } 0074 MouseArea { 0075 id: soloLabelMouseArea 0076 anchors.fill: parent 0077 hoverEnabled: true 0078 } 0079 } 0080 0081 Item { 0082 Layout.leftMargin: Kirigami.Units.largeSpacing 0083 Layout.fillWidth: true 0084 } 0085 0086 Label { 0087 id: portLabel 0088 visible: comboBoxLabelsVisible && portBox.visible 0089 text: i18nd("kcm_pulseaudio", "Port:") 0090 Layout.leftMargin: Kirigami.Units.largeSpacing 0091 } 0092 0093 ComboBox { 0094 id: portBox 0095 0096 readonly property var ports: Ports 0097 0098 Layout.preferredWidth: Kirigami.Units.gridUnit * 10 0099 visible: portBox.count > 1 0100 0101 onModelChanged: currentIndex = ActivePortIndex 0102 currentIndex: ActivePortIndex 0103 onActivated: ActivePortIndex = index 0104 0105 onPortsChanged: { 0106 var items = []; 0107 for (var i = 0; i < ports.length; ++i) { 0108 var port = ports[i]; 0109 var text; 0110 if (port.availability == Port.Unavailable) { 0111 if (port.name == "analog-output-speaker" || port.name == "analog-input-microphone-internal") { 0112 text = i18ndc("kcm_pulseaudio", "Port is unavailable", "%1 (unavailable)", port.description); 0113 } else { 0114 text = i18ndc("kcm_pulseaudio", "Port is unplugged", "%1 (unplugged)", port.description); 0115 } 0116 } else { 0117 text = port.description; 0118 } 0119 items.push(text); 0120 } 0121 model = items; 0122 } 0123 0124 // Ensure the popup is sufficiently wide to list *full* device names 0125 // and is correctly positioned to not go off the page 0126 popup.width: Math.max(implicitWidth, width) 0127 popup.leftMargin: delegate.ListView.view.Layout.leftMargin 0128 popup.rightMargin: delegate.ListView.view.Layout.rightMargin 0129 popup.x: mirrored ? 0 : width - popup.width 0130 } 0131 0132 Label { 0133 id: profileLabel 0134 visible: comboBoxLabelsVisible && profileBox.visible 0135 text: i18ndc("kcm_pulseaudio", "@label", "Profile:") 0136 Layout.leftMargin: Kirigami.Units.largeSpacing 0137 } 0138 0139 ComboBox { 0140 id: profileBox 0141 0142 readonly property var card: paCardModel.data(paCardModel.indexOfCardNumber(CardIndex), paCardModel.KItemModels.KRoleNames.role("PulseObject")) 0143 0144 Layout.preferredWidth: Kirigami.Units.gridUnit * 12 0145 visible: profileBox.count > 1 0146 textRole: "description" 0147 0148 model: card ? card.profiles.filter(profile => profile.availability === Profile.Available) : [] 0149 currentIndex: card ? model.indexOf(card.profiles[card.activeProfileIndex]) : -1 0150 0151 onActivated: index => card.activeProfileIndex = card.profiles.indexOf(model[index]) 0152 0153 // Ensure the popup is sufficiently wide to list *full* device names 0154 // and is correctly positioned to not go off the page 0155 popup.width: Math.max(implicitWidth, width) 0156 popup.leftMargin: delegate.ListView.view.Layout.leftMargin 0157 popup.rightMargin: delegate.ListView.view.Layout.rightMargin 0158 popup.x: mirrored ? 0 : width - popup.width 0159 } 0160 } 0161 0162 RowLayout { 0163 spacing: Kirigami.Units.smallSpacing 0164 0165 MuteButton { 0166 id: muteButton 0167 Layout.alignment: Qt.AlignTop | Qt.AlignVCenter 0168 muted: Muted 0169 onCheckedChanged: Muted = checked 0170 toolTipText: !currentPort ? Description : currentPort.description 0171 } 0172 0173 GridLayout { 0174 rows: Math.max(1, channelSliderRepeater.count) 0175 flow: GridLayout.TopToBottom 0176 0177 VolumeSlider { 0178 id: volumeSlider 0179 Layout.columnSpan: 2 0180 Layout.alignment: Qt.AlignVCenter 0181 visible: !balanceButton.checked 0182 } 0183 0184 Repeater { 0185 model: balanceButton.checked ? Channels : null 0186 0187 Label { 0188 Layout.alignment: Qt.AlignTop | Qt.AlignRight 0189 text: i18ndc("kcm_pulseaudio", "Placeholder is channel name", "%1:", modelData) 0190 } 0191 } 0192 0193 Repeater { 0194 id: channelSliderRepeater 0195 model: balanceButton.checked ? RawChannels : null 0196 0197 VolumeSlider { 0198 Layout.fillWidth: true 0199 0200 value: ChannelVolumes[index] 0201 0202 channel: index 0203 } 0204 } 0205 } 0206 0207 Item { 0208 Layout.leftMargin: Kirigami.Units.smallSpacing 0209 } 0210 0211 Button { 0212 Layout.alignment: Qt.AlignTop 0213 id: testButton 0214 text: i18ndc("kcm_pulseaudio", "Perform an audio test of the device", "Test") 0215 icon.name: "audio-speakers-symbolic" 0216 visible: isPlayback 0217 onClicked: testOverlay.testSink(index); 0218 } 0219 0220 Button { 0221 Layout.alignment: Qt.AlignTop 0222 id: balanceButton 0223 text: i18ndc("kcm_pulseaudio", "Audio balance (e.g. control left/right volume individually", "Balance") 0224 icon.name: "view-media-equalizer" 0225 checkable: true 0226 0227 onClicked: { 0228 if (checked) { 0229 return; 0230 } 0231 0232 // When unifying channels again, set all of them to the same value 0233 // as to not keep an odd difference when adjusting them in unison 0234 let volumes = ChannelVolumes; 0235 for (let i = 0, count = RawChannels.length; i < count; ++i) { 0236 volumes[i] = Volume; 0237 } 0238 // NOTE "ChannelVolumes = volumes" does not work as the 0239 // AbstractModel does not have the magic JS Array to Qt List 0240 // conversion stuff and only sees our Array as a QJSValue 0241 delegate.pulseObject.channelVolumes = volumes; 0242 } 0243 0244 // Default to individual mode when a channel has a different volume 0245 Component.onCompleted: { 0246 checked = ChannelVolumes.some((volume) => { 0247 return volume !== ChannelVolumes[0]; 0248 }); 0249 } 0250 } 0251 } 0252 0253 Kirigami.Separator { 0254 visible: (delegate.ListView.view.count != 0) && (delegate.ListView.view.count != (index + 1)) 0255 Layout.topMargin: Kirigami.Units.smallSpacing 0256 Layout.fillWidth: true 0257 } 0258 }