1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-10 15:32:52 -05:00

iBluetooth repair, input device support, some media player improvements

This commit is contained in:
bbedward
2025-07-11 13:50:10 -04:00
parent b4f73ceb7b
commit d169f5d4a3
14 changed files with 1533 additions and 829 deletions

View File

@@ -828,232 +828,532 @@ PanelWindow {
}
// Audio Tab
ScrollView {
Item {
id: audioTabContainer
anchors.fill: parent
anchors.margins: Theme.spacingM
visible: controlCenterPopup.currentTab === 1
clip: true
property int audioSubTab: 0 // 0: Output, 1: Input
Column {
width: parent.width
spacing: Theme.spacingL
anchors.fill: parent
spacing: Theme.spacingM
// Volume Control
Column {
// Audio Sub-tabs
Row {
width: parent.width
spacing: Theme.spacingM
height: 40
spacing: 2
Text {
text: "Volume"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
}
Row {
width: parent.width
spacing: Theme.spacingM
Rectangle {
width: parent.width / 2 - 1
height: parent.height
radius: Theme.cornerRadius
color: audioTabContainer.audioSubTab === 0 ? Theme.primary : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
Text {
text: "volume_down"
font.family: Theme.iconFont
font.pixelSize: Theme.iconSize
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
anchors.centerIn: parent
text: "Output"
font.pixelSize: Theme.fontSizeMedium
color: audioTabContainer.audioSubTab === 0 ? Theme.primaryText : Theme.surfaceText
font.weight: Font.Medium
}
Rectangle {
id: volumeSliderTrack
width: parent.width - 80
height: 8
radius: 4
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
anchors.verticalCenter: parent.verticalCenter
Rectangle {
id: volumeSliderFill
width: parent.width * (root.volumeLevel / 100)
height: parent.height
radius: parent.radius
color: Theme.primary
Behavior on width {
NumberAnimation { duration: 100 }
}
}
// Draggable handle
Rectangle {
id: volumeHandle
width: 18
height: 18
radius: 9
color: Theme.primary
border.color: Qt.lighter(Theme.primary, 1.3)
border.width: 2
x: Math.max(0, Math.min(parent.width - width, volumeSliderFill.width - width/2))
anchors.verticalCenter: parent.verticalCenter
scale: volumeMouseArea.containsMouse || volumeMouseArea.pressed ? 1.2 : 1.0
Behavior on scale {
NumberAnimation { duration: 150 }
}
}
MouseArea {
id: volumeMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => {
let ratio = Math.max(0, Math.min(1, mouse.x / width))
let newVolume = Math.round(ratio * 100)
AudioService.setVolume(newVolume)
}
onPositionChanged: (mouse) => {
if (pressed) {
let ratio = Math.max(0, Math.min(1, mouse.x / width))
let newVolume = Math.round(ratio * 100)
AudioService.setVolume(newVolume)
}
}
}
}
Text {
text: "volume_up"
font.family: Theme.iconFont
font.pixelSize: Theme.iconSize
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: audioTabContainer.audioSubTab = 0
}
}
Text {
text: root.volumeLevel + "%"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
width: parent.width / 2 - 1
height: parent.height
radius: Theme.cornerRadius
color: audioTabContainer.audioSubTab === 1 ? Theme.primary : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
Text {
anchors.centerIn: parent
text: "Input"
font.pixelSize: Theme.fontSizeMedium
color: audioTabContainer.audioSubTab === 1 ? Theme.primaryText : Theme.surfaceText
font.weight: Font.Medium
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: audioTabContainer.audioSubTab = 1
}
}
}
// Output Devices
Column {
// Output Tab Content
ScrollView {
width: parent.width
spacing: Theme.spacingM
height: parent.height - 48
visible: audioTabContainer.audioSubTab === 0
clip: true
Text {
text: "Output Device"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
}
// Current device indicator
Rectangle {
Column {
width: parent.width
height: 35
radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3)
border.width: 1
visible: root.currentAudioSink !== ""
spacing: Theme.spacingL
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
// Volume Control
Column {
width: parent.width
spacing: Theme.spacingM
Text {
text: "check_circle"
font.family: Theme.iconFont
font.pixelSize: Theme.iconSize - 4
color: Theme.primary
}
Text {
text: "Current: " + (function() {
for (let sink of root.audioSinks) {
if (sink.name === root.currentAudioSink) {
return sink.displayName
}
}
return root.currentAudioSink
})()
font.pixelSize: Theme.fontSizeMedium
color: Theme.primary
text: "Volume"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
}
}
}
// Real audio devices
Repeater {
model: root.audioSinks
Rectangle {
width: parent.width
height: 50
radius: Theme.cornerRadius
color: deviceArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) :
(modelData.active ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
border.color: modelData.active ? Theme.primary : "transparent"
border.width: 1
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
width: parent.width
spacing: Theme.spacingM
Text {
text: {
if (modelData.name.includes("bluez")) return "headset"
else if (modelData.name.includes("hdmi")) return "tv"
else if (modelData.name.includes("usb")) return "headset"
else return "speaker"
}
text: "volume_down"
font.family: Theme.iconFont
font.pixelSize: Theme.iconSize
color: modelData.active ? Theme.primary : Theme.surfaceText
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Column {
spacing: 2
Rectangle {
id: volumeSliderTrack
width: parent.width - 80
height: 8
radius: 4
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
anchors.verticalCenter: parent.verticalCenter
Rectangle {
id: volumeSliderFill
width: parent.width * (root.volumeLevel / 100)
height: parent.height
radius: parent.radius
color: Theme.primary
Behavior on width {
NumberAnimation { duration: 100 }
}
}
// Draggable handle
Rectangle {
id: volumeHandle
width: 18
height: 18
radius: 9
color: Theme.primary
border.color: Qt.lighter(Theme.primary, 1.3)
border.width: 2
x: Math.max(0, Math.min(parent.width - width, volumeSliderFill.width - width/2))
anchors.verticalCenter: parent.verticalCenter
scale: volumeMouseArea.containsMouse || volumeMouseArea.pressed ? 1.2 : 1.0
Behavior on scale {
NumberAnimation { duration: 150 }
}
}
MouseArea {
id: volumeMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => {
let ratio = Math.max(0, Math.min(1, mouse.x / width))
let newVolume = Math.round(ratio * 100)
AudioService.setVolume(newVolume)
}
onPositionChanged: (mouse) => {
if (pressed) {
let ratio = Math.max(0, Math.min(1, mouse.x / width))
let newVolume = Math.round(ratio * 100)
AudioService.setVolume(newVolume)
}
}
}
}
Text {
text: "volume_up"
font.family: Theme.iconFont
font.pixelSize: Theme.iconSize
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Text {
text: root.volumeLevel + "%"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
}
// Output Devices
Column {
width: parent.width
spacing: Theme.spacingM
Text {
text: "Output Device"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
}
// Current device indicator
Rectangle {
width: parent.width
height: 35
radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3)
border.width: 1
visible: root.currentAudioSink !== ""
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
Text {
text: modelData.displayName
font.pixelSize: Theme.fontSizeMedium
color: modelData.active ? Theme.primary : Theme.surfaceText
font.weight: modelData.active ? Font.Medium : Font.Normal
text: "check_circle"
font.family: Theme.iconFont
font.pixelSize: Theme.iconSize - 4
color: Theme.primary
}
Text {
text: modelData.active ? "Selected" : ""
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.8)
visible: modelData.active
text: "Current: " + (function() {
for (let sink of root.audioSinks) {
if (sink.name === root.currentAudioSink) {
return sink.displayName
}
}
return root.currentAudioSink
})()
font.pixelSize: Theme.fontSizeMedium
color: Theme.primary
font.weight: Font.Medium
}
}
}
MouseArea {
id: deviceArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
// Real audio devices
Repeater {
model: root.audioSinks
onClicked: {
console.log("Clicked audio device:", JSON.stringify(modelData))
console.log("Device name to set:", modelData.name)
AudioService.setAudioSink(modelData.name)
Rectangle {
width: parent.width
height: 50
radius: Theme.cornerRadius
color: deviceArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) :
(modelData.active ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
border.color: modelData.active ? Theme.primary : "transparent"
border.width: 1
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
Text {
text: {
if (modelData.name.includes("bluez")) return "headset"
else if (modelData.name.includes("hdmi")) return "tv"
else if (modelData.name.includes("usb")) return "headset"
else return "speaker"
}
font.family: Theme.iconFont
font.pixelSize: Theme.iconSize
color: modelData.active ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Column {
spacing: 2
anchors.verticalCenter: parent.verticalCenter
Text {
text: modelData.displayName
font.pixelSize: Theme.fontSizeMedium
color: modelData.active ? Theme.primary : Theme.surfaceText
font.weight: modelData.active ? Font.Medium : Font.Normal
}
Text {
text: modelData.active ? "Selected" : ""
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.8)
visible: modelData.active
}
}
}
MouseArea {
id: deviceArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
console.log("Clicked audio device:", JSON.stringify(modelData))
console.log("Device name to set:", modelData.name)
AudioService.setAudioSink(modelData.name)
}
}
}
}
}
}
}
// Input Tab Content
ScrollView {
width: parent.width
height: parent.height - 48
visible: audioTabContainer.audioSubTab === 1
clip: true
Column {
width: parent.width
spacing: Theme.spacingL
// Microphone Level Control
Column {
width: parent.width
spacing: Theme.spacingM
Text {
text: "Microphone Level"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
}
Row {
width: parent.width
spacing: Theme.spacingM
Text {
text: "mic"
font.family: Theme.iconFont
font.pixelSize: Theme.iconSize
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
id: micSliderTrack
width: parent.width - 80
height: 8
radius: 4
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
anchors.verticalCenter: parent.verticalCenter
Rectangle {
id: micSliderFill
width: parent.width * (root.micLevel / 100)
height: parent.height
radius: parent.radius
color: Theme.primary
Behavior on width {
NumberAnimation { duration: 100 }
}
}
// Draggable handle
Rectangle {
id: micHandle
width: 18
height: 18
radius: 9
color: Theme.primary
border.color: Qt.lighter(Theme.primary, 1.3)
border.width: 2
x: Math.max(0, Math.min(parent.width - width, micSliderFill.width - width/2))
anchors.verticalCenter: parent.verticalCenter
scale: micMouseArea.containsMouse || micMouseArea.pressed ? 1.2 : 1.0
Behavior on scale {
NumberAnimation { duration: 150 }
}
}
MouseArea {
id: micMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => {
let ratio = Math.max(0, Math.min(1, mouse.x / width))
let newMicLevel = Math.round(ratio * 100)
AudioService.setMicLevel(newMicLevel)
}
onPositionChanged: (mouse) => {
if (pressed) {
let ratio = Math.max(0, Math.min(1, mouse.x / width))
let newMicLevel = Math.round(ratio * 100)
AudioService.setMicLevel(newMicLevel)
}
}
}
}
Text {
text: "mic"
font.family: Theme.iconFont
font.pixelSize: Theme.iconSize
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Text {
text: root.micLevel + "%"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
}
// Input Devices
Column {
width: parent.width
spacing: Theme.spacingM
Text {
text: "Input Device"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
}
// Current device indicator
Rectangle {
width: parent.width
height: 35
radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3)
border.width: 1
visible: root.currentAudioSource !== ""
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
Text {
text: "check_circle"
font.family: Theme.iconFont
font.pixelSize: Theme.iconSize - 4
color: Theme.primary
}
Text {
text: "Current: " + (function() {
for (let source of root.audioSources) {
if (source.name === root.currentAudioSource) {
return source.displayName
}
}
return root.currentAudioSource
})()
font.pixelSize: Theme.fontSizeMedium
color: Theme.primary
font.weight: Font.Medium
}
}
}
// Real audio input devices
Repeater {
model: root.audioSources
Rectangle {
width: parent.width
height: 50
radius: Theme.cornerRadius
color: sourceArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) :
(modelData.active ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
border.color: modelData.active ? Theme.primary : "transparent"
border.width: 1
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
Text {
text: {
if (modelData.name.includes("bluez")) return "headset_mic"
else if (modelData.name.includes("usb")) return "headset_mic"
else return "mic"
}
font.family: Theme.iconFont
font.pixelSize: Theme.iconSize
color: modelData.active ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Column {
spacing: 2
anchors.verticalCenter: parent.verticalCenter
Text {
text: modelData.displayName
font.pixelSize: Theme.fontSizeMedium
color: modelData.active ? Theme.primary : Theme.surfaceText
font.weight: modelData.active ? Font.Medium : Font.Normal
}
Text {
text: modelData.active ? "Selected" : ""
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.8)
visible: modelData.active
}
}
}
MouseArea {
id: sourceArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
console.log("Clicked audio source:", JSON.stringify(modelData))
console.log("Source name to set:", modelData.name)
AudioService.setAudioSource(modelData.name)
}
}
}
}
}