diff --git a/constants/Icons.qml b/constants/Icons.qml index 4126c27..b905db8 100644 --- a/constants/Icons.qml +++ b/constants/Icons.qml @@ -3,6 +3,10 @@ pragma Singleton import Quickshell Singleton { + property string batteryFull: "\u{E059}" + property string batteryMedium: "\u{E05b}" + property string batteryLow: "\u{E05a}" + property string batteryWarning: "\u{E3b0}" property string bell: "\u{E05d}" property string bellRing: "\u{E224}" property string bluetooth: "\u{E060}" diff --git a/modules/bar/Bar.qml b/modules/bar/Bar.qml index 66eae2c..961775d 100644 --- a/modules/bar/Bar.qml +++ b/modules/bar/Bar.qml @@ -1,5 +1,6 @@ import qs.config import QtQuick +import QtQuick.Layouts import Quickshell import "components" import "components/bluetooth" @@ -39,7 +40,7 @@ Scope { } } - Row { + RowLayout { id: leftbar anchors.left: parent.left @@ -52,20 +53,15 @@ Scope { spacing: Dimensions.bar.spacing SystemLogo { - anchors.verticalCenter: parent.verticalCenter implicitSize: 22 } - Workspaces { - anchors.verticalCenter: parent.verticalCenter - } + Workspaces {} - Tray { - anchors.verticalCenter: parent.verticalCenter - } + Tray {} } - Row { + RowLayout { id: centerbar anchors.horizontalCenter: parent.horizontalCenter @@ -76,12 +72,10 @@ Scope { spacing: Dimensions.bar.spacing - Mpris { - anchors.verticalCenter: parent.verticalCenter - } + Mpris {} } - Row { + RowLayout { id: rightbar anchors.right: parent.right @@ -93,49 +87,27 @@ Scope { spacing: Dimensions.bar.spacing - Pywal { - anchors.verticalCenter: parent.verticalCenter - } + Pywal {} - Pipewire { - anchors.verticalCenter: parent.verticalCenter - } + Pipewire {} - Caffeine { - anchors.verticalCenter: parent.verticalCenter - } + Caffeine {} - Network { - anchors.verticalCenter: parent.verticalCenter - } + Network {} - Bluetooth { - anchors.verticalCenter: parent.verticalCenter - } + Bluetooth {} - Storage { - anchors.verticalCenter: parent.verticalCenter - } + Storage {} - Memory { - anchors.verticalCenter: parent.verticalCenter - } + Memory {} - Cpu { - anchors.verticalCenter: parent.verticalCenter - } + Cpu {} - Gpu { - anchors.verticalCenter: parent.verticalCenter - } + Gpu {} - Clock { - anchors.verticalCenter: parent.verticalCenter - } + Clock {} - Notifications { - anchors.verticalCenter: parent.verticalCenter - } + Notifications {} } } } diff --git a/modules/bar/components/bluetooth/BluetoothMenu.qml b/modules/bar/components/bluetooth/BluetoothMenu.qml index ed896c3..b85fec6 100644 --- a/modules/bar/components/bluetooth/BluetoothMenu.qml +++ b/modules/bar/components/bluetooth/BluetoothMenu.qml @@ -1,9 +1,8 @@ pragma ComponentBehavior: Bound import qs.config -import qs.constants import qs.services -import qs.styled +import qs.widgets import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -29,6 +28,7 @@ StyledPopupWindow { } Switch { + Layout.alignment: Qt.AlignRight checked: Bluetooth.defaultAdapter.enabled onClicked: Bluetooth.defaultAdapter.enabled = checked } @@ -43,12 +43,18 @@ StyledPopupWindow { spacing: 8 StyledText { + Layout.minimumWidth: 320 font.bold: true text: "Connected Devices" } - DeviceList { - devices: Bluetooth.connectedDevices + ColumnLayout { + Repeater { + model: Bluetooth.connectedDevices + delegate: ConnectedDevice { + Layout.fillWidth: true + } + } } StyledText { @@ -56,8 +62,13 @@ StyledPopupWindow { text: "Paired Devices" } - DeviceList { - devices: Bluetooth.pairedDevices + ColumnLayout { + Repeater { + model: Bluetooth.pairedDevices + delegate: PairedDevice { + Layout.fillWidth: true + } + } } StyledText { @@ -67,6 +78,9 @@ StyledPopupWindow { DeviceList { devices: Bluetooth.availableDevices + onDeviceActivated: device => { + device.pair(); + } } } } diff --git a/modules/bar/components/bluetooth/ConnectedDevice.qml b/modules/bar/components/bluetooth/ConnectedDevice.qml new file mode 100644 index 0000000..c59fa2b --- /dev/null +++ b/modules/bar/components/bluetooth/ConnectedDevice.qml @@ -0,0 +1,94 @@ +pragma ComponentBehavior: Bound + +import qs.config +import qs.constants +import qs.widgets +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Bluetooth +import Quickshell.Widgets + +StyledLabel { + id: device + required property BluetoothDevice modelData + + RowLayout { + id: row + + spacing: 8 + + Loader { + active: modelData.icon != undefined + sourceComponent: IconImage { + implicitSize: 18 + source: Quickshell.iconPath(modelData.icon) + } + } + + StyledText { + text: device.modelData.deviceName + } + + Loader { + active: device.modelData.batteryAvailable + sourceComponent: RowLayout { + StyledText { + id: icon + font.family: Theme.lucide.font.family + font.pixelSize: Dimensions.cpu.iconSize + font.bold: true + text: Icons.batteryFull + states: [ + State { + name: "full" + when: device.modelData.battery > 0.66 + }, + State { + name: "medium" + when: device.modelData.battery > 0.33 + PropertyChanges { + icon { + text: Icons.batteryFull + } + } + }, + State { + name: "low" + when: device.modelData.battery > 0.10 + PropertyChanges { + icon { + text: Icons.batteryFull + } + } + }, + State { + name: "critical" + when: device.modelData.battery > 0.10 + PropertyChanges { + icon { + text: Icons.batteryWarning + color: Theme.palette.error + } + } + } + ] + } + } + } + + StyledButton { + Layout.alignment: Qt.AlignRight + color: containsMouse ? Theme.palette.error : Theme.palette.base200 + content: StyledText { + text: 'Disconnect' + } + onClicked: { + if (modelData.state != BluetoothDeviceState.Connected) { + return; + } + modelData.disconnect(); + } + } + } +} diff --git a/modules/bar/components/bluetooth/DeviceList.qml b/modules/bar/components/bluetooth/DeviceList.qml index 6508c8a..c4e5d92 100644 --- a/modules/bar/components/bluetooth/DeviceList.qml +++ b/modules/bar/components/bluetooth/DeviceList.qml @@ -1,16 +1,18 @@ +pragma ComponentBehavior: Bound + import qs.config -import qs.constants -import qs.services import qs.styled import QtQuick import QtQuick.Layouts +import Quickshell.Bluetooth ColumnLayout { id: root required property var devices + signal deviceActivated(device: BluetoothDevice) Repeater { - model: devices + model: root.devices delegate: Clickable { id: device required property var modelData @@ -18,6 +20,9 @@ ColumnLayout { implicitWidth: row.width implicitHeight: row.height Layout.fillWidth: true + onClicked: { + root.deviceActivated(modelData); + } RowLayout { id: row diff --git a/modules/bar/components/bluetooth/PairedDevice.qml b/modules/bar/components/bluetooth/PairedDevice.qml new file mode 100644 index 0000000..2512344 --- /dev/null +++ b/modules/bar/components/bluetooth/PairedDevice.qml @@ -0,0 +1,64 @@ +pragma ComponentBehavior: Bound + +import qs.config +import qs.constants +import qs.widgets +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Bluetooth +import Quickshell.Widgets + +StyledLabel { + id: device + required property BluetoothDevice modelData + + RowLayout { + id: row + + spacing: 8 + + Loader { + active: modelData.icon != undefined + sourceComponent: IconImage { + implicitSize: 18 + source: Quickshell.iconPath(device.modelData.icon) + } + } + + StyledText { + text: device.modelData.deviceName + } + + RowLayout { + Layout.alignment: Qt.AlignRight + StyledButton { + hoverEnabled: device.modelData.state == BluetoothDeviceState.Disconnected + color: containsMouse ? Theme.palette.info : Theme.palette.base200 + content: StyledText { + text: 'Connect' + } + onClicked: { + if (!hoverEnabled) { + return; + } + device.modelData.connect(); + } + } + + StyledButton { + hoverEnabled: device.modelData.state == BluetoothDeviceState.Disconnected + color: containsMouse ? Theme.palette.error : Theme.palette.base200 + content: StyledText { + text: 'Unpair' + } + onClicked: { + if (!hoverEnabled) { + return; + } + device.modelData.forget(); + } + } + } + } +} diff --git a/modules/bar/components/mpris/Mpris.qml b/modules/bar/components/mpris/Mpris.qml index b129e77..8c39c15 100644 --- a/modules/bar/components/mpris/Mpris.qml +++ b/modules/bar/components/mpris/Mpris.qml @@ -8,8 +8,6 @@ Item { property int currentIndex: 0 property var players: Mpris.players - anchors.horizontalCenter: parent.horizontalCenter - Repeater { id: players model: Mpris.players.values.filter(item => item != null) diff --git a/modules/bar/components/tray/menu/Menu.qml b/modules/bar/components/tray/menu/Menu.qml index 52d1627..4d49037 100644 --- a/modules/bar/components/tray/menu/Menu.qml +++ b/modules/bar/components/tray/menu/Menu.qml @@ -1,16 +1,16 @@ pragma ComponentBehavior: Bound +import qs.config +import qs.widgets import QtQuick import QtQuick.Layouts import Quickshell -import "../../../../../config/" -import "../../../../../styled/" StyledPopupWindow { id: window backgroundColor: Theme.palette.base300 - margins: 8 + margins: 14 radius: 8 property QsMenuOpener menuOpener @@ -25,7 +25,7 @@ StyledPopupWindow { active: true Layout.fillWidth: true - Layout.minimumWidth: 120 + Layout.minimumWidth: 160 sourceComponent: modelData.isSeparator ? menuSeperator : menuItem property Component menuSeperator: Rectangle { diff --git a/modules/bar/components/tray/menu/MenuItem.qml b/modules/bar/components/tray/menu/MenuItem.qml index 58b550b..bdf866c 100644 --- a/modules/bar/components/tray/menu/MenuItem.qml +++ b/modules/bar/components/tray/menu/MenuItem.qml @@ -1,28 +1,12 @@ +import qs.widgets import Quickshell -import "../../../../../config/" -import "../../../../../styled/" -Clickable { - id: item +StyledButton { + id: root property QsMenuEntry menuEntry - - implicitWidth: text.width - implicitHeight: 30 - onClicked: menuEntry.triggered() - - StyledText { - id: text - - opacity: item.opacity - - font.pixelSize: Dimensions.clock.fontSize - anchors.verticalCenter: parent.verticalCenter - topPadding: Dimensions.clock.verticalPadding - bottomPadding: Dimensions.clock.verticalPadding - leftPadding: Dimensions.clock.horizontalPadding - rightPadding: Dimensions.clock.horizontalPadding - - text: item.menuEntry.text + content: StyledText { + font.pixelSize: 14 + text: root.menuEntry.text } } diff --git a/services/Bluetooth.qml b/services/Bluetooth.qml index 0904672..d802ac8 100644 --- a/services/Bluetooth.qml +++ b/services/Bluetooth.qml @@ -8,7 +8,7 @@ Singleton { property BluetoothAdapter defaultAdapter: Bluetooth.defaultAdapter property list connectedDevices: defaultAdapter.devices.values.filter(device => device.connected) - property list pairedDevices: defaultAdapter.devices.values.filter(device => device.paired) + property list pairedDevices: defaultAdapter.devices.values.filter(device => device.paired && !device.connected) property list availableDevices: defaultAdapter.devices.values.filter(device => !device.paired) function isConnected(BluetoothDevice: device) { diff --git a/widgets/StyledButton.qml b/widgets/StyledButton.qml index 3ac2ee6..c14e4f3 100644 --- a/widgets/StyledButton.qml +++ b/widgets/StyledButton.qml @@ -26,7 +26,7 @@ WrapperMouseArea { } Loader { active: true - sourceComponent: content + sourceComponent: root.content } } } diff --git a/widgets/StyledLabel.qml b/widgets/StyledLabel.qml index 13781b9..4b9dd07 100644 --- a/widgets/StyledLabel.qml +++ b/widgets/StyledLabel.qml @@ -4,7 +4,6 @@ import Quickshell.Widgets WrapperRectangle { id: root - required property Component content margin: 8 radius: 8 color: Theme.palette.base100 diff --git a/styled/StyledPopupWindow.qml b/widgets/StyledPopupWindow.qml similarity index 97% rename from styled/StyledPopupWindow.qml rename to widgets/StyledPopupWindow.qml index cd6374b..f409be8 100644 --- a/styled/StyledPopupWindow.qml +++ b/widgets/StyledPopupWindow.qml @@ -60,7 +60,7 @@ PopupWindow { Loader { active: root.visible - sourceComponent: content + sourceComponent: root.content } } }