dcontent: impl bt device details
This commit is contained in:
parent
806c29a02f
commit
365b993221
4 changed files with 348 additions and 6 deletions
|
|
@ -16,5 +16,6 @@ QtObject {
|
||||||
property BluetoothDevice active
|
property BluetoothDevice active
|
||||||
property BluetoothAdapter currentAdapter: Bluetooth.defaultAdapter
|
property BluetoothAdapter currentAdapter: Bluetooth.defaultAdapter
|
||||||
property bool editingAdapterName
|
property bool editingAdapterName
|
||||||
|
property bool fabMenuOpen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,9 +72,6 @@ RowLayout {
|
||||||
id: details
|
id: details
|
||||||
|
|
||||||
Details {
|
Details {
|
||||||
anchors.margins: Appearance.padding.normal
|
|
||||||
anchors.leftMargin: Appearance.padding.normal / 2
|
|
||||||
|
|
||||||
session: root.session
|
session: root.session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,337 @@
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import ".."
|
import ".."
|
||||||
import qs.widgets
|
import qs.widgets
|
||||||
import qs.services
|
import qs.services
|
||||||
import qs.config
|
import qs.config
|
||||||
import Quickshell
|
import qs.utils
|
||||||
import Quickshell.Bluetooth
|
import Quickshell.Bluetooth
|
||||||
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Effects
|
||||||
|
|
||||||
ColumnLayout {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property Session session
|
required property Session session
|
||||||
|
readonly property BluetoothDevice device: session.bt.active
|
||||||
|
|
||||||
spacing: Appearance.spacing.normal
|
StyledFlickable {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
contentHeight: layout.height
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: layout
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: Icons.getBluetoothIcon(root.device.icon)
|
||||||
|
font.pointSize: Appearance.font.size.extraLarge * 3
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: root.device.name
|
||||||
|
font.pointSize: Appearance.font.size.large
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.topMargin: Appearance.spacing.large
|
||||||
|
text: qsTr("Connection status")
|
||||||
|
font.pointSize: Appearance.font.size.larger
|
||||||
|
font.weight: 500
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: qsTr("Connection settings for this device")
|
||||||
|
color: Colours.palette.m3outline
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: adapterStatus.implicitHeight + Appearance.padding.large * 2
|
||||||
|
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
color: Colours.palette.m3surfaceContainer
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: adapterStatus
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.margins: Appearance.padding.large
|
||||||
|
|
||||||
|
spacing: Appearance.spacing.larger
|
||||||
|
|
||||||
|
Toggle {
|
||||||
|
label: qsTr("Connected")
|
||||||
|
checked: root.device.connected
|
||||||
|
toggle.onToggled: root.device.connected = checked
|
||||||
|
}
|
||||||
|
|
||||||
|
Toggle {
|
||||||
|
label: qsTr("Paired")
|
||||||
|
checked: root.device.paired
|
||||||
|
toggle.onToggled: {
|
||||||
|
if (root.device.paired)
|
||||||
|
root.device.forget();
|
||||||
|
else
|
||||||
|
root.device.pair();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Toggle {
|
||||||
|
label: qsTr("Blocked")
|
||||||
|
checked: root.device.blocked
|
||||||
|
toggle.onToggled: root.device.blocked = checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.right: fabRoot.right
|
||||||
|
anchors.bottom: fabRoot.top
|
||||||
|
anchors.bottomMargin: Appearance.padding.normal
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: fabMenu
|
||||||
|
|
||||||
|
model: [
|
||||||
|
{
|
||||||
|
icon: "handshake",
|
||||||
|
label: root.device.trusted ? qsTr("Untrust") : qsTr("Trust"),
|
||||||
|
onClicked: () => root.device.trusted = !root.device.trusted
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "block",
|
||||||
|
label: root.device.blocked ? qsTr("Unblock") : qsTr("Block"),
|
||||||
|
onClicked: () => root.device.blocked = !root.device.blocked
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "missing_controller",
|
||||||
|
label: root.device.paired ? qsTr("Unpair") : qsTr("Pair"),
|
||||||
|
onClicked: () => {
|
||||||
|
if (root.device.paired)
|
||||||
|
root.device.forget();
|
||||||
|
else
|
||||||
|
root.device.pair();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "bluetooth_connected",
|
||||||
|
label: root.device.connected ? qsTr("Disconnect") : qsTr("Connect"),
|
||||||
|
onClicked: () => root.device.connected = !root.device.connected
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
StyledClippingRect {
|
||||||
|
id: fabMenuItem
|
||||||
|
|
||||||
|
required property var modelData
|
||||||
|
required property int index
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
|
||||||
|
implicitHeight: fabMenuItemInner.implicitHeight + Appearance.padding.larger * 2
|
||||||
|
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
color: Colours.palette.m3primaryContainer
|
||||||
|
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
states: State {
|
||||||
|
name: "visible"
|
||||||
|
when: root.session.bt.fabMenuOpen
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
fabMenuItem.implicitWidth: fabMenuItemInner.implicitWidth + Appearance.padding.large * 2
|
||||||
|
fabMenuItem.opacity: 1
|
||||||
|
fabMenuItemInner.opacity: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transitions: [
|
||||||
|
Transition {
|
||||||
|
to: "visible"
|
||||||
|
|
||||||
|
SequentialAnimation {
|
||||||
|
PauseAnimation {
|
||||||
|
duration: (fabMenu.count - 1 - fabMenuItem.index) * Appearance.anim.durations.small / 8
|
||||||
|
}
|
||||||
|
ParallelAnimation {
|
||||||
|
Anim {
|
||||||
|
property: "implicitWidth"
|
||||||
|
duration: Appearance.anim.durations.expressiveFastSpatial
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
|
||||||
|
}
|
||||||
|
Anim {
|
||||||
|
property: "opacity"
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Transition {
|
||||||
|
from: "visible"
|
||||||
|
|
||||||
|
SequentialAnimation {
|
||||||
|
PauseAnimation {
|
||||||
|
duration: fabMenuItem.index * Appearance.anim.durations.small / 8
|
||||||
|
}
|
||||||
|
ParallelAnimation {
|
||||||
|
Anim {
|
||||||
|
property: "implicitWidth"
|
||||||
|
duration: Appearance.anim.durations.expressiveFastSpatial
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
|
||||||
|
}
|
||||||
|
Anim {
|
||||||
|
property: "opacity"
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
function onClicked(): void {
|
||||||
|
root.session.bt.fabMenuOpen = false;
|
||||||
|
fabMenuItem.modelData.onClicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: fabMenuItemInner
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
text: fabMenuItem.modelData.icon
|
||||||
|
color: Colours.palette.m3onPrimaryContainer
|
||||||
|
fill: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: fabMenuItem.modelData.label
|
||||||
|
color: Colours.palette.m3onPrimaryContainer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: fabRoot
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
|
implicitWidth: 64
|
||||||
|
implicitHeight: 64
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
id: fabBg
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
|
||||||
|
implicitWidth: 64
|
||||||
|
implicitHeight: 64
|
||||||
|
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
color: root.session.bt.fabMenuOpen ? Colours.palette.m3primary : Colours.palette.m3primaryContainer
|
||||||
|
|
||||||
|
states: State {
|
||||||
|
name: "expanded"
|
||||||
|
when: root.session.bt.fabMenuOpen
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
fabBg.implicitWidth: 48
|
||||||
|
fabBg.implicitHeight: 48
|
||||||
|
fabBg.radius: 48 / 2
|
||||||
|
fab.font.pointSize: Appearance.font.size.larger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transitions: Transition {
|
||||||
|
Anim {
|
||||||
|
properties: "implicitWidth,implicitHeight"
|
||||||
|
duration: Appearance.anim.durations.expressiveFastSpatial
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
|
||||||
|
}
|
||||||
|
Anim {
|
||||||
|
properties: "radius,font.pointSize"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Elevation {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: parent.radius
|
||||||
|
z: -1
|
||||||
|
level: fabState.containsMouse && !fabState.pressed ? 4 : 3
|
||||||
|
}
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
id: fabState
|
||||||
|
|
||||||
|
color: root.session.bt.fabMenuOpen ? Colours.palette.m3onPrimary : Colours.palette.m3onPrimaryContainer
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
root.session.bt.fabMenuOpen = !root.session.bt.fabMenuOpen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: fab
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
animate: true
|
||||||
|
text: root.session.bt.fabMenuOpen ? "close" : "settings"
|
||||||
|
color: root.session.bt.fabMenuOpen ? Colours.palette.m3onPrimary : Colours.palette.m3onPrimaryContainer
|
||||||
|
font.pointSize: Appearance.font.size.large
|
||||||
|
fill: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on radius {
|
||||||
|
Anim {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component Toggle: RowLayout {
|
||||||
|
required property string label
|
||||||
|
property alias checked: toggle.checked
|
||||||
|
property alias toggle: toggle
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: parent.label
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledSwitch {
|
||||||
|
id: toggle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component Anim: NumberAnimation {
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.standard
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
widgets/Elevation.qml
Normal file
22
widgets/Elevation.qml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import qs.services
|
||||||
|
import qs.config
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
|
|
||||||
|
RectangularShadow {
|
||||||
|
property int level
|
||||||
|
property real dp: [0, 1, 3, 6, 8, 12][level]
|
||||||
|
|
||||||
|
color: Qt.alpha(Colours.palette.m3shadow, 0.7)
|
||||||
|
blur: (dp * 5) ** 0.7
|
||||||
|
spread: -dp * 0.3 + (dp * 0.1) ** 2
|
||||||
|
offset.y: dp / 2
|
||||||
|
|
||||||
|
Behavior on dp {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.standard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue