dcontent: add bt pane
This commit is contained in:
parent
978e038a26
commit
be6b19ad21
6 changed files with 323 additions and 72 deletions
|
|
@ -67,7 +67,7 @@ ColumnLayout {
|
|||
id: device
|
||||
|
||||
required property BluetoothDevice modelData
|
||||
readonly property bool loading: device.modelData.state === BluetoothDeviceState.Connecting || device.modelData.state === BluetoothDeviceState.Disconnecting
|
||||
readonly property bool loading: modelData.state === BluetoothDeviceState.Connecting || modelData.state === BluetoothDeviceState.Disconnecting
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: Appearance.padding.small
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import "bluetooth"
|
||||
import qs.widgets
|
||||
import qs.services
|
||||
import qs.config
|
||||
import Quickshell.Widgets
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Effects
|
||||
|
||||
ClippingRectangle {
|
||||
id: root
|
||||
|
|
@ -24,23 +24,21 @@ ClippingRectangle {
|
|||
y: -root.session.activeIndex * root.height
|
||||
|
||||
Pane {
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Work in progress")
|
||||
color: Colours.palette.m3outline
|
||||
font.pointSize: Appearance.font.size.extraLarge
|
||||
font.weight: 500
|
||||
index: 0
|
||||
sourceComponent: Item {
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Work in progress")
|
||||
color: Colours.palette.m3outline
|
||||
font.pointSize: Appearance.font.size.extraLarge
|
||||
font.weight: 500
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Work in progress")
|
||||
color: Colours.palette.m3outline
|
||||
font.pointSize: Appearance.font.size.extraLarge
|
||||
font.weight: 500
|
||||
}
|
||||
index: 1
|
||||
sourceComponent: BtPane {}
|
||||
}
|
||||
|
||||
Behavior on y {
|
||||
|
|
@ -52,71 +50,31 @@ ClippingRectangle {
|
|||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
anchors.fill: parent
|
||||
color: Colours.palette.m3surfaceContainer
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect {
|
||||
maskSource: mask
|
||||
maskEnabled: true
|
||||
maskInverted: true
|
||||
maskThresholdMin: 0.5
|
||||
maskSpreadAtMin: 1
|
||||
}
|
||||
InnerBorder {
|
||||
leftThickness: 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: mask
|
||||
|
||||
anchors.fill: parent
|
||||
layer.enabled: true
|
||||
visible: false
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Appearance.padding.normal
|
||||
anchors.leftMargin: 0
|
||||
radius: Appearance.rounding.small
|
||||
}
|
||||
}
|
||||
|
||||
component Pane: Loader {
|
||||
component Pane: Item {
|
||||
id: pane
|
||||
|
||||
default property Item child
|
||||
required property int index
|
||||
property alias sourceComponent: loader.sourceComponent
|
||||
|
||||
asynchronous: true
|
||||
active: {
|
||||
const ly = -layout.y;
|
||||
const ty = layout.children.indexOf(this) * root.height;
|
||||
return ly + root.height > ty && ly < ty + root.height;
|
||||
}
|
||||
implicitWidth: root.width
|
||||
implicitHeight: root.height
|
||||
|
||||
sourceComponent: Item {
|
||||
implicitWidth: root.width
|
||||
implicitHeight: root.height
|
||||
Loader {
|
||||
id: loader
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Appearance.padding.normal
|
||||
anchors.leftMargin: 0
|
||||
anchors.fill: parent
|
||||
asynchronous: true
|
||||
active: {
|
||||
if (root.session.activeIndex === pane.index)
|
||||
return true;
|
||||
|
||||
children: [pane.child]
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
anchors.fill: parent
|
||||
color: Colours.palette.m3surfaceContainer
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect {
|
||||
maskSource: mask
|
||||
maskEnabled: true
|
||||
maskInverted: true
|
||||
maskThresholdMin: 0.5
|
||||
maskSpreadAtMin: 1
|
||||
}
|
||||
const ly = -layout.y;
|
||||
const ty = pane.index * root.height;
|
||||
return ly + root.height > ty && ly < ty + root.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
42
modules/detachedcontent/bluetooth/BtPane.qml
Normal file
42
modules/detachedcontent/bluetooth/BtPane.qml
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.widgets
|
||||
import qs.config
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
spacing: 0
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: Math.floor(parent.width / 3)
|
||||
Layout.fillHeight: true
|
||||
|
||||
DeviceList {
|
||||
anchors.margins: Appearance.padding.large + Appearance.padding.normal
|
||||
anchors.leftMargin: Appearance.padding.large
|
||||
anchors.rightMargin: Appearance.padding.large + Appearance.padding.normal / 2
|
||||
}
|
||||
|
||||
InnerBorder {
|
||||
leftThickness: 0
|
||||
rightThickness: Appearance.padding.normal / 2
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
Details {
|
||||
anchors.margins: Appearance.padding.normal
|
||||
anchors.leftMargin: Appearance.padding.normal / 2
|
||||
}
|
||||
|
||||
InnerBorder {
|
||||
leftThickness: Appearance.padding.normal / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
8
modules/detachedcontent/bluetooth/Details.qml
Normal file
8
modules/detachedcontent/bluetooth/Details.qml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import qs.widgets
|
||||
import qs.services
|
||||
import qs.config
|
||||
import Quickshell
|
||||
import Quickshell.Bluetooth
|
||||
import QtQuick.Layouts
|
||||
|
||||
ColumnLayout {}
|
||||
200
modules/detachedcontent/bluetooth/DeviceList.qml
Normal file
200
modules/detachedcontent/bluetooth/DeviceList.qml
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
import qs.widgets
|
||||
import qs.services
|
||||
import qs.config
|
||||
import qs.utils
|
||||
import Quickshell
|
||||
import Quickshell.Bluetooth
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
anchors.fill: parent
|
||||
spacing: Appearance.spacing.small
|
||||
|
||||
StyledText {
|
||||
text: qsTr("Settings")
|
||||
font.pointSize: Appearance.font.size.large
|
||||
font.weight: 500
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: qsTr("General bluetooth settings")
|
||||
color: Colours.palette.m3outline
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: settingsText.implicitHeight + Appearance.padding.normal * 2
|
||||
|
||||
radius: Appearance.rounding.normal
|
||||
color: Colours.palette.m3surfaceContainer
|
||||
|
||||
StateLayer {}
|
||||
|
||||
StyledText {
|
||||
id: settingsText
|
||||
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Bluetooth settings")
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.topMargin: Appearance.spacing.large
|
||||
text: qsTr("Devices")
|
||||
font.pointSize: Appearance.font.size.large
|
||||
font.weight: 500
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: qsTr("All available bluetooth devices")
|
||||
color: Colours.palette.m3outline
|
||||
}
|
||||
|
||||
StyledListView {
|
||||
model: ScriptModel {
|
||||
values: [...Bluetooth.devices.values].sort((a, b) => (b.connected - a.connected) || (b.paired - a.paired))
|
||||
}
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
|
||||
ScrollBar.vertical: StyledScrollBar {}
|
||||
|
||||
delegate: StyledRect {
|
||||
id: device
|
||||
|
||||
required property BluetoothDevice modelData
|
||||
readonly property bool loading: modelData.state === BluetoothDeviceState.Connecting || modelData.state === BluetoothDeviceState.Disconnecting
|
||||
readonly property bool connected: modelData.state === BluetoothDeviceState.Connected
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
implicitHeight: deviceInner.implicitHeight + Appearance.padding.normal * 2
|
||||
|
||||
StateLayer {
|
||||
id: stateLayer
|
||||
|
||||
function onClicked(): void {
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: deviceInner
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Appearance.padding.normal
|
||||
anchors.leftMargin: Appearance.padding.large
|
||||
anchors.rightMargin: Appearance.padding.large
|
||||
|
||||
spacing: Appearance.spacing.normal
|
||||
|
||||
StyledRect {
|
||||
implicitWidth: implicitHeight
|
||||
implicitHeight: icon.implicitHeight + Appearance.padding.normal * 2
|
||||
|
||||
radius: Appearance.rounding.full
|
||||
color: device.connected ? Colours.palette.m3primaryContainer : device.modelData.bonded ? Colours.palette.m3secondaryContainer : Colours.palette.m3surfaceContainerHigh
|
||||
|
||||
StyledRect {
|
||||
anchors.fill: parent
|
||||
radius: parent.radius
|
||||
color: Qt.alpha(device.connected ? Colours.palette.m3onPrimaryContainer : device.modelData.bonded ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface, stateLayer.pressed ? 0.1 : stateLayer.containsMouse ? 0.08 : 0)
|
||||
}
|
||||
|
||||
MaterialIcon {
|
||||
id: icon
|
||||
|
||||
anchors.centerIn: parent
|
||||
text: Icons.getBluetoothIcon(device.modelData.icon)
|
||||
color: device.connected ? Colours.palette.m3onPrimaryContainer : device.modelData.bonded ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
|
||||
font.pointSize: Appearance.font.size.large
|
||||
fill: device.connected ? 1 : 0
|
||||
|
||||
Behavior on fill {
|
||||
Anim {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
spacing: 0
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
text: device.modelData.name
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
text: device.modelData.address + (device.connected ? qsTr(" (Connected)") : device.modelData.bonded ? qsTr(" (Paired)") : "")
|
||||
color: Colours.palette.m3outline
|
||||
font.pointSize: Appearance.font.size.small
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
id: connectBtn
|
||||
|
||||
implicitWidth: implicitHeight
|
||||
implicitHeight: connectIcon.implicitHeight + Appearance.padding.small * 2
|
||||
|
||||
radius: Appearance.rounding.full
|
||||
color: device.connected ? Colours.palette.m3primaryContainer : "transparent"
|
||||
|
||||
StyledBusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
|
||||
implicitWidth: implicitHeight
|
||||
implicitHeight: connectIcon.implicitHeight
|
||||
|
||||
running: opacity > 0
|
||||
opacity: device.loading ? 1 : 0
|
||||
|
||||
Behavior on opacity {
|
||||
Anim {}
|
||||
}
|
||||
}
|
||||
|
||||
StateLayer {
|
||||
color: device.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
|
||||
disabled: device.loading
|
||||
|
||||
function onClicked(): void {
|
||||
device.modelData.connected = !device.modelData.connected;
|
||||
}
|
||||
}
|
||||
|
||||
MaterialIcon {
|
||||
id: connectIcon
|
||||
|
||||
anchors.centerIn: parent
|
||||
animate: true
|
||||
text: device.modelData.connected ? "link_off" : "link"
|
||||
color: device.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
|
||||
|
||||
opacity: device.loading ? 0 : 1
|
||||
|
||||
Behavior on opacity {
|
||||
Anim {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component Anim: NumberAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
43
widgets/InnerBorder.qml
Normal file
43
widgets/InnerBorder.qml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.services
|
||||
import qs.config
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
|
||||
StyledRect {
|
||||
property alias innerRadius: maskInner.radius
|
||||
property alias thickness: maskInner.anchors.margins
|
||||
property alias leftThickness: maskInner.anchors.leftMargin
|
||||
property alias topThickness: maskInner.anchors.topMargin
|
||||
property alias rightThickness: maskInner.anchors.rightMargin
|
||||
property alias bottomThickness: maskInner.anchors.bottomMargin
|
||||
|
||||
anchors.fill: parent
|
||||
color: Colours.palette.m3surfaceContainer
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect {
|
||||
maskSource: mask
|
||||
maskEnabled: true
|
||||
maskInverted: true
|
||||
maskThresholdMin: 0.5
|
||||
maskSpreadAtMin: 1
|
||||
}
|
||||
|
||||
Item {
|
||||
id: mask
|
||||
|
||||
anchors.fill: parent
|
||||
layer.enabled: true
|
||||
visible: false
|
||||
|
||||
Rectangle {
|
||||
id: maskInner
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Appearance.padding.normal
|
||||
radius: Appearance.rounding.small
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue