@@ -12,6 +12,9 @@ ColumnLayout {
1212 id: root
1313 spacing: Common .Appearance .spacing .large
1414
15+ // Refresh devices when view opens
16+ Component .onCompleted : Services .Audio .refreshDevices ()
17+
1518 // Header with close button
1619 RowLayout {
1720 Layout .fillWidth : true
@@ -215,6 +218,16 @@ ColumnLayout {
215218 color: Common .Appearance .m3colors .onSurfaceVariant
216219 }
217220 }
221+
222+ // Output device selector
223+ DeviceSelector {
224+ Layout .fillWidth : true
225+ label: " Output Device"
226+ devices: Services .Audio .sinks
227+ onDeviceSelected : function (name ) {
228+ Services .Audio .setDefaultSink (name)
229+ }
230+ }
218231 }
219232 }
220233
@@ -399,9 +412,146 @@ ColumnLayout {
399412 color: Common .Appearance .m3colors .onSurfaceVariant
400413 }
401414 }
415+
416+ // Input device selector
417+ DeviceSelector {
418+ Layout .fillWidth : true
419+ label: " Input Device"
420+ devices: Services .Audio .sources
421+ onDeviceSelected : function (name ) {
422+ Services .Audio .setDefaultSource (name)
423+ }
424+ }
402425 }
403426 }
404427
405428 // Spacer
406429 Item { Layout .fillHeight : true }
430+
431+ // Device selector dropdown component
432+ component DeviceSelector: ColumnLayout {
433+ id: selector
434+ property string label: " "
435+ property var devices: []
436+ property bool expanded: false
437+
438+ signal deviceSelected (string name)
439+
440+ spacing: Common .Appearance .spacing .small
441+
442+ // Current selection / dropdown trigger
443+ MouseArea {
444+ Layout .fillWidth : true
445+ Layout .preferredHeight : 40
446+ cursorShape: Qt .PointingHandCursor
447+ hoverEnabled: true
448+
449+ onClicked: selector .expanded = ! selector .expanded
450+
451+ Rectangle {
452+ anchors .fill : parent
453+ radius: Common .Appearance .rounding .medium
454+ color: parent .containsMouse ? Common .Appearance .surfaceLayer (2 ) : Common .Appearance .surfaceLayer (1 )
455+ }
456+
457+ RowLayout {
458+ anchors .fill : parent
459+ anchors .leftMargin : Common .Appearance .spacing .small
460+ anchors .rightMargin : Common .Appearance .spacing .small
461+ spacing: Common .Appearance .spacing .small
462+
463+ ColumnLayout {
464+ Layout .fillWidth : true
465+ spacing: 0
466+
467+ Text {
468+ text: selector .label
469+ font .family : Common .Appearance .fonts .main
470+ font .pixelSize : Common .Appearance .fontSize .small
471+ color: Common .Appearance .m3colors .onSurfaceVariant
472+ }
473+
474+ Text {
475+ Layout .fillWidth : true
476+ text: {
477+ for (let i = 0 ; i < selector .devices .length ; i++ ) {
478+ if (selector .devices [i].isDefault ) {
479+ return selector .devices [i].description
480+ }
481+ }
482+ return " No device"
483+ }
484+ font .family : Common .Appearance .fonts .main
485+ font .pixelSize : Common .Appearance .fontSize .normal
486+ color: Common .Appearance .m3colors .onSurface
487+ elide: Text .ElideRight
488+ }
489+ }
490+
491+ Text {
492+ text: selector .expanded ? Common .Icons .icons .expand : Common .Icons .icons .collapse
493+ font .family : Common .Appearance .fonts .icon
494+ font .pixelSize : Common .Appearance .sizes .iconSmall
495+ color: Common .Appearance .m3colors .onSurfaceVariant
496+ }
497+ }
498+ }
499+
500+ // Dropdown list
501+ ColumnLayout {
502+ visible: selector .expanded
503+ Layout .fillWidth : true
504+ spacing: 2
505+
506+ Repeater {
507+ model: selector .devices
508+
509+ MouseArea {
510+ Layout .fillWidth : true
511+ Layout .preferredHeight : 36
512+ cursorShape: Qt .PointingHandCursor
513+ hoverEnabled: true
514+
515+ onClicked: {
516+ selector .deviceSelected (modelData .name )
517+ selector .expanded = false
518+ }
519+
520+ Rectangle {
521+ anchors .fill : parent
522+ radius: Common .Appearance .rounding .small
523+ color: modelData .isDefault
524+ ? Common .Appearance .m3colors .primaryContainer
525+ : (parent .containsMouse ? Common .Appearance .surfaceLayer (2 ) : " transparent" )
526+ }
527+
528+ RowLayout {
529+ anchors .fill : parent
530+ anchors .leftMargin : Common .Appearance .spacing .small
531+ anchors .rightMargin : Common .Appearance .spacing .small
532+ spacing: Common .Appearance .spacing .small
533+
534+ Text {
535+ Layout .fillWidth : true
536+ text: modelData .description
537+ font .family : Common .Appearance .fonts .main
538+ font .pixelSize : Common .Appearance .fontSize .normal
539+ color: modelData .isDefault
540+ ? Common .Appearance .m3colors .onPrimaryContainer
541+ : Common .Appearance .m3colors .onSurface
542+ elide: Text .ElideRight
543+ }
544+
545+ Text {
546+ visible: modelData .isDefault
547+ text: Common .Icons .icons .check
548+ font .family : Common .Appearance .fonts .icon
549+ font .pixelSize : Common .Appearance .sizes .iconSmall
550+ color: Common .Appearance .m3colors .onPrimaryContainer
551+ }
552+ }
553+ }
554+ }
555+ }
556+ }
407557}
0 commit comments