Merge branch 'main' into feat/dashboard-media-widget
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 18s
JS/TS / lint (pull_request) Successful in 17s
Python / static (pull_request) Successful in 58s
Rust / fmt (pull_request) Successful in 1m4s
C++ / build (pull_request) Successful in 2m39s
Rust / build (pull_request) Successful in 2m22s
Rust / clippy (pull_request) Successful in 1m48s
Python / verify (pull_request) Successful in 3m29s
C++ / clang-tidy (pull_request) Successful in 7m7s

This commit is contained in:
2026-08-19 00:36:42 +02:00
5 changed files with 237 additions and 74 deletions
@@ -1,101 +1,184 @@
import Quickshell.Bluetooth
import Quickshell.Networking as QSNetwork
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Bluetooth
import Quickshell.Networking as QSNetwork
import ZShell.Components
import qs.Components
import ZShell.Config
import qs.Components
import qs.Services
import qs.Helpers
import qs.Daemons
import qs.Services
import qs.Modules.Settings
import qs.Modules.Bar.Popouts as BarPopouts
CustomRect {
id: root
required property Item popouts
required property var visibilities
readonly property bool needExtraRow: quickToggles.length > 6
required property BarPopouts.Wrapper popouts
readonly property var quickToggles: {
const seenIds = new Set();
return Config.utilities.quickToggles.values.filter(item => {
if (!item.enabled)
return false;
if (seenIds.has(item.id)) {
return false;
}
if (item.id === "bluetooth" && !Bluetooth.defaultAdapter)
return false;
if (item.id === "wifi" && !QSNetwork.Networking.devices.values.some(n => n.type === QSNetwork.DeviceType.Wifi))
return false;
seenIds.add(item.id);
return true;
});
}
readonly property int splitIndex: Math.ceil(quickToggles.length / 2)
required property PersistentProperties visibilities
Layout.fillWidth: true
color: Colors.tPalette.m3surfaceContainer
implicitHeight: layout.implicitHeight + 18 * 2
radius: Tokens.rounding.small
implicitHeight: layout.implicitHeight + Tokens.padding.extraLargeIncreased
radius: Tokens.rounding.smallest
ButtonRow {
ColumnLayout {
id: layout
anchors.fill: parent
anchors.margins: 18
spacing: Tokens.spacing.extraSmall
anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.normal
Toggle {
checked: Network.wifiEnabled
icon: Network.wifiEnabled ? "wifi" : "wifi_off"
visible: QSNetwork.Networking.devices.values.some(n => n.type === QSNetwork.DeviceType.Wifi)
onClicked: Network.toggleWifi()
CustomText {
font.pointSize: Tokens.font.size.normal
text: qsTr("Quick Toggles")
}
Toggle {
id: toggle
checked: !NotifServer.dnd
icon: NotifServer.dnd ? "notifications_off" : "notifications"
onClicked: NotifServer.dnd = !NotifServer.dnd
QuickToggleRow {
model: root.needExtraRow ? root.quickToggles.slice(0, root.splitIndex) : root.quickToggles
}
Toggle {
checked: !Audio.sourceMuted
icon: Audio.sourceMuted ? "mic_off" : "mic"
onClicked: {
const audio = Audio.source?.audio;
if (audio)
audio.muted = !audio.muted;
}
}
Toggle {
checked: !Audio.muted
icon: Audio.muted ? "volume_off" : "volume_up"
onClicked: {
const audio = Audio.sink?.audio;
if (audio)
audio.muted = !audio.muted;
}
}
Toggle {
checked: Bluetooth.defaultAdapter?.enabled ?? false
icon: Bluetooth.defaultAdapter?.enabled ? "bluetooth" : "bluetooth_disabled"
visible: Bluetooth.defaultAdapter ?? false
onClicked: {
const adapter = Bluetooth.defaultAdapter;
if (adapter)
adapter.enabled = !adapter.enabled;
}
}
Toggle {
checked: GameMode.enabled
icon: GameMode.enabled ? "videogame_asset" : "videogame_asset_off"
onClicked: GameMode.enabled = !GameMode.enabled
QuickToggleRow {
model: root.needExtraRow ? root.quickToggles.slice(root.splitIndex) : []
visible: root.needExtraRow
}
}
CustomShortcut {
name: "toggle-dnd"
component QuickToggleRow: ButtonRow {
property alias model: repeater.model
onPressed: {
toggle.clicked();
Layout.fillWidth: true
spacing: Tokens.spacing.small
Repeater {
id: repeater
delegate: DelegateChooser {
role: "id"
DelegateChoice {
roleValue: "wifi"
delegate: Toggle {
checked: Network.wifiEnabled
icon: checked ? "wifi" : "wifi_off"
onClicked: Network.toggleWifi()
}
}
DelegateChoice {
roleValue: "bluetooth"
delegate: Toggle {
checked: Bluetooth.defaultAdapter?.enabled ?? false // qmllint disable unresolved-type
icon: "bluetooth"
onClicked: {
const adapter = Bluetooth.defaultAdapter; // qmllint disable unresolved-type
if (adapter)
adapter.enabled = !adapter.enabled;
}
}
}
DelegateChoice {
roleValue: "mic"
delegate: Toggle {
checked: !Audio.sourceMuted
icon: checked ? "mic" : "mic_off"
onClicked: {
const audio = Audio.source?.audio;
if (audio)
audio.muted = !audio.muted;
}
}
}
DelegateChoice {
roleValue: "audio"
delegate: Toggle {
checked: !Audio.muted
icon: checked ? "volume_up" : "volume_off"
onClicked: {
const audio = Audio.sink?.audio;
if (audio)
audio.muted = !audio.muted;
}
}
}
DelegateChoice {
roleValue: "gameMode"
delegate: Toggle {
checked: GameMode.enabled
icon: "gamepad"
onClicked: GameMode.enabled = !GameMode.enabled
}
}
DelegateChoice {
roleValue: "dnd"
delegate: Toggle {
checked: NotifServer.dnd
icon: "notifications_off"
onClicked: NotifServer.dnd = !NotifServer.dnd
}
}
DelegateChoice {
roleValue: "settings"
delegate: Toggle {
icon: "settings"
inactiveOnColor: Colors.palette.m3onSurfaceVariant
isToggle: false
onClicked: {
root.visibilities.sidebar = false;
root.visibilities.settings = true;
}
}
}
}
}
}
component Toggle: IconButton {
fillWidth: true
inactiveColor: Colors.layer(Colors.palette.m3surfaceContainerHighest, 2)
isRound: true
isToggle: true
shapeMorph: true
@@ -1,13 +1,14 @@
import Quickshell
import QtQuick
import QtQuick.Layouts
import qs.Modules.Bar.Popouts as BarPopouts
import qs.Modules.Notifications.Sidebar.Utils.Cards
import ZShell.Config
Item {
id: root
required property Item popouts
required property BarPopouts.Wrapper popouts
required property PersistentProperties props
required property var visibilities
@@ -30,6 +31,7 @@ Item {
}
Toggles {
Layout.fillWidth: true
popouts: root.popouts
visibilities: root.visibilities
}
@@ -1,15 +1,16 @@
pragma ComponentBehavior: Bound
import qs.Components
import ZShell.Config
import Quickshell
import QtQuick
import Quickshell
import ZShell.Config
import qs.Components
import qs.Modules.Bar.Popouts as BarPopouts
Item {
id: root
property real offsetScale: shouldBeActive ? 0 : 1
required property Item popouts
required property BarPopouts.Wrapper popouts
readonly property PersistentProperties props: PersistentProperties {
property string recordingConfirmDelete
property bool recordingListExpanded: false
@@ -9,6 +9,16 @@ import qs.Modules.Settings.Common
PageBase {
id: root
readonly property var builtinIcons: ({
audio: qsTr("Toggle audio"),
mic: qsTr("Toggle microphone"),
settings: qsTr("Open settings"),
dnd: qsTr("Toggle Do-Not-Disturb"),
gameMode: qsTr("Toggle game mode"),
bluetooth: qsTr("Toggle bluetooth"),
wifi: qsTr("Toggle Wi-Fi")
})
isSubPage: true
title: qsTr("Sidebar")
@@ -44,5 +54,59 @@ PageBase {
onMoved: v => Config.sidebar.dragThreshold = v
}
SectionHeader {
text: qsTr("Quick toggles")
}
ListEditor {
function labelFor(item: var): string {
const prettyName = root.builtinIcons[item.id];
if (prettyName)
return prettyName;
const label = item.id.replace(/([A-Z])/g, " $1");
return label.charAt(0).toUpperCase() + label.slice(1).toLowerCase();
}
function toggledFor(item: var): bool {
return item.enabled;
}
first: true
values: Config.utilities.quickToggles.values
z: 1
onItemMoved: (from, to) => Config.utilities.quickToggles.move(from, to)
onItemRemoved: index => Config.utilities.quickToggles.remove(index)
onItemToggled: (index, checked) => Config.utilities.quickToggles.at(index).enabled = checked
}
DialogSelectButton {
id: addItemContainer
acceptLabel: qsTr("Add")
enabled: Object.keys(model).length > 0
header: qsTr("Add new entry")
icon: "add"
label: qsTr("Add entry")
model: {
const present = new Set(Config.utilities.quickToggles.values.map(item => item.id));
return Object.keys(root.builtinIcons).filter(id => !present.has(id)).map(id => ({
id: id,
label: root.builtinIcons[id]
}));
}
rootParent: root.flickable
onAccepted: {
if (!selectedItem)
return;
Config.utilities.quickToggles.insert({
id: selectedItem,
enabled: true
});
}
}
}
}
+13
View File
@@ -1,5 +1,8 @@
#pragma once
#include "configobject.hpp"
#include "configlist.hpp"
#include <QVariantList>
#include <QStringList>
#include <qqmlintegration.h>
@@ -58,6 +61,16 @@ class Utilities : public ConfigObject {
CONFIG_SUBOBJECT(UtilitiesSizes, sizes)
CONFIG_SUBOBJECT(Toasts, toasts)
CONFIG_SUBOBJECT(Vpn, vpn)
CONFIG_LIST(
EntryList,
quickToggles,
{LIST_ENTRY(dnd, true),
LIST_ENTRY(wifi, true),
LIST_ENTRY(settings, true),
LIST_ENTRY(bluetooth, true),
LIST_ENTRY(mic, true),
LIST_ENTRY(audio, true),
LIST_ENTRY(gameMode, true)})
public:
explicit Utilities(QObject* parent = nullptr)