refractor quick toggles data, add volume slider for waffles action center

This commit is contained in:
end-4
2025-11-17 23:43:25 +01:00
parent 9228165428
commit fcee7ce6f9
55 changed files with 939 additions and 470 deletions
@@ -0,0 +1,113 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs
import qs.services
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
Rectangle {
id: root
property int currentPage: 0
property alias columns: grid.columns
property alias rows: grid.rows
readonly property int itemsPerPage: columns * rows
property list<string> toggles: Config.options.waffles.actionCenter.toggles
property list<string> togglesInCurrentPage: toggles.slice(currentPage * itemsPerPage, (currentPage + 1) * itemsPerPage)
Layout.fillHeight: true
Layout.fillWidth: true
color: Looks.colors.bgPanelBody
implicitWidth: 360
implicitHeight: contentLayout.implicitHeight
ColumnLayout {
id: contentLayout
anchors.fill: parent
spacing: 0
Item {
id: togglesContainer
property real padding: 22
Layout.fillWidth: true
Layout.bottomMargin: -12
implicitHeight: grid.implicitHeight + padding * 2
GridLayout {
id: grid
anchors {
fill: parent
margins: parent.padding
}
columns: 3
rows: 2
rowSpacing: 12
columnSpacing: 12
uniformCellHeights: true
uniformCellWidths: true
Repeater {
model: ScriptModel {
values: root.togglesInCurrentPage
}
delegate: ActionCenterToggle {
required property var modelData
name: modelData
}
}
}
// TODO: pages indicator on the right
}
Rectangle {
implicitHeight: 1
Layout.fillWidth: true
color: Looks.colors.bg1Border
}
RowLayout {
Layout.margins: 12
Layout.topMargin: 18
Layout.bottomMargin: 14
spacing: 4
WPanelIconButton {
iconName: WIcons.volumeIcon
onClicked: {
Audio.sink.audio.muted = !Audio.sink.audio.muted;
}
}
WSlider {
Layout.fillWidth: true
value: Audio.sink.audio.volume
onMoved: {
Audio.sink.audio.volume = value;
}
}
WPanelIconButton {
contentItem: Item {
anchors.centerIn: parent
Row {
anchors.centerIn: parent
spacing: -1
FluentIcon {
anchors.verticalCenter: parent.verticalCenter
implicitSize: 18
icon: "settings"
}
FluentIcon {
anchors.verticalCenter: parent.verticalCenter
implicitSize: 12
icon: "chevron-right"
}
}
}
}
}
}
}
@@ -14,15 +14,9 @@ WBarAttachedPanelContent {
anchors.centerIn: parent
spacing: 0
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
ActionCenterBody {
topLeftRadius: root.border.radius - root.border.border.width
topRightRadius: topLeftRadius
color: Looks.colors.bgPanelBody
implicitWidth: 360
implicitHeight: 380
}
Rectangle {
@@ -32,46 +26,9 @@ WBarAttachedPanelContent {
implicitHeight: 1
}
Rectangle {
Layout.fillHeight: false
Layout.fillWidth: true
ActionCenterFooter {
bottomLeftRadius: root.border.radius - root.border.border.width
bottomRightRadius: bottomLeftRadius
color: Looks.colors.bgPanelFooter
implicitWidth: 360
implicitHeight: 47
// Battery button
WPanelFooterButton {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 12
contentItem: Row {
spacing: 4
FluentIcon {
anchors.verticalCenter: parent.verticalCenter
icon: WIcons.batteryIcon
}
WText {
anchors.verticalCenter: parent.verticalCenter
text: `${Math.round(Battery.percentage * 100) || 0}%`
}
}
}
// Settings button
WPanelFooterButton {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 12
contentItem: FluentIcon {
icon: "settings"
}
}
}
}
}
@@ -0,0 +1,49 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs
import qs.services
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
Rectangle {
Layout.fillHeight: false
Layout.fillWidth: true
color: Looks.colors.bgPanelFooter
implicitWidth: 360
implicitHeight: 47
// Battery button
WPanelFooterButton {
visible: Battery.available
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 12
contentItem: Row {
spacing: 4
FluentIcon {
anchors.verticalCenter: parent.verticalCenter
icon: WIcons.batteryIcon
}
WText {
anchors.verticalCenter: parent.verticalCenter
text: `${Math.round(Battery.percentage * 100) || 0}%`
}
}
}
// Settings button
WPanelFooterButton {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 12
contentItem: FluentIcon {
icon: "settings"
}
}
}
@@ -0,0 +1,40 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
// It should be perfectly fine to use just a Column here, but somehow
// using ColumnLayout prevents weird opening anim stutter
ColumnLayout {
id: root
property alias name: toggleNameText.text
Rectangle {
Layout.fillWidth: true
implicitWidth: 96
implicitHeight: 48
color: "transparent"
border.width: 1
border.color: Looks.colors.bg0Border // ???
radius: Looks.radius.medium
}
Item {
implicitHeight: 36
Layout.fillWidth: true
WText {
id: toggleNameText
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
right: parent.right
}
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
text: "Toggle"
}
}
}
@@ -0,0 +1,16 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs.services
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
import qs.modules.waffle.actionCenter
ActionCenterToggle {
id: root
name: Network.ethernet ? Translation.tr("Network") : Network.networkName
}
@@ -3,6 +3,7 @@ import QtQuick.Layouts
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.waffle.looks
BarButton {
@@ -38,22 +39,15 @@ BarButton {
id: volumeHoverArea
iconItem: FluentIcon {
anchors.verticalCenter: parent.verticalCenter
icon: {
const muted = Audio.sink?.audio.muted ?? false;
const volume = Audio.sink?.audio.volume ?? 0;
if (muted)
return volume > 0 ? "speaker-off" : "speaker-none";
if (volume == 0)
return "speaker-none";
if (volume < 0.5)
return "speaker-1";
return "speaker";
}
icon: WIcons.volumeIcon
}
onScrollDown: Audio.decrementVolume();
onScrollUp: Audio.incrementVolume();
}
IconHoverArea {
id: batteryHoverArea
visible: Battery?.available ?? false
iconItem: FluentIcon {
anchors.verticalCenter: parent.verticalCenter
icon: WIcons.batteryIcon
@@ -62,7 +56,7 @@ BarButton {
}
}
component IconHoverArea: MouseArea {
component IconHoverArea: FocusedScrollMouseArea {
id: hoverArea
required property var iconItem
anchors {
@@ -85,6 +85,7 @@ AppButton {
BarMenu {
id: contextMenu
noSmoothClosing: false // On the real thing this is always smooth
model: [
...((root.desktopEntry?.actions.length > 0) ? root.desktopEntry.actions.map(action =>({
@@ -35,6 +35,8 @@ Singleton {
property color bg2Border: root.dark ? "#464646" : "#EEEEEE"
property color fg: root.dark ? "#FFFFFF" : "#000000"
property color fg1: root.dark ? "#D1D1D1" : "#626262"
property color controlBg: root.dark ? "#9B9B9B" : "#868686"
property color controlFg: root.dark ? "#454545" : "#FFFFFF"
property color danger: "#C42B1C"
property color dangerActive: "#B62D1F"
property color warning: "#FF9900"
@@ -71,6 +73,9 @@ Singleton {
transition: QtObject {
id: transition
property int velocity: 850
property QtObject easing: QtObject {
property QtObject bezierCurve: QtObject {
readonly property list<real> easeInOut: [0.42,0.00,0.58,1.00,1,1]
@@ -27,5 +27,16 @@ Singleton {
if (Battery.percentage >= 0.9) return "battery-full";
return `battery-${Math.ceil(Battery.percentage * 10)}`;
}
property string volumeIcon: {
const muted = Audio.sink?.audio.muted ?? false;
const volume = Audio.sink?.audio.volume ?? 0;
if (muted)
return volume > 0 ? "speaker-off" : "speaker-none";
if (volume == 0)
return "speaker-none";
if (volume < 0.5)
return "speaker-1";
return "speaker";
}
}
@@ -0,0 +1,23 @@
import QtQuick
import Quickshell
import qs
import qs.services
import qs.modules.common
import qs.modules.waffle.looks
import qs.modules.waffle.bar
WButton {
id: root
property alias iconName: iconContent.icon
inset: 0
implicitWidth: 40
implicitHeight: 40
contentItem: FluentIcon {
id: iconContent
anchors.centerIn: parent
implicitSize: 18
icon: root.iconName
}
}
@@ -0,0 +1,81 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Widgets
import qs.modules.common
import qs.modules.common.widgets
Slider {
id: root
property real trackWidth: 4
// leftPadding: handle.width / 2
// rightPadding: handle.width / 2
leftPadding: 0
rightPadding: 0
implicitHeight: handle.implicitHeight
Behavior on value { // This makes the adjusted value (like volume) shift smoothly
SmoothedAnimation {
velocity: Looks.transition.velocity
}
}
background: Item {
id: background
anchors.fill: parent
Rectangle {
id: trackHighlight
anchors {
left: parent.left
verticalCenter: parent.verticalCenter
}
topLeftRadius: root.trackWidth / 2
bottomLeftRadius: root.trackWidth / 2
color: Looks.colors.accent
implicitHeight: root.trackWidth
width: background.width * root.visualPosition
}
Rectangle {
id: trackTrough
anchors {
right: parent.right
verticalCenter: parent.verticalCenter
}
topLeftRadius: root.trackWidth / 2
bottomLeftRadius: root.trackWidth / 2
color: Looks.colors.controlBg
implicitHeight: root.trackWidth
width: background.width * (1 - root.visualPosition)
}
}
handle: Circle {
id: handle
anchors.verticalCenter: parent.verticalCenter
x: (diameter / 2) + root.visualPosition * (root.width - diameter) - (diameter / 2)
diameter: 20
color: Looks.colors.controlFg
MouseArea {
id: handleMouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
}
Circle {
anchors.centerIn: parent
diameter: root.pressed ? 10 : handleMouseArea.containsMouse ? 14 : 12
color: Looks.colors.accent
Behavior on diameter {
animation: Looks.transition.enter.createObject(this)
}
}
}
}