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 BluetoothAdapter currentAdapter: Bluetooth.defaultAdapter
|
||||
property bool editingAdapterName
|
||||
property bool fabMenuOpen
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,9 +72,6 @@ RowLayout {
|
|||
id: details
|
||||
|
||||
Details {
|
||||
anchors.margins: Appearance.padding.normal
|
||||
anchors.leftMargin: Appearance.padding.normal / 2
|
||||
|
||||
session: root.session
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,337 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import ".."
|
||||
import qs.widgets
|
||||
import qs.services
|
||||
import qs.config
|
||||
import Quickshell
|
||||
import qs.utils
|
||||
import Quickshell.Bluetooth
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Effects
|
||||
|
||||
ColumnLayout {
|
||||
Item {
|
||||
id: root
|
||||
|
||||
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