forked from Shinonome/dots-hyprland
refractor quick toggles data, add volume slider for waffles action center
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user