menu: bluetooth settings

This commit is contained in:
2026-02-05 16:41:27 +02:00
parent a3a782163a
commit 887b477c5e
2 changed files with 150 additions and 20 deletions

View File

@@ -2,6 +2,7 @@ import QtQuick
import Quickshell
import Quickshell.Widgets
import Quickshell.Services.Mpris
import Quickshell.Bluetooth
FloatingWindow {
title: "Quickshell debugger"
@@ -43,6 +44,29 @@ FloatingWindow {
font.pixelSize: 32
}
Repeater {
model: Bluetooth.devices
Item {
y: 16 * index
Text {
text: "bt" + index + modelData.name
color: "#04047C"
font.family: "Determination Mono"
font.pixelSize: 16
y: 64 + 128 + 1
x: 64 + 1 + 512
}
Text {
text: "bt" + index + modelData.name
color: "#ff0000"
font.family: "Determination Mono"
font.pixelSize: 16
y: 64 + 128
x: 64 + 512
}
}
}
Repeater {
model: Mpris.players
Item {
@@ -54,7 +78,7 @@ FloatingWindow {
asynchronous: true
}
Text {
text: "mpris" + index + JSON.stringify(modelData.metadata, undefined, "\t")
text: "mpris" + index + JSON.stringify(modelData, undefined, "\t")
color: "#04047C"
font.family: "Determination Mono"
font.pixelSize: 16
@@ -62,7 +86,7 @@ FloatingWindow {
x: 64 + 1
}
Text {
text: "mpris" + index + JSON.stringify(modelData.metadata, undefined, "\t")
text: "mpris" + index + JSON.stringify(modelData, undefined, "\t")
color: "#ff0000"
font.family: "Determination Mono"
font.pixelSize: 16

View File

@@ -1,4 +1,5 @@
import QtQuick
import Quickshell.Bluetooth
import Quickshell.Services.Pipewire
import "../.."
@@ -28,6 +29,7 @@ Item {
property ShellStateManager manager: null
property int activeSelection: 0
property bool inBluetoothMenu: false
property bool isSelected: false
@@ -35,20 +37,75 @@ Item {
return Math.max(lo, Math.min(hi, v));
}
function wrapIndex(i) {
if (actions.length === 0)
function menuLength() {
if (!menuModel)
return 0;
return (i + actions.length) % actions.length;
if (menuModel.count !== undefined)
return menuModel.count;
if (menuModel.length !== undefined)
return menuModel.length;
return 0;
}
function menuAt(index) {
if (!menuModel)
return null;
if (menuModel.get)
return menuModel.get(index);
if (menuModel.length !== undefined)
return menuModel[index];
return null;
}
function wrapIndex(i) {
const length = menuLength();
if (length === 0)
return 0;
return (i + length) % length;
}
function currentAction() {
return actions.length > 0 ? actions[activeSelection] : null;
if (root.inBluetoothMenu)
return null;
return menuLength() > 0 ? menuAt(activeSelection) : null;
}
function clampSelection() {
const length = menuLength();
if (length === 0) {
activeSelection = 0;
return;
}
activeSelection = clamp(activeSelection, 0, length - 1);
}
function bluetoothDisplayName(device) {
if (!device)
return "";
if (device.name && device.name.length > 0)
return device.name;
return device.deviceName || "";
}
function bluetoothDisplayState(device) {
if (!device)
return "";
// dont change symbols
return device.connected ? "✓" : "";
}
function bluetoothDeviceAt(index) {
const item = bluetoothRepeater.itemAt(index);
if (!item)
return null;
return item.device || null;
}
PwObjectTracker {
objects: [Pipewire.defaultAudioSink]
}
property int bluetoothActionIndex: 1
property var actions: [
{
name: "Master Volume",
@@ -68,17 +125,44 @@ Item {
}
},
{
name: "Controls",
ent: function () {},
name: "Bluetooth",
ent: function () {
root.inBluetoothMenu = true;
root.isSelected = false;
root.activeSelection = 0;
root.clampSelection();
},
getState: function () {
console.log("deltarune tommorow");
return "";
}
}
]
property var menuModel: root.inBluetoothMenu ? Bluetooth.devices : actions
Connections {
target: Bluetooth.devices
ignoreUnknownSignals: true
function onCountChanged() {
if (root.inBluetoothMenu)
root.clampSelection();
}
function onModelReset() {
if (root.inBluetoothMenu)
root.clampSelection();
}
function onRowsInserted() {
if (root.inBluetoothMenu)
root.clampSelection();
}
function onRowsRemoved() {
if (root.inBluetoothMenu)
root.clampSelection();
}
}
Text {
text: "CONFIG"
text: root.inBluetoothMenu ? "BLUETOOTH" : "CONFIG"
font.family: "8bitoperator JVE"
font.pixelSize: 71
renderType: Text.NativeRendering
@@ -91,7 +175,8 @@ Item {
}
Repeater {
model: root.actions
id: bluetoothRepeater
model: root.menuModel
delegate: Item {
width: root.width
@@ -99,6 +184,8 @@ Item {
x: 0
y: menuTop + index * lineHeight
property var device: root.inBluetoothMenu ? modelData : null
Image {
source: "./soul.png"
width: 36
@@ -111,7 +198,7 @@ Item {
Text {
x: 239
y: 0
text: modelData.name
text: root.inBluetoothMenu ? root.bluetoothDisplayName(modelData) : modelData.name
font.family: "8bitoperator JVE"
font.pixelSize: 71
font.letterSpacing: 1
@@ -126,7 +213,7 @@ Item {
Text {
x: menuLeft + stateColumnX
y: 4
text: modelData.getState ? modelData.getState() : ""
text: root.inBluetoothMenu ? root.bluetoothDisplayState(modelData) : (modelData.getState ? modelData.getState() : "")
font.family: "8bitoperator JVE"
font.pixelSize: 71
font.letterSpacing: 1
@@ -146,11 +233,11 @@ Item {
function handleKey(key) {
switch (key) {
case Qt.Key_Up:
if (root.isSelected === false)
if (root.inBluetoothMenu || root.isSelected === false)
activeSelection = wrapIndex(activeSelection - 1);
return true;
case Qt.Key_Down:
if (root.isSelected === false)
if (root.inBluetoothMenu || root.isSelected === false)
activeSelection = wrapIndex(activeSelection + 1);
return true;
case Qt.Key_Left:
@@ -171,18 +258,36 @@ Item {
case Qt.Key_Return:
case Qt.Key_Enter:
{
const a = currentAction();
if (a && a.ent) {
a.ent();
if (root.inBluetoothMenu) {
const device = bluetoothDeviceAt(activeSelection);
console.log(root.inBluetoothMenu, activeSelection, device);
if (device) {
if (!device.connected) {
device.connect();
} else {
device.disconnect();
}
// device.connected = !device.connected;
}
} else {
root.isSelected = !root.isSelected;
const a = currentAction();
if (a && a.ent) {
a.ent();
} else {
root.isSelected = !root.isSelected;
}
}
return true;
}
case Qt.Key_X:
case Qt.Key_Shift:
case Qt.Key_Escape:
if (root.isSelected === true) {
if (root.inBluetoothMenu) {
root.inBluetoothMenu = false;
root.isSelected = false;
root.activeSelection = root.bluetoothActionIndex;
root.clampSelection();
} else if (root.isSelected === true) {
root.isSelected = false;
} else {
if (manager && manager.closeQuickSettings) {
@@ -197,6 +302,7 @@ Item {
Component.onCompleted: {
root.activeSelection = 0;
root.isSelected = false;
root.inBluetoothMenu = false;
ShellInputManager.registerHandler("quickSettings", handleKey);
}