Changeset View
Changeset View
Standalone View
Standalone View
applet/contents/ui/ListItemBase.qml
Show First 20 Lines • Show All 147 Lines • ▼ Show 20 Line(s) | 112 | RowLayout { | |||
---|---|---|---|---|---|
148 | 148 | | |||
149 | PlasmaComponents3.ToolButton { | 149 | PlasmaComponents3.ToolButton { | ||
150 | id: defaultButton | 150 | id: defaultButton | ||
151 | text: i18n("Default Device") | 151 | text: i18n("Default Device") | ||
152 | icon.name: PulseObject.default ? "starred-symbolic" : "non-starred-symbolic" | 152 | icon.name: PulseObject.default ? "starred-symbolic" : "non-starred-symbolic" | ||
153 | checkable: true | 153 | checkable: true | ||
154 | checked: PulseObject.default | 154 | checked: PulseObject.default | ||
155 | visible: (type == "sink" && sinkView.model.count > 1) || (type == "source" && sourceView.model.count > 1) | 155 | visible: (type == "sink" && sinkView.model.count > 1) || (type == "source" && sourceView.model.count > 1) | ||
156 | onClicked: PulseObject.default = true; | 156 | onClicked: { | ||
157 | PulseObject.default = true; | ||||
158 | PulseObject.switchStreams(); | ||||
157 | } | 159 | } | ||
158 | | ||||
159 | SmallToolButton { | | |||
160 | id: contextMenuButton | | |||
161 | icon: "application-menu" | | |||
162 | checkable: true | | |||
163 | onClicked: contextMenu.show() | | |||
164 | tooltip: i18n("Show additional options for %1", textLabel.text) | | |||
165 | } | 160 | } | ||
166 | } | 161 | } | ||
167 | 162 | | |||
168 | RowLayout { | 163 | RowLayout { | ||
169 | SmallToolButton { | 164 | SmallToolButton { | ||
170 | readonly property bool isPlayback: type.substring(0, 4) == "sink" | 165 | readonly property bool isPlayback: type.substring(0, 4) == "sink" | ||
171 | icon: Icon.name(Volume, Muted, isPlayback ? "audio-volume" : "microphone-sensitivity") | 166 | icon: Icon.name(Volume, Muted, isPlayback ? "audio-volume" : "microphone-sensitivity") | ||
172 | onClicked: Muted = !Muted | 167 | onClicked: Muted = !Muted | ||
173 | checked: Muted | 168 | checked: Muted | ||
174 | tooltip: i18n("Mute %1", textLabel.text) | 169 | tooltip: i18n("Mute %1", textLabel.text) | ||
175 | 170 | | |||
176 | } | 171 | } | ||
177 | 172 | | |||
178 | PlasmaComponents.Slider { | 173 | PlasmaComponents.Slider { | ||
179 | id: slider | 174 | id: slider | ||
180 | 175 | | |||
181 | // Helper properties to allow async slider updates. | 176 | // Helper properties to allow async slider updates. | ||
182 | // While we are sliding we must not react to value updates | 177 | // While we are sliding we must not react to value updates | ||
183 | // as otherwise we can easily end up in a loop where value | 178 | // as otherwise we can easily end up in a loop where value | ||
184 | // changes trigger volume changes trigger value changes. | 179 | // changes trigger volume changes trigger value changes. | ||
185 | property int volume: Volume | 180 | property int volume: Volume | ||
186 | property bool ignoreValueChange: true | 181 | property bool ignoreValueChange: true | ||
187 | property bool forceRaiseMaxVolume: false | | |||
188 | readonly property bool raiseMaxVolume: forceRaiseMaxVolume || volume >= PulseAudio.NormalVolume * 1.01 | | |||
189 | 182 | | |||
190 | Layout.fillWidth: true | 183 | Layout.fillWidth: true | ||
191 | minimumValue: PulseAudio.MinimalVolume | 184 | minimumValue: PulseAudio.MinimalVolume | ||
192 | maximumValue: raiseMaxVolume ? PulseAudio.MaximalVolume : PulseAudio.NormalVolume | 185 | maximumValue: main.maxVolumeValue | ||
193 | stepSize: maximumValue / (maximumValue / PulseAudio.NormalVolume * 100.0) | 186 | stepSize: main.volumeStep | ||
194 | visible: HasVolume | 187 | visible: HasVolume | ||
195 | enabled: VolumeWritable | 188 | enabled: VolumeWritable | ||
196 | opacity: Muted ? 0.5 : 1 | 189 | opacity: Muted ? 0.5 : 1 | ||
197 | 190 | | |||
198 | Accessible.name: i18nc("Accessibility data on volume slider", "Adjust volume for %1", textLabel.text) | 191 | Accessible.name: i18nc("Accessibility data on volume slider", "Adjust volume for %1", textLabel.text) | ||
199 | 192 | | |||
200 | Component.onCompleted: { | 193 | Component.onCompleted: { | ||
201 | ignoreValueChange = false; | 194 | ignoreValueChange = false; | ||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Line(s) | 270 | MouseArea { | |||
278 | anchors { | 271 | anchors { | ||
279 | fill: parent | 272 | fill: parent | ||
280 | leftMargin: clientIcon.width | 273 | leftMargin: clientIcon.width | ||
281 | } | 274 | } | ||
282 | acceptedButtons: Qt.MiddleButton | 275 | acceptedButtons: Qt.MiddleButton | ||
283 | onClicked: Muted = !Muted | 276 | onClicked: Muted = !Muted | ||
284 | } | 277 | } | ||
285 | } | 278 | } | ||
286 | | ||||
287 | PlasmaComponents.ContextMenu { | | |||
288 | id: contextMenu | | |||
289 | | ||||
290 | visualParent: contextMenuButton | | |||
291 | placement: PlasmaCore.Types.BottomPosedLeftAlignedPopup | | |||
292 | | ||||
293 | onStatusChanged: { | | |||
294 | if (status == PlasmaComponents.DialogStatus.Closed) { | | |||
295 | contextMenuButton.checked = false; | | |||
296 | } | | |||
297 | } | | |||
298 | | ||||
299 | function newSeperator() { | | |||
300 | return Qt.createQmlObject("import org.kde.plasma.components 2.0 as PlasmaComponents; PlasmaComponents.MenuItem { separator: true }", contextMenu); | | |||
301 | } | | |||
302 | function newMenuItem() { | | |||
303 | return Qt.createQmlObject("import org.kde.plasma.components 2.0 as PlasmaComponents; PlasmaComponents.MenuItem {}", contextMenu); | | |||
304 | } | | |||
305 | | ||||
306 | function loadDynamicActions() { | | |||
307 | contextMenu.clearMenuItems(); | | |||
308 | | ||||
309 | // Raise max volume | | |||
310 | menuItem = newMenuItem(); | | |||
311 | menuItem.text = i18n("Raise maximum volume"); | | |||
312 | menuItem.checkable = true; | | |||
313 | menuItem.checked = slider.forceRaiseMaxVolume; | | |||
314 | menuItem.clicked.connect(function() { | | |||
315 | slider.forceRaiseMaxVolume = !slider.forceRaiseMaxVolume; | | |||
316 | if (!slider.forceRaiseMaxVolume && Volume > PulseAudio.NormalVolume) { | | |||
317 | Volume = PulseAudio.NormalVolume; | | |||
318 | } | | |||
319 | }); | | |||
320 | contextMenu.addMenuItem(menuItem); | | |||
321 | | ||||
322 | // Switch all streams of the relevant kind to this device | | |||
323 | if (type == "source") { | | |||
324 | menuItem = newMenuItem(); | | |||
325 | menuItem.text = i18n("Record all audio via this device"); | | |||
326 | menuItem.icon = "mic-on" // or "mic-ready" // or "audio-input-microphone-symbolic" | | |||
327 | menuItem.clicked.connect(function() { | | |||
328 | PulseObject.switchStreams(); | | |||
329 | }); | | |||
330 | contextMenu.addMenuItem(menuItem); | | |||
331 | } else if (type == "sink") { | | |||
332 | menuItem = newMenuItem(); | | |||
333 | menuItem.text = i18n("Play all audio via this device"); | | |||
334 | menuItem.icon = "audio-on" // or "audio-ready" // or "audio-speakers-symbolic" | | |||
335 | menuItem.clicked.connect(function() { | | |||
336 | PulseObject.switchStreams(); | | |||
337 | }); | | |||
338 | contextMenu.addMenuItem(menuItem); | | |||
339 | } | | |||
340 | | ||||
341 | // Choose output / input device | | |||
342 | // By choice only shown when there are at least two options | | |||
343 | if ((type == "sink-input" && sinkView.model.count > 1) || (type == "source-input" && sourceView.model.count > 1)) { | | |||
344 | contextMenu.addMenuItem(newSeperator()); | | |||
345 | var menuItem = newMenuItem(); | | |||
346 | if (type == "sink-input") { | | |||
347 | menuItem.text = i18nc("Heading for a list of possible output devices (speakers, headphones, ...) to choose", "Play audio using"); | | |||
348 | } else { | | |||
349 | menuItem.text = i18nc("Heading for a list of possible input devices (built-in microphone, headset, ...) to choose", "Record audio using"); | | |||
350 | } | | |||
351 | menuItem.section = true; | | |||
352 | contextMenu.addMenuItem(menuItem); | | |||
353 | var sModel = type == "sink-input" ? sinkView.model : sourceView.model; | | |||
354 | | ||||
355 | for (var i = 0; i < sModel.count; ++i) { | | |||
356 | var data = sModel.get(i); | | |||
357 | var menuItem = newMenuItem(); | | |||
358 | menuItem.text = data.Description; | | |||
359 | menuItem.enabled = true; | | |||
360 | menuItem.checkable = true; | | |||
361 | menuItem.checked = data.Index === PulseObject.deviceIndex; | | |||
362 | var setActiveSink = function(sinkIndex) { | | |||
363 | return function() { | | |||
364 | PulseObject.deviceIndex = sinkIndex; | | |||
365 | }; | | |||
366 | }; | | |||
367 | menuItem.clicked.connect(setActiveSink(data.Index)); | | |||
368 | contextMenu.addMenuItem(menuItem); | | |||
369 | } | | |||
370 | } | | |||
371 | } | | |||
372 | | ||||
373 | function show() { | | |||
374 | loadDynamicActions(); | | |||
375 | openRelative(); | | |||
376 | } | | |||
377 | } | | |||
378 | } | 279 | } |