waffles: action center: volume menu

This commit is contained in:
end-4
2025-11-19 23:39:18 +01:00
parent bca177eed2
commit 5c8d824749
42 changed files with 680 additions and 129 deletions
@@ -76,7 +76,8 @@ Singleton {
}
property QtObject pixelSize: QtObject {
property real normal: 11
property real large: 14
property real large: 13
property real larger: 15
}
}
@@ -78,11 +78,14 @@ Item {
}
}
Item {
Rectangle {
id: contentArea
color: "red"
z: 0
anchors.fill: borderRect
anchors.margins: borderRect.border.width
implicitWidth: contentItem.implicitWidth
implicitHeight: contentItem.implicitHeight
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {
@@ -15,6 +15,7 @@ Button {
property color colBackgroundToggled: Looks.colors.accent
property color colBackgroundToggledHover: Looks.colors.accentHover
property color colBackgroundToggledActive: Looks.colors.accentActive
property color colForeground: Looks.colors.fg
property alias backgroundOpacity: backgroundRect.opacity
property color color: {
if (root.checked) {
@@ -35,7 +36,29 @@ Button {
}
}
// Hover stuff
signal hoverTimedOut()
property bool shouldShowTooltip: false
property Timer hoverTimer: Timer {
id: hoverTimer
running: root.hovered
interval: 400
onTriggered: {
root.hoverTimedOut()
}
}
onHoverTimedOut: {
root.shouldShowTooltip = true
}
onHoveredChanged: {
if (!root.hovered) {
root.shouldShowTooltip = false
root.hoverTimer.stop()
}
}
property alias monochromeIcon: buttonIcon.monochrome
property alias buttonSpacing: contentLayout.spacing
property bool forceShowIcon: false
property var altAction: () => {}
@@ -93,16 +116,16 @@ Button {
spacing: 12
FluentIcon {
id: buttonIcon
visible: root.icon.name !== "" || root.forceShowIcon
monochrome: true
implicitSize: 16
Layout.leftMargin: 6
Layout.leftMargin: root.iconLeftMargin
Layout.fillWidth: false
Layout.alignment: Qt.AlignVCenter
icon: root.icon.name
color: root.colForeground
visible: root.icon.name !== ""
}
WText {
Layout.rightMargin: 12
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
text: root.text
@@ -110,6 +133,7 @@ Button {
font {
pixelSize: Looks.font.pixelSize.large
}
color: root.colForeground
}
}
}
@@ -0,0 +1,67 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs
import qs.services
import qs.modules.common
import qs.modules.common.functions
import qs.modules.common.widgets
import qs.modules.waffle.looks
WButton {
id: root
Layout.fillWidth: true
implicitWidth: contentItem.implicitWidth
horizontalPadding: 10
verticalPadding: 11
inset: 0
buttonSpacing: 8
property color color: {
if (root.checked) {
if (root.down) {
return root.colBackgroundHover;
} else if (root.hovered && !root.down) {
return root.colBackgroundActive;
} else {
return root.colBackgroundHover;
}
}
if (root.down) {
return root.colBackgroundActive;
} else if (root.hovered && !root.down) {
return root.colBackgroundHover;
} else {
return root.colBackground;
}
}
background: Rectangle {
id: backgroundRect
radius: Looks.radius.medium
color: root.color
Behavior on color {
animation: Looks.transition.color.createObject(this)
}
WFadeLoader {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
shown: root.checked
sourceComponent: Rectangle {
implicitWidth: 3
implicitHeight: 3
radius: width / 2
color: Looks.colors.accent
Component.onCompleted: {
implicitHeight = 16;
}
Behavior on implicitHeight {
animation: Looks.transition.opacity.createObject(this)
}
}
}
}
}
@@ -0,0 +1,19 @@
import QtQuick
import qs.modules.common
// Yes, this is (mostly) a copy of FadeLoader.
// The animation of a Behavior cannot be changed... I'd love to be proven wrong.
Loader {
id: root
property bool shown: true
property alias fade: opacityBehavior.enabled
property alias animation: opacityBehavior.animation
opacity: shown ? 1 : 0
visible: opacity > 0
active: opacity > 0
Behavior on opacity {
id: opacityBehavior
animation: Looks.transition.opacity.createObject(null)
}
}
@@ -8,24 +8,34 @@ Singleton {
id: root
property string internetIcon: {
if (Network.ethernet) return "ethernet";
if (Network.ethernet)
return "ethernet";
if (Network.wifiEnabled) {
const strength = Network.networkStrength;
if (strength > 75) return "wifi-1";
if (strength > 50) return "wifi-2";
if (strength > 25) return "wifi-3";
if (strength > 75)
return "wifi-1";
if (strength > 50)
return "wifi-2";
if (strength > 25)
return "wifi-3";
return "wifi-4";
}
if (Network.wifiStatus === "connecting") return "wifi-4";
if (Network.wifiStatus === "disconnected") return "wifi-off";
if (Network.wifiStatus === "disabled") return "wifi-off";
if (Network.wifiStatus === "connecting")
return "wifi-4";
if (Network.wifiStatus === "disconnected")
return "wifi-off";
if (Network.wifiStatus === "disabled")
return "wifi-off";
return "wifi-warning";
}
property string batteryIcon: {
if (Battery.isCharging) return "battery-charge";
if (Battery.isCriticalAndNotCharging) return "battery-warning";
if (Battery.percentage >= 0.9) return "battery-full";
if (Battery.isCharging)
return "battery-charge";
if (Battery.isCriticalAndNotCharging)
return "battery-warning";
if (Battery.percentage >= 0.9)
return "battery-full";
return `battery-${Math.ceil(Battery.percentage * 10)}`;
}
@@ -33,7 +43,7 @@ Singleton {
const muted = Audio.sink?.audio.muted ?? false;
const volume = Audio.sink?.audio.volume ?? 0;
if (muted)
return volume > 0 ? "speaker-off" : "speaker-none";
return "speaker-mute";
if (volume == 0)
return "speaker-none";
if (volume < 0.5)
@@ -53,10 +63,39 @@ Singleton {
property string notificationsIcon: Notifications.silent ? "alert-snooze" : "alert"
property string powerProfileIcon: {
switch(PowerProfiles.profile) {
case PowerProfile.PowerSaver: return "leaf-two";
case PowerProfile.Balanced: return "flash-on";
case PowerProfile.Performance: return "fire";
switch (PowerProfiles.profile) {
case PowerProfile.PowerSaver:
return "leaf-two";
case PowerProfile.Balanced:
return "flash-on";
case PowerProfile.Performance:
return "fire";
}
}
function audioDeviceIcon(node) {
if (!node.isSink)
return "mic-on";
const monitor = /monitor|hdmi/i;
const headphones = /headset|headphone|bluez|wireless/i;
const speakers = /speaker|output/i;
if (monitor.test(node.nickname) || monitor.test(node.description) || monitor.test(node.name)) {
return "desktop-speaker";
}
if (headphones.test(node.nickname) || headphones.test(node.description) || headphones.test(node.name)) {
return "headphones";
}
if (speakers.test(node.nickname) || speakers.test(node.description) || speakers.test(node.name)) {
return "speaker";
}
return "speaker";
}
function audioAppIcon(node) {
let icon;
icon = AppSearch.guessIcon(node?.properties["application.icon-name"] ?? "");
if (AppSearch.iconExists(icon)) return icon;
icon = AppSearch.guessIcon(node?.properties["node.name"] ?? "");
return icon;
}
}
@@ -10,6 +10,7 @@ WButton {
id: root
property alias iconName: iconContent.icon
property alias monochrome: iconContent.monochrome
inset: 0
implicitWidth: 40
implicitHeight: 40
@@ -10,37 +10,22 @@ import qs.modules.waffle.looks
PopupToolTip {
id: root
property Item realContentItem
required property Item realContentItem
realContentItem: WText {
text: root.text
anchors.centerIn: parent
}
property real visualMargin: 11
verticalPadding: visualMargin
horizontalPadding: visualMargin
property real realContentVerticalPadding: 8
property real realContentHorizontalPadding: 10
verticalPadding: 8
horizontalPadding: 10
verticalMargin: visualMargin
horizontalMargin: visualMargin
contentItem: Item {
anchors.centerIn: parent
implicitWidth: realContent.implicitWidth + 2 * 2
implicitHeight: realContent.implicitHeight + 2 * 2
WAmbientShadow {
target: realContent
}
Rectangle {
id: realContent
z: 1
anchors.centerIn: parent
implicitWidth: root.realContentItem.implicitWidth + root.realContentHorizontalPadding * 2
implicitHeight: root.realContentItem.implicitHeight + root.realContentVerticalPadding * 2
color: Looks.colors.bg1
radius: Looks.radius.medium
children: [root.realContentItem]
}
contentItem: WToolTipContent {
id: tooltipContent
realContentItem: root.realContentItem
horizontalPadding: root.horizontalPadding
verticalPadding: root.verticalPadding
}
}
@@ -10,8 +10,7 @@ Slider {
id: root
property real trackWidth: 4
// leftPadding: handle.width / 2
// rightPadding: handle.width / 2
property string tooltipContent: `${Math.round(value * 100)}`
leftPadding: 0
rightPadding: 0
@@ -77,5 +76,14 @@ Slider {
animation: Looks.transition.enter.createObject(this)
}
}
WToolTip {
id: tooltip
extraVisibleCondition: root.pressed
text: root.tooltipContent
font.pixelSize: Looks.font.pixelSize.larger
verticalPadding: 3
horizontalPadding: 8
}
}
}
@@ -0,0 +1,34 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import qs.modules.common
import qs.modules.common.functions
import qs.modules.common.widgets
import qs.modules.waffle.looks
StyledToolTip {
id: root
required property Item realContentItem
font {
family: Looks.font.family.ui
pixelSize: Looks.font.pixelSize.normal
weight: Looks.font.weight.regular
}
realContentItem: WText {
text: root.text
font: root.font
anchors.centerIn: parent
}
verticalPadding: 8
horizontalPadding: 10
contentItem: WToolTipContent {
id: tooltipContent
realContentItem: root.realContentItem
horizontalPadding: root.horizontalPadding
verticalPadding: root.verticalPadding
}
}
@@ -0,0 +1,29 @@
import QtQuick
import Quickshell
import qs.modules.waffle.looks
Item {
id: root
anchors.centerIn: parent
required property Item realContentItem
property real verticalPadding: 8
property real horizontalPadding: 10
implicitWidth: realContent.implicitWidth + 2 * 2
implicitHeight: realContent.implicitHeight + 2 * 2
WAmbientShadow {
target: realContent
}
Rectangle {
id: realContent
z: 1
anchors.centerIn: parent
implicitWidth: root.realContentItem.implicitWidth + root.horizontalPadding * 2
implicitHeight: root.realContentItem.implicitHeight + root.verticalPadding * 2
color: Looks.colors.bg1
radius: Looks.radius.medium
children: [root.realContentItem]
}
}