// Copyright (C) 2026 Danilo M. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. import QtQuick import "../.." Column { id: page required property var bt signal back spacing: 14 // --- Adapter --- Item { width: page.width implicitHeight: Math.max(btLabel.implicitHeight, powerSwitch.implicitHeight) Text { id: btLabel anchors.verticalCenter: parent.verticalCenter text: "Bluetooth" font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 1; bold: true } color: Theme.text } Switch { id: powerSwitch anchors { right: parent.right; verticalCenter: parent.verticalCenter } enabled: page.bt.adapter !== null checked: page.bt.adapter ? page.bt.adapter.enabled : false onToggled: if (page.bt.adapter) page.bt.adapter.enabled = checked } } Text { width: page.width visible: !(page.bt.adapter && page.bt.adapter.enabled) text: "Bluetooth off" font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } color: Theme.subtext } Item { width: page.width visible: page.bt.adapter && page.bt.adapter.enabled implicitHeight: Math.max(visLabel.implicitHeight, visSwitch.implicitHeight) Text { id: visLabel anchors.verticalCenter: parent.verticalCenter text: "Visible" font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } color: Theme.text } Switch { id: visSwitch anchors { right: parent.right; verticalCenter: parent.verticalCenter } enabled: page.bt.adapter !== null checked: page.bt.adapter ? page.bt.adapter.discoverable : false onToggled: if (page.bt.adapter) page.bt.adapter.discoverable = checked } } Row { width: page.width visible: page.bt.adapter && page.bt.adapter.enabled spacing: 8 Button { text: page.bt.adapter && page.bt.adapter.discovering ? "Stop scan" : "Scan" onClicked: if (page.bt.adapter) page.bt.adapter.discovering = !page.bt.adapter.discovering } } // --- Connected --- Text { width: page.width visible: page.bt.connectedDevices.length > 0 text: "Connected" font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2; bold: true } color: Theme.subtext } Repeater { model: page.bt.connectedDevices BluetoothRow { required property var modelData bt: page.bt device: modelData width: page.width } } // --- Paired --- Text { width: page.width visible: page.bt.pairedDevices.length > 0 text: "Paired" font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2; bold: true } color: Theme.subtext } Repeater { model: page.bt.pairedDevices BluetoothRow { required property var modelData bt: page.bt device: modelData width: page.width } } // --- Available (found while scanning, not yet paired) --- Text { width: page.width visible: page.bt.availableDevices.length > 0 text: "Available" font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2; bold: true } color: Theme.subtext } Repeater { model: page.bt.availableDevices Rectangle { required property var modelData width: page.width implicitHeight: availText.implicitHeight + 16 radius: 8 color: Qt.alpha(Theme.surface, 0.35) Text { id: availText anchors { left: parent.left; leftMargin: 10; verticalCenter: parent.verticalCenter } width: parent.width - pairBtn.width - 28 elide: Text.ElideRight text: page.bt.pairing.busy && page.bt.pairing.address === modelData.address ? "Pairing…" : (modelData.name || modelData.deviceName || modelData.address) font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } color: Theme.text } Button { id: pairBtn anchors { right: parent.right; rightMargin: 8; verticalCenter: parent.verticalCenter } text: "Pair" enabled: !page.bt.pairing.busy onClicked: page.bt.pairing.pair(modelData.address) } } } Text { width: page.width visible: page.bt.pairing.error !== "" wrapMode: Text.Wrap text: page.bt.pairing.error font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 } color: Theme.red } }